diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 659a53da6..6e2b1eefb 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1927,7 +1927,8 @@ rule FORTRAN_DEP_HACK commands += linker.get_linker_always_args() if not isinstance(target, build.StaticLibrary): commands += compilers.get_base_link_args(self.environment.coredata.base_options, - linker) + linker, + isinstance(target, build.SharedModule)) commands += linker.get_buildtype_linker_args(self.environment.coredata.get_builtin_option('buildtype')) commands += linker.get_option_link_args(self.environment.coredata.compiler_options) commands += self.get_link_debugfile_args(linker, target, outname) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 39e215fd0..b5ca5aa43 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1129,6 +1129,16 @@ class SharedLibrary(BuildTarget): def type_suffix(self): return "@sha" +# A shared library that is meant to be used with dlopen rather than linking +# into something else. +class SharedModule(SharedLibrary): + def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): + if 'version' in kwargs: + raise MesonException('Shared modules must not specify the version kwarg.') + if 'soversion' in kwargs: + raise MesonException('Shared modules must not specify the soversion kwarg.') + super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) + class CustomTarget: known_kwargs = {'input' : True, 'output' : True, diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 8f8851f4d..c603f370b 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -248,7 +248,7 @@ def get_base_compile_args(options, compiler): pass return args -def get_base_link_args(options, linker): +def get_base_link_args(options, linker, is_shared_module): args = [] # FIXME, gcc/clang specific. try: @@ -269,7 +269,7 @@ def get_base_link_args(options, linker): except KeyError: pass try: - if options['b_lundef'].value: + if not is_shared_module and options['b_lundef'].value: args.append('-Wl,--no-undefined') except KeyError: pass diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index ef99511d4..fefc1ff0c 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -586,6 +586,10 @@ class SharedLibraryHolder(BuildTargetHolder): def __init__(self, target, interp): super().__init__(target, interp) +class SharedModuleHolder(BuildTargetHolder): + def __init__(self, target, interp): + super().__init__(target, interp) + class JarHolder(BuildTargetHolder): def __init__(self, target, interp): super().__init__(target, interp) @@ -1203,6 +1207,7 @@ class Interpreter(): 'dependency' : self.func_dependency, 'static_library' : self.func_static_lib, 'shared_library' : self.func_shared_lib, + 'shared_module' : self.func_shared_module, 'library' : self.func_library, 'jar' : self.func_jar, 'build_target': self.func_build_target, @@ -1961,6 +1966,9 @@ requirements use the version keyword argument instead.''') def func_shared_lib(self, node, args, kwargs): return self.build_target(node, args, kwargs, SharedLibraryHolder) + def func_shared_module(self, node, args, kwargs): + return self.build_target(node, args, kwargs, SharedModuleHolder) + def func_library(self, node, args, kwargs): if self.coredata.get_builtin_option('default_library') == 'shared': return self.func_shared_lib(node, args, kwargs) @@ -2448,6 +2456,8 @@ requirements use the version keyword argument instead.''') targetclass = build.Executable elif targetholder is SharedLibraryHolder: targetclass = build.SharedLibrary + elif targetholder is SharedModuleHolder: + targetclass = build.SharedModule elif targetholder is StaticLibraryHolder: targetclass = build.StaticLibrary elif targetholder is JarHolder: diff --git a/test cases/common/125 shared module/meson.build b/test cases/common/125 shared module/meson.build new file mode 100644 index 000000000..70e954bd8 --- /dev/null +++ b/test cases/common/125 shared module/meson.build @@ -0,0 +1,4 @@ +project('shared module', 'c') + +shared_module('mymodule', 'module.c') + diff --git a/test cases/common/125 shared module/module.c b/test cases/common/125 shared module/module.c new file mode 100644 index 000000000..be0720d29 --- /dev/null +++ b/test cases/common/125 shared module/module.c @@ -0,0 +1,22 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +/* + * Shared modules often have references to symbols that are not defined + * at link time, but which will be provided by the executable that + * dlopens it. We need to make sure that this works, i.e. that we do + * not pass -Wl,--no-undefined when linking modules. + */ +int nonexisting_function(); + +int DLL_PUBLIC func() { + return nonexisting_function(); +}