diff options
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 3 | ||||
-rw-r--r-- | mesonbuild/build.py | 49 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 30 | ||||
-rw-r--r-- | mesonbuild/compilers/d.py | 6 |
4 files changed, 67 insertions, 21 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index acbeed3..6daa939 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2257,7 +2257,8 @@ rule FORTRAN_DEP_HACK%s commands += linker.get_pic_args() # Add -Wl,-soname arguments on Linux, -install_name on OS X commands += linker.get_soname_args(target.prefix, target.name, target.suffix, - target.soversion, isinstance(target, build.SharedModule)) + target.soversion, target.darwin_versions, + isinstance(target, build.SharedModule)) # This is only visited when building for Windows using either GCC or Visual Studio if target.vs_module_defs and hasattr(linker, 'gen_vs_module_defs_args'): commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src)) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 3debeeb..efe58f8 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -83,7 +83,7 @@ known_build_target_kwargs = ( cs_kwargs) known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic'} -known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs'} +known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions'} known_shmod_kwargs = known_build_target_kwargs known_stlib_kwargs = known_build_target_kwargs | {'pic'} known_jar_kwargs = known_exe_kwargs | {'main_class'} @@ -1392,6 +1392,8 @@ class SharedLibrary(BuildTarget): def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): self.soversion = None self.ltversion = None + # Max length 2, first element is compatibility_version, second is current_version + self.darwin_versions = [] self.vs_module_defs = None # The import library this target will generate self.import_filename = None @@ -1518,6 +1520,44 @@ class SharedLibrary(BuildTarget): self.filename = self.filename_tpl.format(self) self.outputs = [self.filename] + @staticmethod + def _validate_darwin_versions(darwin_versions): + try: + if isinstance(darwin_versions, int): + darwin_versions = str(darwin_versions) + if isinstance(darwin_versions, str): + darwin_versions = 2 * [darwin_versions] + if not isinstance(darwin_versions, list): + raise InvalidArguments('Shared library darwin_versions: must be a string, integer,' + 'or a list, not {!r}'.format(darwin_versions)) + if len(darwin_versions) > 2: + raise InvalidArguments('Shared library darwin_versions: list must contain 2 or fewer elements') + if len(darwin_versions) == 1: + darwin_versions = 2 * darwin_versions + for i, v in enumerate(darwin_versions[:]): + if isinstance(v, int): + v = str(v) + if not isinstance(v, str): + raise InvalidArguments('Shared library darwin_versions: list elements ' + 'must be strings or integers, not {!r}'.format(v)) + if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', v): + raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z where ' + 'X, Y, Z are numbers, and Y and Z are optional') + parts = v.split('.') + if len(parts) in (1, 2, 3) and int(parts[0]) > 65535: + raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z ' + 'where X is [0, 65535] and Y, Z are optional') + if len(parts) in (2, 3) and int(parts[1]) > 255: + raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z ' + 'where Y is [0, 255] and Y, Z are optional') + if len(parts) == 3 and int(parts[2]) > 255: + raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z ' + 'where Z is [0, 255] and Y, Z are optional') + darwin_versions[i] = v + except ValueError: + raise InvalidArguments('Shared library darwin_versions: value is invalid') + return darwin_versions + def process_kwargs(self, kwargs, environment): super().process_kwargs(kwargs, environment) @@ -1546,6 +1586,13 @@ class SharedLibrary(BuildTarget): # We replicate what Autotools does here and take the first # number of the version by default. self.soversion = self.ltversion.split('.')[0] + # macOS and iOS dylib compatibility_version and current_version + if 'darwin_versions' in kwargs: + self.darwin_versions = self._validate_darwin_versions(kwargs['darwin_versions']) + elif self.soversion: + # If unspecified, pick the soversion + self.darwin_versions = 2 * [self.soversion] + # Visual Studio module-definitions file if 'vs_module_defs' in kwargs: path = kwargs['vs_module_defs'] diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 71f8ebe..36507b0 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1056,14 +1056,14 @@ class Compiler: return None def build_osx_rpath_args(self, build_dir, rpath_paths, build_rpath): + # Ensure that there is enough space for large RPATHs and install_name + args = ['-Wl,-headerpad_max_install_names'] if not rpath_paths and not build_rpath: - return [] + return args # On OSX, rpaths must be absolute. abs_rpaths = [os.path.join(build_dir, p) for p in rpath_paths] if build_rpath != '': abs_rpaths.append(build_rpath) - # Ensure that there is enough space for large RPATHs - args = ['-Wl,-headerpad_max_install_names'] # Need to deduplicate abs_rpaths, as rpath_paths and # build_rpath are not guaranteed to be disjoint sets args += ['-Wl,-rpath,' + rp for rp in OrderedSet(abs_rpaths)] @@ -1165,12 +1165,9 @@ def get_macos_dylib_install_name(prefix, shlib_name, suffix, soversion): install_name += '.dylib' return '@rpath/' + install_name -def get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, soversion, is_shared_module): - if soversion is None: - sostr = '' - else: - sostr = '.' + soversion +def get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, soversion, darwin_versions, is_shared_module): if gcc_type == GCC_STANDARD: + sostr = '' if soversion is None else '.' + soversion return ['-Wl,-soname,%s%s.%s%s' % (prefix, shlib_name, suffix, sostr)] elif gcc_type in (GCC_MINGW, GCC_CYGWIN): # For PE/COFF the soname argument has no effect with GNU LD @@ -1179,7 +1176,10 @@ def get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, soversion, is_shar if is_shared_module: return [] name = get_macos_dylib_install_name(prefix, shlib_name, suffix, soversion) - return ['-install_name', name] + args = ['-install_name', name] + if darwin_versions: + args += ['-compatibility_version', darwin_versions[0], '-current_version', darwin_versions[1]] + return args else: raise RuntimeError('Not implemented yet.') @@ -1325,8 +1325,8 @@ class GnuCompiler: def split_shlib_to_parts(self, fname): return os.path.dirname(fname), fname - def get_soname_args(self, prefix, shlib_name, suffix, soversion, is_shared_module): - return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, soversion, is_shared_module) + def get_soname_args(self, *args): + return get_gcc_soname_args(self.gcc_type, *args) def get_std_shared_lib_link_args(self): return ['-shared'] @@ -1452,7 +1452,7 @@ class ClangCompiler: # so it might change semantics at any time. return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))] - def get_soname_args(self, prefix, shlib_name, suffix, soversion, is_shared_module): + def get_soname_args(self, *args): if self.clang_type == CLANG_STANDARD: gcc_type = GCC_STANDARD elif self.clang_type == CLANG_OSX: @@ -1461,7 +1461,7 @@ class ClangCompiler: gcc_type = GCC_MINGW else: raise MesonException('Unreachable code when converting clang type to gcc type.') - return get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, soversion, is_shared_module) + return get_gcc_soname_args(gcc_type, *args) def has_multi_arguments(self, args, env): myargs = ['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument'] @@ -1620,7 +1620,7 @@ class IntelCompiler: def split_shlib_to_parts(self, fname): return os.path.dirname(fname), fname - def get_soname_args(self, prefix, shlib_name, suffix, soversion, is_shared_module): + def get_soname_args(self, *args): if self.icc_type == ICC_STANDARD: gcc_type = GCC_STANDARD elif self.icc_type == ICC_OSX: @@ -1629,7 +1629,7 @@ class IntelCompiler: gcc_type = GCC_MINGW else: raise MesonException('Unreachable code when converting icc type to gcc type.') - return get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, soversion, is_shared_module) + return get_gcc_soname_args(gcc_type, *args) # TODO: centralise this policy more globally, instead # of fragmenting it into GnuCompiler and ClangCompiler diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index a03af3e..c81c048 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -118,16 +118,14 @@ class DCompiler(Compiler): def get_std_shared_lib_link_args(self): return ['-shared'] - def get_soname_args(self, prefix, shlib_name, suffix, soversion, is_shared_module): + def get_soname_args(self, *args): # FIXME: Make this work for cross-compiling gcc_type = GCC_STANDARD if is_windows(): gcc_type = GCC_CYGWIN if is_osx(): gcc_type = GCC_OSX - - return get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, soversion, is_shared_module) - + return get_gcc_soname_args(gcc_type, *args) def get_feature_args(self, kwargs, build_to_src): res = [] |