Skip to content

Commit 1aa0822

Browse files
authored
AWS_CRT_BUILD_FORCE_STATIC_LIBS (#596)
**Issue:** #593 introduced env-var, `AWS_CRT_BUILD_USE_SYSTEM_LIBS=1`, but it didn't work unless those system libs were built statically. **Diagnosis:** The reason it didn't work is: there's a hack in [setup.py](https://github.com/awslabs/aws-crt-python/blob/2dae492d57b40c68839f2ecd7867bea34e6f9f1a/setup.py#L339-L348) that forces dependencies to be linked statically on Unix variants (excluding macOS). It worked when I tested on macOS because the hack isn't applied there. The reason for the hack is: in Brazil (internal AWS build system), dependencies are available as both static and dynamic libs. But we prefer to link the static ones so that, if a python application is packaged for AWS lambda, the developer has fewer files they need to chase down and copy into their .zip package. **Description of changes:** Don't force static libs to be used unless `AWS_CRT_BUILD_FORCE_STATIC_LIBS=1` (new env-var). Otherwise (by default), the linker will use whatever version of the lib is available (if both are available, linkers generally prefer dynamic). This only applies to non-OS dependencies, we won't force libc to be linked statically. It's unlikely this env-var will be used anywhere except Brazil.
1 parent 7e52d8a commit 1aa0822

File tree

2 files changed

+37
-30
lines changed

2 files changed

+37
-30
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ set environment variable `AWS_CRT_BUILD_USE_SYSTEM_LIBS=1` while building from s
7272
AWS_CRT_BUILD_USE_SYSTEM_LIBS=1 python3 -m pip install .
7373
```
7474

75+
If these dependencies are available as both static and shared libs, you can force the static ones to be used by setting: `AWS_CRT_BUILD_FORCE_STATIC_LIBS=1`
76+
7577
## Mac-Only TLS Behavior
7678

7779
Please note that on Mac, once a private key is used with a certificate, that certificate-key pair is imported into the Mac Keychain. All subsequent uses of that certificate will use the stored private key and ignore anything passed in programmatically. Beginning in v0.6.2, when a stored private key from the Keychain is used, the following will be logged at the "info" log level:

setup.py

+35-30
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,20 @@ def get_cmake_path():
140140

141141
def using_system_libs():
142142
"""If true, don't build any dependencies. Use the libs that are already on the system."""
143-
return os.getenv('AWS_CRT_BUILD_USE_SYSTEM_LIBS') == '1'
143+
return (os.getenv('AWS_CRT_BUILD_USE_SYSTEM_LIBS') == '1'
144+
or not os.path.exists(os.path.join(PROJECT_DIR, 'crt', 'aws-c-common', 'CMakeLists.txt')))
144145

145146

146147
def using_system_libcrypto():
147148
"""If true, don't build AWS-LC. Use the libcrypto that's already on the system."""
148149
return using_system_libs() or os.getenv('AWS_CRT_BUILD_USE_SYSTEM_LIBCRYPTO') == '1'
149150

150151

152+
def forcing_static_libs():
153+
"""If true, force libs to be linked statically."""
154+
return os.getenv('AWS_CRT_BUILD_FORCE_STATIC_LIBS') == '1'
155+
156+
151157
class AwsLib:
152158
def __init__(self, name, extra_cmake_args=[], libname=None):
153159
self.name = name
@@ -156,12 +162,11 @@ def __init__(self, name, extra_cmake_args=[], libname=None):
156162

157163

158164
# The extension depends on these libs.
159-
# They're built along with the extension.
165+
# They're built along with the extension (unless using_system_libs() is True)
160166
AWS_LIBS = []
161167
if sys.platform != 'darwin' and sys.platform != 'win32':
162-
if not using_system_libcrypto():
163-
# aws-lc produces libcrypto.a
164-
AWS_LIBS.append(AwsLib('aws-lc', libname='crypto'))
168+
# aws-lc produces libcrypto.a
169+
AWS_LIBS.append(AwsLib('aws-lc', libname='crypto'))
165170
AWS_LIBS.append(AwsLib('s2n'))
166171
AWS_LIBS.append(AwsLib('aws-c-common'))
167172
AWS_LIBS.append(AwsLib('aws-c-sdkutils'))
@@ -296,9 +301,7 @@ def _build_dependencies(self):
296301

297302
def run(self):
298303
if using_system_libs():
299-
print("Skip building dependencies, using system libs.")
300-
elif not os.path.exists(os.path.join(PROJECT_DIR, 'crt', 'aws-c-common', 'CMakeLists.txt')):
301-
print("Skip building dependencies, source not found.")
304+
print("Skip building dependencies")
302305
else:
303306
self._build_dependencies()
304307

@@ -345,38 +348,40 @@ def awscrt_ext():
345348
extra_link_args += ['-framework', 'Security']
346349

347350
else: # unix
348-
# linker will prefer shared libraries over static if it can find both.
349-
# force linker to choose static variant by using using
350-
# "-l:libaws-c-common.a" syntax instead of just "-laws-c-common".
351-
#
352-
# This helps AWS developers creating Lambda applications from Brazil.
353-
# In Brazil, both shared and static libs are available.
354-
# But Lambda requires all shared libs to be explicitly packaged up.
355-
# So it's simpler to link them in statically and have less runtime dependencies.
356-
libraries = [':lib{}.a'.format(x) for x in libraries]
351+
if forcing_static_libs():
352+
# linker will prefer shared libraries over static if it can find both.
353+
# force linker to choose static variant by using
354+
# "-l:libaws-c-common.a" syntax instead of just "-laws-c-common".
355+
#
356+
# This helps AWS developers creating Lambda applications from Brazil.
357+
# In Brazil, both shared and static libs are available.
358+
# But Lambda requires all shared libs to be explicitly packaged up.
359+
# So it's simpler to link them in statically and have less runtime dependencies.
360+
#
361+
# Don't apply this trick to dependencies that are always on the OS (e.g. librt)
362+
libraries = [':lib{}.a'.format(x) for x in libraries]
357363

358364
# OpenBSD doesn't have librt; functions are found in libc instead.
359365
if not sys.platform.startswith('openbsd'):
360366
libraries += ['rt']
361367

362-
if using_system_libcrypto():
363-
libraries += ['crypto']
364-
else:
365-
# hide the symbols from libcrypto.a
366-
# this prevents weird crashes if an application also ends up using
367-
# libcrypto.so from the system's OpenSSL installation.
368-
extra_link_args += ['-Wl,--exclude-libs,libcrypto.a']
369-
370-
# OpenBSD 7.4+ defaults to linking with --execute-only, which is bad for AWS-LC.
371-
# See: https://github.com/aws/aws-lc/blob/4b07805bddc55f68e5ce8c42f215da51c7a4e099/CMakeLists.txt#L44-L53
372-
# (If AWS-LC's CMakeLists.txt removes these lines in the future, we can remove this hack here as well)
373-
if sys.platform.startswith('openbsd'):
368+
# hide the symbols from libcrypto.a
369+
# this prevents weird crashes if an application also ends up using
370+
# libcrypto.so from the system's OpenSSL installation.
371+
# Do this even if using system libcrypto, since it could still be a static lib.
372+
extra_link_args += ['-Wl,--exclude-libs,libcrypto.a']
373+
374+
# OpenBSD 7.4+ defaults to linking with --execute-only, which is bad for AWS-LC.
375+
# See: https://github.com/aws/aws-lc/blob/4b07805bddc55f68e5ce8c42f215da51c7a4e099/CMakeLists.txt#L44-L53
376+
# (If AWS-LC's CMakeLists.txt removes these lines in the future, we can remove this hack here as well)
377+
if sys.platform.startswith('openbsd'):
378+
if not using_system_libcrypto():
374379
extra_link_args += ['-Wl,--no-execute-only']
375380

376381
# FreeBSD doesn't have execinfo as a part of libc like other Unix variant.
377382
# Passing linker flag to link execinfo properly
378383
if sys.platform.startswith('freebsd'):
379-
extra_link_args += ['-lexecinfo']
384+
libraries += ['execinfo']
380385

381386
# python usually adds -pthread automatically, but we've observed
382387
# rare cases where that didn't happen, so let's be explicit.

0 commit comments

Comments
 (0)