1 """SCons.Tool.applelink
3 Tool-specific initialization for Apple's gnu-like linker.
5 There normally shouldn't be any need to import this module directly.
6 It will usually be imported through the generic SCons.Tool.Tool()
14 # Copyright The SCons Foundation
16 # Permission is hereby granted, free of charge, to any person obtaining
17 # a copy of this software and associated documentation files (the
18 # "Software"), to deal in the Software without restriction, including
19 # without limitation the rights to use, copy, modify, merge, publish,
20 # distribute, sublicense, and/or sell copies of the Software, and to
21 # permit persons to whom the Software is furnished to do so, subject to
22 # the following conditions:
24 # The above copyright notice and this permission notice shall be included
25 # in all copies or substantial portions of the Software.
27 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
28 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
29 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 # Even though the Mac is based on the GNU toolchain, it doesn't understand
37 # the -rpath option, so we use the "link" tool instead of "gnulink".
38 from SCons
.Util
import CLVar
39 from SCons
.Errors
import UserError
42 # User programmatically describes how SHLIBVERSION maps to values for compat/current.
43 _APPLELIB_MAX_VERSION_VALUES
= (65535, 255, 255)
46 class AppleLinkInvalidCurrentVersionException(Exception):
50 class AppleLinkInvalidCompatibilityVersionException(Exception):
54 def _applelib_check_valid_version(version_string
):
56 Check that the version # is valid.
59 where Y either not specified or 0-255
60 where Z either not specified or 0-255
61 :param version_string:
64 parts
= version_string
.split('.')
66 return False, "Version string has too many periods [%s]" % version_string
68 return False, "Version string unspecified [%s]" % version_string
70 for (i
, p
) in enumerate(parts
):
74 return False, "Version component %s (from %s) is not a number" % (p
, version_string
)
75 if p_i
< 0 or p_i
> _APPLELIB_MAX_VERSION_VALUES
[i
]:
76 return False, "Version component %s (from %s) is not valid value should be between 0 and %d" % (
77 p
, version_string
, _APPLELIB_MAX_VERSION_VALUES
[i
])
82 def _applelib_currentVersionFromSoVersion(source
, target
, env
, for_signature
) -> str:
84 A generator function to create the -Wl,-current_version flag if needed.
85 If env['APPLELINK_NO_CURRENT_VERSION'] contains a true value no flag will be generated
86 Otherwise if APPLELINK_CURRENT_VERSION is not specified, env['SHLIBVERSION']
93 :return: A string providing the flag to specify the current_version of the shared library
95 if env
.get('APPLELINK_NO_CURRENT_VERSION', False):
97 elif env
.get('APPLELINK_CURRENT_VERSION', False):
98 version_string
= env
['APPLELINK_CURRENT_VERSION']
99 elif env
.get('SHLIBVERSION', False):
100 version_string
= env
['SHLIBVERSION']
104 version_string
= ".".join(version_string
.split('.')[:3])
106 valid
, reason
= _applelib_check_valid_version(version_string
)
108 raise AppleLinkInvalidCurrentVersionException(reason
)
110 return "-Wl,-current_version,%s" % version_string
113 def _applelib_compatVersionFromSoVersion(source
, target
, env
, for_signature
) -> str:
115 A generator function to create the -Wl,-compatibility_version flag if needed.
116 If env['APPLELINK_NO_COMPATIBILITY_VERSION'] contains a true value no flag will be generated
117 Otherwise if APPLELINK_COMPATIBILITY_VERSION is not specified
118 the first two parts of env['SHLIBVERSION'] will be used with a .0 appended.
123 :param for_signature:
124 :return: A string providing the flag to specify the compatibility_version of the shared library
126 if env
.get('APPLELINK_NO_COMPATIBILITY_VERSION', False):
128 elif env
.get('APPLELINK_COMPATIBILITY_VERSION', False):
129 version_string
= env
['APPLELINK_COMPATIBILITY_VERSION']
130 elif env
.get('SHLIBVERSION', False):
131 version_string
= ".".join(env
['SHLIBVERSION'].split('.')[:2] + ['0'])
135 if version_string
is None:
138 valid
, reason
= _applelib_check_valid_version(version_string
)
140 raise AppleLinkInvalidCompatibilityVersionException(reason
)
142 return "-Wl,-compatibility_version,%s" % version_string
144 def _applelib_soname(target
, source
, env
, for_signature
) -> str:
146 Override default _soname() function from SCons.Tools.linkCommon.SharedLibrary.
147 Apple's file naming for versioned shared libraries puts the version string before
148 the shared library suffix (.dylib), instead of after.
151 # Now verify that SOVERSION is not also set as that is not allowed
152 if "SOVERSION" in env
:
154 "Ambiguous library .so naming, both SONAME: %s and SOVERSION: %s are defined. "
155 "Only one can be defined for a target library."
156 % (env
["SONAME"], env
["SOVERSION"])
160 return "$SHLIBPREFIX$_get_shlib_stem$_SHLIBSOVERSION${SHLIBSUFFIX}"
163 def generate(env
) -> None:
164 """Add Builders and construction variables for applelink to an
168 env
['FRAMEWORKPATHPREFIX'] = '-F'
169 env
['_FRAMEWORKPATH'] = '${_concat(FRAMEWORKPATHPREFIX, FRAMEWORKPATH, "", __env__, RDirs)}'
171 env
['_FRAMEWORKS'] = '${_concat("-framework ", FRAMEWORKS, "", __env__)}'
172 env
['LINKCOM'] = env
['LINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS'
173 env
['SHLINKFLAGS'] = CLVar('$LINKFLAGS -dynamiclib')
174 env
['SHLINKCOM'] = env
['SHLINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS'
176 env
['_APPLELINK_CURRENT_VERSION'] = _applelib_currentVersionFromSoVersion
177 env
['_APPLELINK_COMPATIBILITY_VERSION'] = _applelib_compatVersionFromSoVersion
178 env
['_SHLIBVERSIONFLAGS'] = '$_APPLELINK_CURRENT_VERSION $_APPLELINK_COMPATIBILITY_VERSION '
179 env
['_LDMODULEVERSIONFLAGS'] = '$_APPLELINK_CURRENT_VERSION $_APPLELINK_COMPATIBILITY_VERSION '
181 # override the default for loadable modules, which are different
182 # on OS X than dynamic shared libs. echoing what XCode does for
184 env
['LDMODULEPREFIX'] = ''
185 env
['LDMODULESUFFIX'] = ''
186 env
['LDMODULEFLAGS'] = CLVar('$LINKFLAGS -bundle')
187 env
['LDMODULECOM'] = '$LDMODULE -o ${TARGET} $LDMODULEFLAGS' \
188 ' $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS'
192 env
['_SHLIBSUFFIX'] = '${_SHLIBVERSION}${SHLIBSUFFIX}'
194 env
['__SHLIBVERSIONFLAGS'] = '${__lib_either_version_flag(__env__,' \
195 '"SHLIBVERSION","_APPLELINK_CURRENT_VERSION", "_SHLIBVERSIONFLAGS")}'
196 env
['__LDMODULEVERSIONFLAGS'] = '${__lib_either_version_flag(__env__,' \
197 '"LDMODULEVERSION","_APPLELINK_CURRENT_VERSION", "_LDMODULEVERSIONFLAGS")}'
199 env
["_SHLIBSONAME"] = _applelib_soname
203 return env
['PLATFORM'] == 'darwin'
207 # indent-tabs-mode:nil
209 # vim: set expandtab tabstop=4 shiftwidth=4: