From a0aad5a43bb631a97dd45cf1a3899f88adb25ed7 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 6 Dec 2018 18:25:26 -0500 Subject: Fix GH issue #3241 - Support -compatability_version and -current_version flags propagating to linker for shared libraries. Derive them from SHLIBVERSION if not independantly specified --- src/engine/SCons/Tool/applelink.py | 14 ++++--- src/engine/SCons/Tool/applelink.xml | 8 ++-- test/LINK/applelink.py | 48 +++++++++++++++++++++- .../applelink_image/SConstruct_CurVers_CompatVers | 23 +++++++++++ 4 files changed, 82 insertions(+), 11 deletions(-) create mode 100644 test/LINK/applelink_image/SConstruct_CurVers_CompatVers diff --git a/src/engine/SCons/Tool/applelink.py b/src/engine/SCons/Tool/applelink.py index c332fc2..cb7cfb6 100644 --- a/src/engine/SCons/Tool/applelink.py +++ b/src/engine/SCons/Tool/applelink.py @@ -43,7 +43,7 @@ from . import link class AppleLinkInvalidCurrentVersionException(Exception): pass -class AppleLinkInvalidCompatibityVersionException(Exception): +class AppleLinkInvalidCompatibilityVersionException(Exception): pass @@ -93,9 +93,9 @@ def _applelib_check_valid_version(version_string): """ parts = version_string.split('.') if len(parts) > 3: - return False, "Version string has too many periods" + return False, "Version string has too many periods [%s]"%version_string if len(parts) <= 0: - return False, "Version string unspecified" + return False, "Version string unspecified [%s]"%version_string for (i, p) in enumerate(parts): try: @@ -120,7 +120,6 @@ def _applelib_currentVersionFromSoVersion(source, target, env, for_signature): else: return "" - print("Version_String:%s"%version_string) version_string = ".".join(version_string.split('.')[:3]) valid, reason = _applelib_check_valid_version(version_string) @@ -144,7 +143,7 @@ def _applelib_compatVersionFromSoVersion(source, target, env, for_signature): valid, reason = _applelib_check_valid_version(version_string) if not valid: - raise AppleLinkInvalidCompatibityVersionException(reason) + raise AppleLinkInvalidCompatibilityVersionException(reason) return "-Wl,-compatibility_version,%s" % version_string @@ -182,6 +181,11 @@ def generate(env): env['LDMODULEFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -bundle') env['LDMODULECOM'] = '$LDMODULE -o ${TARGET} $LDMODULEFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' + # + env['__SHLIBVERSIONFLAGS'] = '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}' + + + def exists(env): return env['PLATFORM'] == 'darwin' diff --git a/src/engine/SCons/Tool/applelink.xml b/src/engine/SCons/Tool/applelink.xml index c7c6d5b..c3346db 100644 --- a/src/engine/SCons/Tool/applelink.xml +++ b/src/engine/SCons/Tool/applelink.xml @@ -59,8 +59,8 @@ See its __doc__ string for a discussion of the format. The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and - 255, Z can be omitted or between 1 and 255. This value will be set to &cv-link-SHLIBVERSION; if not - specified. + 255, Z can be omitted or between 1 and 255. This value will be derived from &cv-link-SHLIBVERSION; if not + specified. The lowest digit will be dropped and replaced by a 0. See MacOS's ld manpage for more details @@ -76,8 +76,8 @@ See its __doc__ string for a discussion of the format. The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and - 255, Z can be omitted or between 1 and 255. This value will be derived from &cv-link-SHLIBVERSION; if not - specified. The lowest digit will be dropped and replaced by a 0. + 255, Z can be omitted or between 1 and 255. This value will be set to &cv-link-SHLIBVERSION; if not + specified. See MacOS's ld manpage for more details diff --git a/test/LINK/applelink.py b/test/LINK/applelink.py index 36b4bf2..b548390 100644 --- a/test/LINK/applelink.py +++ b/test/LINK/applelink.py @@ -29,15 +29,59 @@ import os import TestSCons _python_ = TestSCons._python_ -_exe = TestSCons._exe +_exe = TestSCons._exe test = TestSCons.TestSCons() - +test.verbose_set(1) # Test issue # 2580 test.dir_fixture('applelink_image') test.run(arguments='-f SConstruct_gh2580 -Q -n', stdout='gcc -o foo.o -c -Fframeworks foo.c\n') +# Now test combinations of SHLIBVERSION, APPLELINK_CURRENT_VERSION, APPLELINK_COMPATIBILITY_VERSION + + +for SHLIBVERSION, APPLELINK_CURRENT_VERSION, APPLELINK_COMPATIBILITY_VERSION, should_error in [ + ('1.2.3', '', '', False), + ('1.2.3', '9.9.9', '9.9.0', False), + ('99999.2.3', '', '', 'AppleLinkInvalidCurrentVersionException'), + ('1.2.3', '9.9.999', '9.9.0', 'AppleLinkInvalidCurrentVersionException'), + ('1.2.3', '9.9.9', '9.999.0', 'AppleLinkInvalidCompatibilityVersionException'), + ('1.2.3', '9.9.9', '99999.99.0', 'AppleLinkInvalidCompatibilityVersionException'), +]: + if not APPLELINK_CURRENT_VERSION: + APPLELINK_CURRENT_VERSION = SHLIBVERSION + if not APPLELINK_COMPATIBILITY_VERSION: + APPLELINK_COMPATIBILITY_VERSION = '.'.join(APPLELINK_CURRENT_VERSION.split('.', 2)[:2] + ['0']) + + if not should_error: + expected_stdout = r"^.+ -dynamiclib -Wl,-current_version,{APPLELINK_CURRENT_VERSION} -Wl,-compatibility_version,{APPLELINK_COMPATIBILITY_VERSION}.+".format( + **locals()) + expected_stderr = None + expected_status = 0 + else: + expected_stdout = None + expected_stderr = r"^.+{should_error}.+".format(**locals()) + expected_status = 2 + + test.run( + arguments='-f SConstruct_CurVers_CompatVers SHLIBVERSION={SHLIBVERSION} APPLELINK_CURRENT_VERSION={APPLELINK_CURRENT_VERSION} APPLELINK_COMPATIBILITY_VERSION={APPLELINK_COMPATIBILITY_VERSION}'.format(**locals()), + stdout=expected_stdout, + stderr=expected_stderr, + match=TestSCons.match_re_dotall, + status=expected_status) + + if not should_error: + # Now run otool -L to get the compat and current version info and verify it's correct in the library. + # We expect output such as this + # libfoo.1.2.3.dylib: + # > libfoo.1.2.3.dylib (compatibility version 1.1.99, current version 9.9.9) + # > /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4) + otool_output = "libfoo.{SHLIBVERSION}.dylib:\n\tlibfoo.{SHLIBVERSION}.dylib (compatibility version {APPLELINK_COMPATIBILITY_VERSION}, current version {APPLELINK_CURRENT_VERSION})\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)\n".format( + **locals()) + + test.run(program='/usr/bin/otool', arguments='-L libfoo.%s.dylib' % SHLIBVERSION, stdout=otool_output) + test.pass_test() # Local Variables: diff --git a/test/LINK/applelink_image/SConstruct_CurVers_CompatVers b/test/LINK/applelink_image/SConstruct_CurVers_CompatVers new file mode 100644 index 0000000..b699ad8 --- /dev/null +++ b/test/LINK/applelink_image/SConstruct_CurVers_CompatVers @@ -0,0 +1,23 @@ + + +vars = Variables(None, ARGUMENTS) +vars.Add('SHLIBVERSION', 'Set the SHLIBVERSION', 0) +vars.Add('APPLELINK_CURRENT_VERSION', 'Set APPLELINK_CURRENT_VERSION', 0) +vars.Add('APPLELINK_COMPATIBILITY_VERSION', 'Set APPLELINK_COMPATIBILITY_VERSION', 0) + +env = Environment(variables = vars, tools=['gcc', 'applelink']) + +obj = env.SharedObject('foo.c') + +# sl = env.SharedLibrary('foo', obj) + +sl = env.SharedLibrary('foo', obj) +lm = env.LoadableModule('fool', obj) + +env.InstallVersionedLib(target='#/install', + source=sl) + +env.InstallVersionedLib(target='#/install', + source=lm) + +print("SHLIBVERSION=%s"%env['SHLIBVERSION']) -- cgit v0.12