Add `export_dynamic` argument to `executable`. (#2662)

pull/2617/merge
Nikita Churaev 7 years ago committed by Jussi Pakkanen
parent 398aed6e49
commit de8018a17d
  1. 16
      docs/markdown/Reference-manual.md
  2. 3
      mesonbuild/backend/ninjabackend.py
  3. 25
      mesonbuild/build.py
  4. 8
      mesonbuild/compilers/c.py
  5. 2
      mesonbuild/interpreter.py
  6. 4
      test cases/common/125 shared module/meson.build
  7. 8
      test cases/common/156 shared module resolving symbol in executable/meson.build

@ -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()

@ -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))

@ -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"

@ -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

@ -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

@ -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)

@ -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())

Loading…
Cancel
Save