summaryrefslogtreecommitdiff
path: root/recipes/openssl.recipe
blob: dd1827c27ad420f2fb5bd2f42a8bf21c77c633ed (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# -*- Mode: Python -*- vi:si:et:sw=4:sts=4:ts=4:syntax=python
from cerbero.build.build import modify_environment
from cerbero.tools.libtool import LibtoolLibrary
from cerbero.utils import shell, messages

class Recipe(recipe.Recipe):
    name = 'openssl'
    # Note: openssl helpfully moves tarballs somewhere else (old/x.y.z/)
    # whenever a new release comes out, so make sure to mirror to fdo when
    # bumping the release!
    version = '1.1.1h'
    licenses = [{License.OPENSSL: ['LICENSE']}]
    stype = SourceType.TARBALL
    url = 'https://ftp.openssl.org/source/{0}-{1}.tar.gz'.format(name, version)
    tarball_checksum = '5c9ca8774bd7b03e5784f26ae9e9e6d749c9da2438545077e6b3d755a06595d9'
    deps = ['ca-certificates', 'zlib']
    # Parallel make fails randomly due to undefined macros, probably races
    allow_parallel_build = False
    # Configure script is perl, not shell
    config_sh_needs_shell = False
    # Can build for MSVC and UWP
    can_msvc = True

    patches = [
        # Portable prefix with SSL certs
        'openssl/0001-Load-ca-certificate.crt-from-PREFIX-etc-ssl-on-macOS.patch',
        # MSVC and UWP support
        'openssl/0001-windows-makefile.tmpl-Generate-and-install-pkgconfig.patch',
        'openssl/0002-windows-makefile.tmpl-Fix-ONECORE-build.patch',
        'openssl/0003-windows-makefile.tmpl-Do-not-prefix-import-libraries.patch',
        # https://github.com/openssl/openssl/pull/12400
        'openssl/0001-crypto-win-Don-t-use-disallowed-APIs-on-UWP.patch',
        'openssl/0002-win-onecore-Build-with-APPCONTAINER-for-UWP-compat.patch',
        # https://github.com/openssl/openssl/pull/13476 '1.1.1i'
        'openssl/0001-Add-darwin64-arm64-cc-build-target.patch',
    ]

    files_bins = ['openssl']
    files_libs = ['libcrypto', 'libssl']
    files_devel = ['include/openssl', 'lib/pkgconfig/openssl.pc',
                   'lib/pkgconfig/libssl.pc', 'lib/pkgconfig/libcrypto.pc']

    def _get_openssl_platform(self):
        # map platforms
        if self.config.target_platform == Platform.IOS:
            if self.config.target_arch == Architecture.ARMv7:
                return 'BSD-generic32'
            if self.config.target_arch == Architecture.ARMv7S:
                return 'BSD-generic32'
            if self.config.target_arch == Architecture.X86:
                return 'BSD-generic32'
            if self.config.target_arch == Architecture.X86_64:
                return 'BSD-generic64'
            if self.config.target_arch == Architecture.ARM64:
                return 'BSD-generic64'
            raise InvalidRecipeError(self, "Unknown iOS platform")
        if self.config.target_platform == Platform.ANDROID:
            self.make += ['CROSS_SYSROOT=' + self.config.sysroot]
            if self.config.target_arch == Architecture.ARM:
                return 'android-arm'
            if self.config.target_arch == Architecture.ARMv7:
                return 'android-arm'
            if self.config.target_arch == Architecture.ARM64:
                return 'android-arm64'
            if self.config.target_arch == Architecture.X86:
                return 'android-x86'
            if self.config.target_arch == Architecture.X86_64:
                return 'android-x86_64'
            raise InvalidRecipeError(self, "Unknown Android platform")
        if self.config.target_platform == Platform.DARWIN:
            if self.config.target_arch == Architecture.X86:
                return 'darwin-i386-cc'
            if self.config.target_arch == Architecture.X86_64:
                return 'darwin64-x86_64-cc'
            if self.config.target_arch == Architecture.ARM64:
                return 'darwin64-arm64-cc'
            raise InvalidRecipeError(self, "Unknown macOS platform")
        if self.config.target_platform == Platform.LINUX:
            if self.config.target_arch == Architecture.X86:
                return 'linux-elf'
            if self.config.target_arch == Architecture.X86_64:
                return 'linux-x86_64'
            if self.config.target_arch == Architecture.ARM:
                return 'linux-armv4'
            if self.config.target_arch == Architecture.ARMv7:
                return 'linux-armv4'
            if self.config.target_arch == Architecture.ARM64:
                return 'linux-aarch64'
            raise InvalidRecipeError(self, "Unknown Linux platform")
        if self.config.target_platform == Platform.WINDOWS:
            if self.using_uwp():
                if self.config.target_arch == Architecture.X86:
                    return 'VC-WIN32-ONECORE'
                if self.config.target_arch == Architecture.X86_64:
                    return 'VC-WIN64A-ONECORE'
                if self.config.target_arch == Architecture.ARM:
                    return 'VC-WIN32-ARM'
                if self.config.target_arch == Architecture.ARMv7:
                    return 'VC-WIN32-ARM'
                if self.config.target_arch == Architecture.ARM64:
                    return 'VC-WIN64-ARM'
            elif self.using_msvc():
                if self.config.target_arch == Architecture.X86:
                    return 'VC-WIN32'
                if self.config.target_arch == Architecture.X86_64:
                    return 'VC-WIN64A'
            else:
                if self.config.target_arch == Architecture.X86:
                    return 'mingw'
                if self.config.target_arch == Architecture.X86_64:
                    return 'mingw64'
            raise InvalidRecipeError(self, "Unknown Windows platform")
        raise InvalidRecipeError(self, "Unknown target platform {}"
                                 .format(self.config.target_platform))

    def prepare(self):
        self.openssl_platform = self._get_openssl_platform()
        cflags = self.get_env('CFLAGS')
        ldflags = self.get_env('LDFLAGS')

        if self.using_msvc():
            # Gets converted to C:/MinGW/msys/1.0/utf-8 by MSYS somehow, so
            # just remove it. We only need this for gstreamer sources anyway.
            cflags = cflags.replace('/utf-8', '')
            # If we don't unset these, they override values set by openssl's makefile
            self.set_env('CFLAGS')
            self.set_env('CPPFLAGS')
            self.set_env('CXXFLAGS')
            self.set_env('LDFLAGS')
            # Building with MSVC uses nmake, not make
            self.make = ['nmake', 'CFLAG=' + cflags, 'LDFLAG=' + ldflags]
            self.make_install = ['nmake', 'install_sw']
        else:
            cflags += '-fPIC -DOPENSSL_PIC'
            ldflags += '-fPIC'
            ranlib = self.get_env('RANLIB')
            ar = self.get_env('AR')
            # Need to add CFLAGS to CC because CFLAG is not used everywhere in the
            # build, and we can't pass arguments via Configure because on Darwin,
            # Configure reads the `-arch x86_64` as meaning that you want to use
            # `x86_64` as the platform, and errors out about a redefined platform.
            cc = self.get_env('CC') + ' ' + self.get_env('CFLAGS')
            ld = self.get_env('LD') + ' ' + self.get_env('LDFLAGS')
            # NOTE: CFLAG and LDFLAG are not typos!
            self.make += ['AR=' + ar, 'RANLIB=' + ranlib, 'CC=' + cc, 'LD=' + ld,
                          'CFLAG=' + cflags, 'LDFLAG=' + ldflags]
            self.make_install = ['make', 'install_sw', 'RANLIB=' + ranlib]

        # We probably don't need and can't use the tools on these platforms
        if self.config.target_platform in (Platform.IOS, Platform.ANDROID):
            self.make += ['build_libs', 'openssl.pc', 'libssl.pc', 'libcrypto.pc']
            self.make_install = ['make', 'install_dev', 'RANLIB=' + ranlib]

        if self.config.platform == Platform.WINDOWS:
            # Msys ships with a too-old perl, so we modify PATH to use the
            # mingw-perl that was downloaded and installed by bootstrap.
            openssl_path = os.path.join(self.config.mingw_perl_prefix, 'bin')
            self.prepend_env('PATH', openssl_path, sep=';')
            # Ensure that our Perl's File/Spec.pm uses backward slashes when
            # building for MSVC and forward-slashes when building for MinGW.
            # The vars for the MinGW case are automatically set by the MSYS
            # terminal, but they might get overriden by something, which will
            # cause Perl to use backward slashes and fail
            # `Configurations/unix-checker.pm` on configure.
            self.set_env('MSYSTEM', 'MINGW32')
            if self.using_msvc():
                self.set_env('TERM', 'dumb')
            else:
                self.set_env('TERM', 'cygwin')


    @modify_environment
    async def configure(self):
        if self.config.platform == Platform.WINDOWS:
            perl, found, newer = shell.check_tool_version('perl','5.10.0', env=self.env)
            m = 'please run bootstrap again'
            if newer is None:
                raise FatalError('Perl not found, ' + m)
            if newer is False:
                raise FatalError('Configured Perl {!r} is {} which is too old, {}'
                                 ''.format(perl, found, m))
        # OpenSSL guesses the libdir incorrectly on x86_64
        config_sh = 'perl ./Configure --prefix=' + self.config.prefix + \
            ' --libdir=lib' + self.config.lib_suffix + '  no-makedepend '
        if self.config.target_platform == Platform.IOS:
            # Note: disable 'no-devcryptoeng' when we finally target the
            # *real* ios configuration targets
            config_sh += ' no-shared no-dso no-async no-devcryptoeng '
            # Undefined symbols in aesni_* in libcrypto.a only on x86_64
            if self.config.target_arch == Architecture.X86_64:
                config_sh += ' no-asm '
        else:
            config_sh += ' shared '

        # ssl3 is needed by sphinx which is used by gst-validate, which tries
        # to use this libssl and fails with undefined symbols. md2 is needed by
        # librpmio.so.8, which is used during package generation on Fedora.
        if self.config.target_platform == Platform.LINUX:
            config_sh += ' enable-ssl3 enable-ssl3-method enable-md2 '

        if self.using_msvc():
            if self.config.variants.vscrt == 'md':
                config_sh += ' --release '
            elif self.config.variants.vscrt == 'mdd':
                config_sh += ' --debug '
            else:
                raise AssertionError

        await shell.async_call(config_sh + self.openssl_platform, self.build_dir,
                               logfile=self.logfile, env=self.env)

    def post_install(self):
        # XXX: Don't forget to update this when the soname is bumped!
        # We don't build shared libraries on iOS as the build system
        # of openssl is broken and iOS does not support them anyway.
        if self.config.target_platform != Platform.IOS:
            libtool_la = LibtoolLibrary('ssl', 1, 1, 0, self.config.libdir,
                                        self.config.target_platform,
                                        deps=['crypto'])
            libtool_la.save()
            libtool_la = LibtoolLibrary('crypto', 1, 1, 0, self.config.libdir,
                                        self.config.target_platform)
            libtool_la.save()
        super().post_install()