diff options
-rw-r--r-- | docs/yaml/functions/shared_library.yaml | 7 | ||||
-rw-r--r-- | docs/yaml/functions/shared_module.yaml | 9 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 2 | ||||
-rw-r--r-- | mesonbuild/build.py | 16 | ||||
-rw-r--r-- | test cases/failing/75 link with shared module on osx/test.json | 2 | ||||
-rw-r--r-- | test cases/unit/1 soname/main.c | 5 | ||||
-rw-r--r-- | test cases/unit/1 soname/meson.build | 13 | ||||
-rw-r--r-- | unittests/allplatformstests.py | 6 | ||||
-rw-r--r-- | unittests/linuxliketests.py | 18 |
9 files changed, 63 insertions, 15 deletions
diff --git a/docs/yaml/functions/shared_library.yaml b/docs/yaml/functions/shared_library.yaml index 46e5a1c..15ac782 100644 --- a/docs/yaml/functions/shared_library.yaml +++ b/docs/yaml/functions/shared_library.yaml @@ -2,13 +2,6 @@ name: shared_library returns: lib description: Builds a shared library with the given sources. -notes: - - | - Linking to a shared module is not supported on some - platforms, notably OSX. Consider using a - [[shared_library]] instead, if you need to both - `dlopen()` and link with a library. - posargs_inherit: _build_target_base varargs_inherit: _build_target_base kwargs_inherit: _build_target_base diff --git a/docs/yaml/functions/shared_module.yaml b/docs/yaml/functions/shared_module.yaml index 8909c2f..ff374e7 100644 --- a/docs/yaml/functions/shared_module.yaml +++ b/docs/yaml/functions/shared_module.yaml @@ -13,6 +13,15 @@ description: | you will need to set the `export_dynamic` argument of the executable to `true`. +notes: + - | + *Linking to a shared module is deprecated, and will be an error in the future*. + It used to be allowed because it was the only way to have a shared-library-like target that + contained references to undefined symbols. However, since 0.40.0, the `override_options:` + [[build_target]] keyword argument can be used to create such a [[shared_library]], and shared + modules have other characteristics that make them incompatible with linking, such as a lack of + SONAME. Linking to shared modules also does not work on some platforms, such as on macOS / iOS. + posargs_inherit: _build_target_base varargs_inherit: _build_target_base kwargs_inherit: _build_target_base diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index a1d3e50..b6621c9 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2785,7 +2785,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) commands += linker.get_std_shared_lib_link_args() # All shared libraries are PIC commands += linker.get_pic_args() - if not isinstance(target, build.SharedModule): + if not isinstance(target, build.SharedModule) or target.backwards_compat_want_soname: # Add -Wl,-soname arguments on Linux, -install_name on OS X commands += linker.get_soname_args( self.environment, target.prefix, target.name, target.suffix, diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 6036735..ad18a7f 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1591,11 +1591,16 @@ You probably should put it in link_with instead.''') if isinstance(link_target, SharedModule): if self.environment.machines[self.for_machine].is_darwin(): raise MesonException( - 'target links against shared modules. This is not permitted on OSX') + f'target {self.name} links against shared module {link_target.name}. This is not permitted on OSX') else: - mlog.warning('target links against shared modules. This ' - 'is not recommended as it is not supported on some ' - 'platforms') + mlog.deprecation(f'target {self.name} links against shared module {link_target.name}, which is incorrect.' + '\n ' + f'This will be an error in the future, so please use shared_library() for {link_target.name} instead.' + '\n ' + f'If shared_module() was used for {link_target.name} because it has references to undefined symbols,' + '\n ' + 'use shared_libary() with `override_options: [\'b_lundef=false\']` instead.') + link_target.backwards_compat_want_soname = True return class Generator(HoldableObject): @@ -2259,6 +2264,9 @@ class SharedModule(SharedLibrary): raise MesonException('Shared modules must not specify the soversion kwarg.') super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) self.typename = 'shared module' + # We need to set the soname in cases where build files link the module + # to build targets, see: https://github.com/mesonbuild/meson/issues/9492 + self.backwards_compat_want_soname = False def get_default_install_dir(self, environment) -> T.Tuple[str, str]: return environment.get_shared_module_dir(), '{moduledir_shared}' diff --git a/test cases/failing/75 link with shared module on osx/test.json b/test cases/failing/75 link with shared module on osx/test.json index 7db17d8..81ee2ac 100644 --- a/test cases/failing/75 link with shared module on osx/test.json +++ b/test cases/failing/75 link with shared module on osx/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/75 link with shared module on osx/meson.build:8:0: ERROR: target links against shared modules. This is not permitted on OSX" + "line": "test cases/failing/75 link with shared module on osx/meson.build:8:0: ERROR: target prog links against shared module mymodule. This is not permitted on OSX" } ] } diff --git a/test cases/unit/1 soname/main.c b/test cases/unit/1 soname/main.c new file mode 100644 index 0000000..f5ccbb9 --- /dev/null +++ b/test cases/unit/1 soname/main.c @@ -0,0 +1,5 @@ +int versioned_func (void); + +int main (void) { + return versioned_func(); +} diff --git a/test cases/unit/1 soname/meson.build b/test cases/unit/1 soname/meson.build index 950dadc..44b003a 100644 --- a/test cases/unit/1 soname/meson.build +++ b/test cases/unit/1 soname/meson.build @@ -20,3 +20,16 @@ shared_library('settosame', 'versioned.c', install : true, soversion : '7.8.9', version : '7.8.9') + +shared_module('some_module', 'versioned.c', + install: true) + +module1 = shared_module('linked_module1', 'versioned.c', + install: true) + +module2 = shared_module('linked_module2', 'versioned.c', + install: true) +module2_dep = declare_dependency(link_with: module2) + +executable('main1', 'main.c', link_with: module1) +executable('main2', 'main.c', dependencies: module2_dep) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 03992bd..30c0572 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -1946,8 +1946,10 @@ class AllPlatformTests(BasePlatformTests): """ tdir = os.path.join(self.unit_test_dir, '30 shared_mod linking') out = self.init(tdir) - msg = ('WARNING: target links against shared modules. This is not ' - 'recommended as it is not supported on some platforms') + msg = ('''DEPRECATION: target prog links against shared module mymod, which is incorrect. + This will be an error in the future, so please use shared_library() for mymod instead. + If shared_module() was used for mymod because it has references to undefined symbols, + use shared_libary() with `override_options: ['b_lundef=false']` instead.''') self.assertIn(msg, out) def test_mixed_language_linker_check(self): diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index 0f99f01..8ff0f8e 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -438,6 +438,24 @@ class LinuxlikeTests(BasePlatformTests): self.assertEqual(get_soname(bothset), 'libbothset.so.1.2.3') self.assertEqual(len(self.glob_sofiles_without_privdir(bothset[:-3] + '*')), 3) + # A shared_module that is not linked to anything + module = os.path.join(libpath, 'libsome_module.so') + self.assertPathExists(module) + self.assertFalse(os.path.islink(module)) + self.assertEqual(get_soname(module), None) + + # A shared_module that is not linked to an executable with link_with: + module = os.path.join(libpath, 'liblinked_module1.so') + self.assertPathExists(module) + self.assertFalse(os.path.islink(module)) + self.assertEqual(get_soname(module), 'liblinked_module1.so') + + # A shared_module that is not linked to an executable with dependencies: + module = os.path.join(libpath, 'liblinked_module2.so') + self.assertPathExists(module) + self.assertFalse(os.path.islink(module)) + self.assertEqual(get_soname(module), 'liblinked_module2.so') + def test_soname(self): self._test_soname_impl(self.builddir, False) |