diff options
-rw-r--r-- | docs/markdown/Reference-manual.md | 16 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 3 | ||||
-rw-r--r-- | mesonbuild/build.py | 25 | ||||
-rw-r--r-- | mesonbuild/compilers/c.py | 8 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 2 | ||||
-rw-r--r-- | test cases/common/125 shared module/meson.build | 4 | ||||
-rw-r--r-- | test cases/common/156 shared module resolving symbol in executable/meson.build | 8 |
7 files changed, 46 insertions, 20 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index e30b79c..a231ed4 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -403,7 +403,7 @@ be passed to [shared and static libraries](#library). flags here for all platforms. - `link_depends` strings, files, or custom targets the link step depends on such as a symbol visibility map. The purpose is to - automaticallytrigger a re-link (but not a re-compile) of the target + automatically trigger a re-link (but not a re-compile) of the target when this file changes. - `link_whole` links all contents of the given static libraries whether they are used by not, equivalent to the @@ -412,13 +412,18 @@ be passed to [shared and static libraries](#library). - `link_with`, one or more shared or static libraries (built by this project) that this target should be linked with, If passed a list this list will be flattened as of 0.41.0. +- `export_dynamic` when set to true causes the target's symbols to be + dynamically exported, allowing modules built using the + [`shared_module`](#shared_module) function to refer to functions, + variables and other symbols defined in the executable itself. Implies + the `implib` argument. Since 0.44.0 - `implib` when set to true, an import library is generated for the executable (the name of the import library is based on *exe_name*). Alternatively, when set to a string, that gives the base name for the import library. The import library is used when the returned build target object appears in `link_with:` elsewhere. Only has any - effect on platforms where that is meaningful (e.g. Windows). Since - 0.42.0 + effect on platforms where that is meaningful (e.g. Windows). Implies + the `export_dynamic` argument. Since 0.42.0 - `implicit_include_directories` is a boolean telling whether Meson adds the current source and build directories to the include path, defaults to `true`, since 0.42.0 @@ -1010,6 +1015,11 @@ This is useful for building modules that will be `dlopen()`ed and hence may contain undefined symbols that will be provided by the library that is loading it. +If you want the shared module to be able to refer to functions and +variables defined in the [`executable`](#executable) it is loaded by, +you will need to set the `export_dynamic` argument of the executable to +`true`. + *Added 0.37.0* ### static_library() diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 2429fba..2945d6a 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2341,6 +2341,9 @@ rule FORTRAN_DEP_HACK # If gui_app, and that's significant on this platform if target.gui_app and hasattr(linker, 'get_gui_app_args'): commands += linker.get_gui_app_args() + # If export_dynamic, add the appropriate linker arguments + if target.export_dynamic: + commands += linker.gen_export_dynamic_link_args(self.environment) # If implib, and that's significant on this platform (i.e. Windows using either GCC or Visual Studio) if target.import_filename: commands += linker.gen_import_library_args(os.path.join(self.get_target_dir(target), target.import_filename)) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 8a2e716..16a18a9 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -82,6 +82,7 @@ known_lib_kwargs.update({'version': True, # Only for shared libs known_exe_kwargs = known_basic_kwargs.copy() known_exe_kwargs.update({'implib': True, + 'export_dynamic': True }) class InvalidArguments(MesonException): @@ -1160,23 +1161,33 @@ class Executable(BuildTarget): # The import library that GCC would generate (and prefer) self.gcc_import_filename = None - # if implib appears, this target is linkwith:-able, but that only means - # something on Windows platforms. - self.is_linkwithable = False - if 'implib' in kwargs and kwargs['implib']: + # Check for export_dynamic + self.export_dynamic = False + if kwargs.get('export_dynamic'): + if not isinstance(kwargs['export_dynamic'], bool): + raise InvalidArguments('"export_dynamic" keyword argument must be a boolean') + self.export_dynamic = True + if kwargs.get('implib'): + self.export_dynamic = True + if self.export_dynamic and kwargs.get('implib') is False: + raise InvalidArguments('"implib" keyword argument must not be false for if "export_dynamic" is true') + + # If using export_dynamic, set the import library name + if self.export_dynamic: implib_basename = self.name + '.exe' - if not isinstance(kwargs['implib'], bool): + if not isinstance(kwargs.get('implib', False), bool): implib_basename = kwargs['implib'] - self.is_linkwithable = True if for_windows(is_cross, environment) or for_cygwin(is_cross, environment): self.vs_import_filename = '{0}.lib'.format(implib_basename) self.gcc_import_filename = 'lib{0}.a'.format(implib_basename) - if self.get_using_msvc(): self.import_filename = self.vs_import_filename else: self.import_filename = self.gcc_import_filename + # Only linkwithable if using export_dynamic + self.is_linkwithable = self.export_dynamic + def type_suffix(self): return "@exe" diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 233fc84..4c6e3a2 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -183,6 +183,14 @@ class CCompiler(Compiler): def get_default_include_dirs(self): return [] + def gen_export_dynamic_link_args(self, env): + if for_windows(env.is_cross_build(), env): + return ['-Wl,--export-all-symbols'] + elif for_darwin(env.is_cross_build(), env): + return [] + else: + return ['-Wl,-export-dynamic'] + def gen_import_library_args(self, implibname): """ The name of the outputted import library diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 48b8d82..488c2a3 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1347,7 +1347,7 @@ build_target_common_kwargs = ( rust_kwargs | cs_kwargs) -exe_kwargs = (build_target_common_kwargs) | {'implib'} +exe_kwargs = (build_target_common_kwargs) | {'implib', 'export_dynamic'} shlib_kwargs = (build_target_common_kwargs) | {'version', 'soversion'} shmod_kwargs = shlib_kwargs stlib_kwargs = shlib_kwargs diff --git a/test cases/common/125 shared module/meson.build b/test cases/common/125 shared module/meson.build index 29277e9..08a284d 100644 --- a/test cases/common/125 shared module/meson.build +++ b/test cases/common/125 shared module/meson.build @@ -8,6 +8,6 @@ l = shared_library('runtime', 'runtime.c') # at runtime. This requires extra help on Windows, so # should be avoided unless really necessary. m = shared_module('mymodule', 'module.c') -e = executable('prog', 'prog.c', link_with : l, dependencies : dl) +e = executable('prog', 'prog.c', + link_with : l, export_dynamic : true, dependencies : dl) test('import test', e, args : m) - diff --git a/test cases/common/156 shared module resolving symbol in executable/meson.build b/test cases/common/156 shared module resolving symbol in executable/meson.build index 34a75f1..282a4d2 100644 --- a/test cases/common/156 shared module resolving symbol in executable/meson.build +++ b/test cases/common/156 shared module resolving symbol in executable/meson.build @@ -9,13 +9,7 @@ project('shared module resolving symbol in executable', 'c') # See testcase 125 for an example of the more complex portability gymnastics # required if we do not know (at link-time) what provides the symbol. -link_flags = [] -if host_machine.system() != 'windows' - # Needed to export dynamic symbols from the executable - link_flags += ['-rdynamic'] -endif - dl = meson.get_compiler('c').find_library('dl', required: false) -e = executable('prog', 'prog.c', dependencies: dl, implib: true, link_args: link_flags) +e = executable('prog', 'prog.c', dependencies: dl, export_dynamic: true) m = shared_module('module', 'module.c', link_with: e) test('test', e, args: m.full_path()) |