parent
5421c24ea0
commit
32be9bd6de
|
@ -0,0 +1,4 @@
|
||||||
|
## Executable gains vs_module_defs keyword
|
||||||
|
|
||||||
|
This allows using a .def file to control which functions an [[executable]] will
|
||||||
|
expose to a [[shared_module]].
|
|
@ -44,3 +44,13 @@ kwargs:
|
||||||
type: bool
|
type: bool
|
||||||
since: 0.49.0
|
since: 0.49.0
|
||||||
description: Build a position-independent executable.
|
description: Build a position-independent executable.
|
||||||
|
|
||||||
|
vs_module_defs:
|
||||||
|
type: str | file | custom_tgt | custom_idx
|
||||||
|
since: 1.3.0
|
||||||
|
description: |
|
||||||
|
Specify a Microsoft module definition file for controlling symbol exports,
|
||||||
|
etc., on platforms where that is possible (e.g. Windows).
|
||||||
|
|
||||||
|
This can be used to expose which functions a shared_module loaded by an
|
||||||
|
executable will be allowed to use.
|
||||||
|
|
|
@ -3248,6 +3248,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
|
||||||
commands += linker.gen_import_library_args(self.get_import_filename(target))
|
commands += linker.gen_import_library_args(self.get_import_filename(target))
|
||||||
if target.pie:
|
if target.pie:
|
||||||
commands += linker.get_pie_link_args()
|
commands += linker.get_pie_link_args()
|
||||||
|
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))
|
||||||
elif isinstance(target, build.SharedLibrary):
|
elif isinstance(target, build.SharedLibrary):
|
||||||
if isinstance(target, build.SharedModule):
|
if isinstance(target, build.SharedModule):
|
||||||
commands += linker.get_std_shared_module_link_args(target.get_options())
|
commands += linker.get_std_shared_module_link_args(target.get_options())
|
||||||
|
|
|
@ -1530,7 +1530,7 @@ class Vs2010Backend(backends.Backend):
|
||||||
# DLLs built with MSVC always have an import library except when
|
# DLLs built with MSVC always have an import library except when
|
||||||
# they're data-only DLLs, but we don't support those yet.
|
# they're data-only DLLs, but we don't support those yet.
|
||||||
ET.SubElement(link, 'ImportLibrary').text = target.get_import_filename()
|
ET.SubElement(link, 'ImportLibrary').text = target.get_import_filename()
|
||||||
if isinstance(target, build.SharedLibrary):
|
if isinstance(target, (build.SharedLibrary, build.Executable)):
|
||||||
# Add module definitions file, if provided
|
# Add module definitions file, if provided
|
||||||
if target.vs_module_defs:
|
if target.vs_module_defs:
|
||||||
relpath = os.path.join(down, target.vs_module_defs.rel_to_builddir(self.build_to_src))
|
relpath = os.path.join(down, target.vs_module_defs.rel_to_builddir(self.build_to_src))
|
||||||
|
|
|
@ -114,7 +114,7 @@ known_build_target_kwargs = (
|
||||||
rust_kwargs |
|
rust_kwargs |
|
||||||
cs_kwargs)
|
cs_kwargs)
|
||||||
|
|
||||||
known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie'}
|
known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie', 'vs_module_defs'}
|
||||||
known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions', 'rust_abi'}
|
known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions', 'rust_abi'}
|
||||||
known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs', 'rust_abi'}
|
known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs', 'rust_abi'}
|
||||||
known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink', 'rust_abi'}
|
known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink', 'rust_abi'}
|
||||||
|
@ -1702,6 +1702,28 @@ class BuildTarget(Target):
|
||||||
'use shared_library() with `override_options: [\'b_lundef=false\']` instead.')
|
'use shared_library() with `override_options: [\'b_lundef=false\']` instead.')
|
||||||
link_target.force_soname = True
|
link_target.force_soname = True
|
||||||
|
|
||||||
|
def process_vs_module_defs_kw(self, kwargs: T.Dict[str, T.Any]) -> None:
|
||||||
|
if kwargs.get('vs_module_defs') is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
path: T.Union[str, File, CustomTarget, CustomTargetIndex] = kwargs['vs_module_defs']
|
||||||
|
if isinstance(path, str):
|
||||||
|
if os.path.isabs(path):
|
||||||
|
self.vs_module_defs = File.from_absolute_file(path)
|
||||||
|
else:
|
||||||
|
self.vs_module_defs = File.from_source_file(self.environment.source_dir, self.subdir, path)
|
||||||
|
elif isinstance(path, File):
|
||||||
|
# When passing a generated file.
|
||||||
|
self.vs_module_defs = path
|
||||||
|
elif isinstance(path, (CustomTarget, CustomTargetIndex)):
|
||||||
|
# When passing output of a Custom Target
|
||||||
|
self.vs_module_defs = File.from_built_file(path.get_subdir(), path.get_filename())
|
||||||
|
else:
|
||||||
|
raise InvalidArguments(
|
||||||
|
'vs_module_defs must be either a string, '
|
||||||
|
'a file object, a Custom Target, or a Custom Target Index')
|
||||||
|
self.process_link_depends(path)
|
||||||
|
|
||||||
class FileInTargetPrivateDir:
|
class FileInTargetPrivateDir:
|
||||||
"""Represents a file with the path '/path/to/build/target_private_dir/fname'.
|
"""Represents a file with the path '/path/to/build/target_private_dir/fname'.
|
||||||
target_private_dir is the return value of get_target_private_dir which is e.g. 'subdir/target.p'.
|
target_private_dir is the return value of get_target_private_dir which is e.g. 'subdir/target.p'.
|
||||||
|
@ -1925,6 +1947,9 @@ class Executable(BuildTarget):
|
||||||
# Remember that this exe was returned by `find_program()` through an override
|
# Remember that this exe was returned by `find_program()` through an override
|
||||||
self.was_returned_by_find_program = False
|
self.was_returned_by_find_program = False
|
||||||
|
|
||||||
|
self.vs_module_defs: T.Optional[File] = None
|
||||||
|
self.process_vs_module_defs_kw(kwargs)
|
||||||
|
|
||||||
def post_init(self) -> None:
|
def post_init(self) -> None:
|
||||||
super().post_init()
|
super().post_init()
|
||||||
machine = self.environment.machines[self.for_machine]
|
machine = self.environment.machines[self.for_machine]
|
||||||
|
@ -2321,24 +2346,7 @@ class SharedLibrary(BuildTarget):
|
||||||
self.darwin_versions = (self.soversion, self.soversion)
|
self.darwin_versions = (self.soversion, self.soversion)
|
||||||
|
|
||||||
# Visual Studio module-definitions file
|
# Visual Studio module-definitions file
|
||||||
if kwargs.get('vs_module_defs') is not None:
|
self.process_vs_module_defs_kw(kwargs)
|
||||||
path = kwargs['vs_module_defs']
|
|
||||||
if isinstance(path, str):
|
|
||||||
if os.path.isabs(path):
|
|
||||||
self.vs_module_defs = File.from_absolute_file(path)
|
|
||||||
else:
|
|
||||||
self.vs_module_defs = File.from_source_file(self.environment.source_dir, self.subdir, path)
|
|
||||||
elif isinstance(path, File):
|
|
||||||
# When passing a generated file.
|
|
||||||
self.vs_module_defs = path
|
|
||||||
elif isinstance(path, (CustomTarget, CustomTargetIndex)):
|
|
||||||
# When passing output of a Custom Target
|
|
||||||
self.vs_module_defs = File.from_built_file(path.get_subdir(), path.get_filename())
|
|
||||||
else:
|
|
||||||
raise InvalidArguments(
|
|
||||||
'Shared library vs_module_defs must be either a string, '
|
|
||||||
'a file object, a Custom Target, or a Custom Target Index')
|
|
||||||
self.process_link_depends(path)
|
|
||||||
|
|
||||||
rust_abi = kwargs.get('rust_abi')
|
rust_abi = kwargs.get('rust_abi')
|
||||||
rust_crate_type = kwargs.get('rust_crate_type')
|
rust_crate_type = kwargs.get('rust_crate_type')
|
||||||
|
|
|
@ -341,6 +341,7 @@ class _LibraryMixin(TypedDict):
|
||||||
class Executable(_BuildTarget):
|
class Executable(_BuildTarget):
|
||||||
|
|
||||||
gui_app: T.Optional[bool]
|
gui_app: T.Optional[bool]
|
||||||
|
vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex]]
|
||||||
win_subsystem: T.Optional[str]
|
win_subsystem: T.Optional[str]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -601,6 +601,7 @@ _EXCLUSIVE_EXECUTABLE_KWS: T.List[KwargInfo] = [
|
||||||
EXECUTABLE_KWS = [
|
EXECUTABLE_KWS = [
|
||||||
*_BUILD_TARGET_KWS,
|
*_BUILD_TARGET_KWS,
|
||||||
*_EXCLUSIVE_EXECUTABLE_KWS,
|
*_EXCLUSIVE_EXECUTABLE_KWS,
|
||||||
|
_VS_MODULE_DEFS_KW.evolve(since='1.3.0', since_values=None),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Arguments exclusive to library types
|
# Arguments exclusive to library types
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
EXPORTS
|
||||||
|
exefunc
|
|
@ -1,5 +1,5 @@
|
||||||
project('generated_dll_module_defs', 'c')
|
project('generated_dll_module_defs', 'c')
|
||||||
|
|
||||||
subdir('subdir')
|
subdir('subdir')
|
||||||
exe = executable('prog', 'prog.c', link_with : shlib)
|
exe = executable('prog', 'prog.c', link_with : shlib, vs_module_defs : 'exe.def')
|
||||||
test('runtest', exe)
|
test('runtest', exe)
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
int somedllfunc(void);
|
int somedllfunc(void);
|
||||||
|
|
||||||
int main(void) {
|
int exefunc(void) {
|
||||||
return somedllfunc() == 42 ? 0 : 1;
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
return somedllfunc() == exefunc() ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue