summaryrefslogtreecommitdiff
path: root/winbuild/pycurl.py
blob: 975de7757a8c8199caf0bb77143d5509703bfef3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import os.path, shutil, zipfile
from .builder import *
from .utils import *
from .curl import *

class PycurlBuilder(Builder):
    def __init__(self, **kwargs):
        self.python_release = kwargs.pop('python_release')
        super(PycurlBuilder, self).__init__(**kwargs)
        # vc_version is specified externally for bconf/BuildConfig
        assert self.bconf.vc_version == PYTHON_VC_VERSIONS[self.python_release]

    @property
    def python_path(self):
        if self.bconf.build_wheels:
            python_path = os.path.join(self.bconf.archives_path, 'venv-%s-%s' % (self.python_release, self.bconf.bitness), 'scripts', 'python')
        else:
            python_path = PythonBinary(self.python_release, self.bconf.bitness).executable_path
        return python_path

    @property
    def platform_indicator(self):
        platform_indicators = {32: 'win32', 64: 'win-amd64'}
        return platform_indicators[self.bconf.bitness]

    def build(self, targets):
        libcurl_builder = LibcurlBuilder(bconf=self.bconf)
        libcurl_dir = os.path.join(os.path.abspath(libcurl_builder.output_dir_path), 'dist')
        dll_paths = libcurl_builder.dll_paths
        if self.bconf.use_zlib:
            zlib_builder = ZlibBuilder(bconf=self.bconf)
            dll_paths += zlib_builder.dll_paths
        dll_paths = [os.path.abspath(dll_path) for dll_path in dll_paths]
        with in_dir(self.build_dir_name):
            dest_lib_path = 'build/lib.%s-%s' % (self.platform_indicator,
                self.python_release)
            # exists for building additional targets for the same python version
            mkdir_p(dest_lib_path)
            if self.use_dlls:
                for dll_path in dll_paths:
                    shutil.copy(dll_path, dest_lib_path)
            with self.execute_batch() as b:
                b.add("%s setup.py docstrings" % (self.python_path,))
                if self.use_dlls:
                    libcurl_arg = '--use-libcurl-dll'
                else:
                    libcurl_arg = '--libcurl-lib-name=libcurl_a.lib'
                if self.bconf.use_openssl:
                    libcurl_arg += ' --with-openssl'
                    if self.bconf.openssl_version_tuple >= (1, 1):
                        libcurl_arg += ' --openssl-lib-name=""'
                    openssl_builder = OpensslBuilder(bconf=self.bconf)
                    b.add("set include=%%include%%;%s" % openssl_builder.include_path)
                    b.add("set lib=%%lib%%;%s" % openssl_builder.lib_path)
                #if build_wheels:
                    #b.add("call %s" % os.path.join('..', 'venv-%s-%s' % (self.python_release, self.bconf.bitness), 'Scripts', 'activate'))
                if self.bconf.build_wheels:
                    targets = targets + ['bdist_wheel']
                if self.bconf.libcurl_version_tuple >= (7, 60, 0):
                    # As of 7.60.0 libcurl does not include its dependencies into
                    # its static libraries.
                    # libcurl_a.lib in 7.59.0 is 30 mb.
                    # libcurl_a.lib in 7.60.0 is 2 mb.
                    # https://github.com/curl/curl/pull/2474 is most likely culprit.
                    # As a result we need to specify all of the libraries that
                    # libcurl depends on here, plus the library paths,
                    # plus even windows standard libraries for good measure.
                    if self.bconf.use_zlib:
                        zlib_builder = ZlibBuilder(bconf=self.bconf)
                        libcurl_arg += ' --link-arg=/LIBPATH:%s' % zlib_builder.lib_path
                        libcurl_arg += ' --link-arg=zlib.lib'
                    if self.bconf.use_openssl:
                        openssl_builder = OpensslBuilder(bconf=self.bconf)
                        libcurl_arg += ' --link-arg=/LIBPATH:%s' % openssl_builder.lib_path
                        # openssl 1.1
                        libcurl_arg += ' --link-arg=libcrypto.lib'
                        libcurl_arg += ' --link-arg=libssl.lib'
                        libcurl_arg += ' --link-arg=crypt32.lib'
                        libcurl_arg += ' --link-arg=advapi32.lib'
                    if self.bconf.use_cares:
                        cares_builder = CaresBuilder(bconf=self.bconf)
                        libcurl_arg += ' --link-arg=/LIBPATH:%s' % cares_builder.lib_path
                        libcurl_arg += ' --link-arg=libcares.lib'
                    if self.bconf.use_libssh2:
                        libssh2_builder = Libssh2Builder(bconf=self.bconf)
                        libcurl_arg += ' --link-arg=/LIBPATH:%s' % libssh2_builder.lib_path
                        libcurl_arg += ' --link-arg=libssh2.lib'
                    if self.bconf.use_nghttp2:
                        nghttp2_builder = Nghttp2Builder(bconf=self.bconf)
                        libcurl_arg += ' --link-arg=/LIBPATH:%s' % nghttp2_builder.lib_path
                        libcurl_arg += ' --link-arg=nghttp2_static.lib'
                    if self.bconf.vc_version == 'vc9':
                        # this is for normaliz.lib
                        libcurl_builder = LibcurlBuilder(bconf=self.bconf)
                        libcurl_arg += ' --link-arg=/LIBPATH:%s' % libcurl_builder.lib_path
                    # We always use normaliz.lib, but it may come from
                    # "standard" msvc location or from libcurl's lib dir for msvc9
                    libcurl_arg += ' --link-arg=normaliz.lib'
                    libcurl_arg += ' --link-arg=user32.lib'
                b.add("%s setup.py %s --curl-dir=%s %s" % (
                    self.python_path, ' '.join(targets), libcurl_dir, libcurl_arg))
            # Fixing of bizarre paths in created zip archives,
            # no longer relevant because we only keep wheels
            if False and 'bdist' in targets:
                zip_basename_orig = 'pycurl-%s.%s.zip' % (
                    self.bconf.pycurl_version, self.platform_indicator)
                zip_basename_new = 'pycurl-%s.%s-py%s.zip' % (
                    self.bconf.pycurl_version, self.platform_indicator, self.python_release)
                with zipfile.ZipFile('dist/%s' % zip_basename_orig, 'r') as src_zip:
                    with zipfile.ZipFile('dist/%s' % zip_basename_new, 'w') as dest_zip:
                        for name in src_zip.namelist():
                            parts = name.split('/')
                            while True:
                                popped = parts.pop(0)
                                if popped == 'python%s' % self.python_release.dotless or popped.startswith('venv-'):
                                    break
                            assert len(parts) > 0
                            new_name = '/'.join(parts)
                            print('Recompressing %s -> %s' % (name, new_name))

                            member = src_zip.open(name)
                            dest_zip.writestr(new_name, member.read(), zipfile.ZIP_DEFLATED)
    
    @property
    def build_dir_name(self):
        return 'pycurl-%s-py%s-%s' % (self.bconf.pycurl_version, self.python_release, self.bconf.vc_tag)
    
    def prepare_tree(self):
        #fetch('https://dl.bintray.com/pycurl/pycurl/pycurl-%s.tar.gz' % pycurl_version)
        if os.path.exists(self.build_dir_name):
            # shutil.rmtree is incapable of removing .git directory because it contains
            # files marked read-only (tested on python 2.7 and 3.6)
            #shutil.rmtree('pycurl-%s' % config.pycurl_version)
            rm_rf(self.bconf, self.build_dir_name)
        #check_call([tar_path, 'xf', 'pycurl-%s.tar.gz' % pycurl_version])
        shutil.copytree('c:/dev/pycurl', self.build_dir_name)