From d69e21f852392552a22922e982b99d7a3acd26ee Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 13 Jul 2023 10:26:14 -0700 Subject: [PATCH] interpreter: add _(static|shared)_args Which allow passing arguments specifically to the static or shared libraries (but not shared_modules). For design, this is all handled in the interpreter, by the build layer the arguments are combined into the existing fields. This limits changes required in the mid and backend layers --- .../snippets/shared_static_only_args.md | 5 +++++ docs/yaml/functions/shared_library.yaml | 5 +++++ docs/yaml/functions/static_library.yaml | 5 +++++ mesonbuild/build.py | 5 +++-- mesonbuild/interpreter/interpreter.py | 20 ++++++++++++----- mesonbuild/interpreter/type_checking.py | 3 +++ test cases/common/3 static/lib3.c | 11 ++++++++++ test cases/common/3 static/meson.build | 6 ++++- test cases/common/4 shared/libfile2.c | 22 +++++++++++++++++++ test cases/common/4 shared/meson.build | 6 ++++- 10 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 docs/markdown/snippets/shared_static_only_args.md create mode 100644 test cases/common/3 static/lib3.c create mode 100644 test cases/common/4 shared/libfile2.c diff --git a/docs/markdown/snippets/shared_static_only_args.md b/docs/markdown/snippets/shared_static_only_args.md new file mode 100644 index 000000000000..027fe4460726 --- /dev/null +++ b/docs/markdown/snippets/shared_static_only_args.md @@ -0,0 +1,5 @@ +## `_(shared|static)_args` for both_library + +We now allow passing arguments like `c_static_args` and `c_shared_args`. This +allows a `both_library` to have arguments specific to either the shared or +static library, as well as common arguments to both. diff --git a/docs/yaml/functions/shared_library.yaml b/docs/yaml/functions/shared_library.yaml index 956fb2cb2ce1..9c656c6ae11d 100644 --- a/docs/yaml/functions/shared_library.yaml +++ b/docs/yaml/functions/shared_library.yaml @@ -44,3 +44,8 @@ kwargs: description: | Specify a Microsoft module definition file for controlling symbol exports, etc., on platforms where that is possible (e.g. Windows). + + _shared_args: + type: str | file + description: + Arguments that are only passed to a shared library diff --git a/docs/yaml/functions/static_library.yaml b/docs/yaml/functions/static_library.yaml index 1d42d600a4b6..a95809df66bc 100644 --- a/docs/yaml/functions/static_library.yaml +++ b/docs/yaml/functions/static_library.yaml @@ -23,3 +23,8 @@ kwargs: If `true` the object files in the target will be prelinked, meaning that it will contain only one prelinked object file rather than the individual object files. + + _static_args: + type: str | file + description: + Arguments that are only passed to a static library diff --git a/mesonbuild/build.py b/mesonbuild/build.py index f3b8b917d382..f161f31477c1 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -113,9 +113,9 @@ cs_kwargs) known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie'} -known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions'} +known_shlib_kwargs = known_build_target_kwargs | {f'{l}_shared_args' for l in all_languages} | {'version', 'soversion', 'vs_module_defs', 'darwin_versions'} known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs'} -known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink'} +known_stlib_kwargs = known_build_target_kwargs | {f'{l}_static_args' for l in all_languages} | {'pic', 'prelink'} known_jar_kwargs = known_exe_kwargs | {'main_class', 'java_resources'} def _process_install_tag(install_tag: T.Optional[T.List[T.Optional[str]]], @@ -141,6 +141,7 @@ def get_target_macos_dylib_install_name(ld) -> str: class InvalidArguments(MesonException): pass + @dataclass(eq=False) class DependencyOverride(HoldableObject): dep: dependencies.Dependency diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 56222628e8e6..6de428bc7888 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -83,7 +83,9 @@ OVERRIDE_OPTIONS_KW, PRESERVE_PATH_KW, REQUIRED_KW, + SHARED_LIB_LANGUAGE_KWS, SOURCES_KW, + STATIC_LIB_LANGUAGE_KWS, VARIABLES_KW, TEST_KWS, NoneType, @@ -1815,7 +1817,7 @@ def func_executable(self, node: mparser.BaseNode, @permittedKwargs(build.known_stlib_kwargs) @typed_pos_args('static_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('static_library', *LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('static_library', *LANGUAGE_KWS, *STATIC_LIB_LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_static_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> build.StaticLibrary: @@ -1823,7 +1825,7 @@ def func_static_lib(self, node: mparser.BaseNode, @permittedKwargs(build.known_shlib_kwargs) @typed_pos_args('shared_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('shared_library', *LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('shared_library', *LANGUAGE_KWS, *SHARED_LIB_LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_shared_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> build.SharedLibrary: @@ -1833,7 +1835,7 @@ def func_shared_lib(self, node: mparser.BaseNode, @permittedKwargs(known_library_kwargs) @typed_pos_args('both_libraries', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('both_libraries', *LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('both_libraries', *LANGUAGE_KWS, *STATIC_LIB_LANGUAGE_KWS, *SHARED_LIB_LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_both_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> build.BothLibraries: @@ -1842,7 +1844,7 @@ def func_both_lib(self, node: mparser.BaseNode, @FeatureNew('shared_module', '0.37.0') @permittedKwargs(build.known_shmod_kwargs) @typed_pos_args('shared_module', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('shared_module', *LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('shared_module', *LANGUAGE_KWS, *SHARED_LIB_LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_shared_module(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> build.SharedModule: @@ -1850,7 +1852,7 @@ def func_shared_module(self, node: mparser.BaseNode, @permittedKwargs(known_library_kwargs) @typed_pos_args('library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('library', *LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('library', *LANGUAGE_KWS, *STATIC_LIB_LANGUAGE_KWS, *SHARED_LIB_LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_library(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> build.Executable: @@ -1867,7 +1869,7 @@ def func_jar(self, node: mparser.BaseNode, @FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options']) @permittedKwargs(known_build_target_kwargs) @typed_pos_args('build_target', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('build_target', *LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('build_target', *LANGUAGE_KWS, *STATIC_LIB_LANGUAGE_KWS, *SHARED_LIB_LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_build_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary, @@ -3261,6 +3263,12 @@ def build_target_decorator_caller(self, node, args, kwargs): raise RuntimeError('Unreachable code') self.kwarg_strings_to_includedirs(kwargs) self.__extract_language_args(kwargs) + if targetclass is build.StaticLibrary: + for lang in compilers.all_languages: + kwargs['language_args'][lang].extend(kwargs[f'{lang}_static_args']) + elif targetclass is build.SharedLibrary: + for lang in compilers.all_languages: + kwargs['language_args'][lang].extend(kwargs[f'{lang}_shared_args']) # Filter out kwargs from other target types. For example 'soversion' # passed to library() when default_library == 'static'. diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index a30f445737c0..e2790cbce942 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -486,3 +486,6 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus ] LANGUAGE_KWS.append(KwargInfo( 'rust_args', ContainerTypeInfo(list, str), listify=True, default=[], since='0.41.0')) + +STATIC_LIB_LANGUAGE_KWS = [l.evolve(name=f'{l.name.split("_", 1)[0]}_static_args', since='1.3.0') for l in LANGUAGE_KWS] +SHARED_LIB_LANGUAGE_KWS = [l.evolve(name=f'{l.name.split("_", 1)[0]}_shared_args', since='1.3.0') for l in LANGUAGE_KWS] diff --git a/test cases/common/3 static/lib3.c b/test cases/common/3 static/lib3.c new file mode 100644 index 000000000000..f834cf8b8422 --- /dev/null +++ b/test cases/common/3 static/lib3.c @@ -0,0 +1,11 @@ +int func3(const int x) { + return x + 1; +} + +#ifndef WORK +# error "did not get static only C args" +#endif + +#ifdef BREAK +# error "got shared only C args, but shouldn't have" +#endif diff --git a/test cases/common/3 static/meson.build b/test cases/common/3 static/meson.build index 04ff2f6f301e..92ec9a304c6f 100644 --- a/test cases/common/3 static/meson.build +++ b/test cases/common/3 static/meson.build @@ -1,4 +1,4 @@ -project('static library test', 'c') +project('static library test', 'c', default_options : ['default_library=static']) lib = static_library('mylib', get_option('source'), link_args : '-THISMUSTNOBEUSED') # Static linker needs to ignore all link args. @@ -12,3 +12,7 @@ endif assert(has_not_changed, 'Static library has changed.') assert(not is_disabler(lib), 'Static library is a disabler.') + +library('lib2', 'lib3.c', c_static_args : ['-DWORK'], c_shared_args : ['-DBREAK']) +static_library('lib3', 'lib3.c', c_static_args : ['-DWORK']) +build_target('lib4', 'lib3.c', c_static_args : ['-DWORK'], target_type : 'static_library') diff --git a/test cases/common/4 shared/libfile2.c b/test cases/common/4 shared/libfile2.c new file mode 100644 index 000000000000..fee1d1efd872 --- /dev/null +++ b/test cases/common/4 shared/libfile2.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 + +#ifndef WORK +# error "Did not get shared only arguments" +#endif + +#ifdef BREAK +# error "got static only C args, but shouldn't have" +#endif + +int DLL_PUBLIC libfunc(void) { + return 3; +} diff --git a/test cases/common/4 shared/meson.build b/test cases/common/4 shared/meson.build index 1c88bc5877d6..14549417c9dc 100644 --- a/test cases/common/4 shared/meson.build +++ b/test cases/common/4 shared/meson.build @@ -1,4 +1,4 @@ -project('shared library test', 'c') +project('shared library test', 'c', default_options : ['default_library=shared']) lib = shared_library('mylib', 'libfile.c') build_target('mylib2', 'libfile.c', target_type: 'shared_library') @@ -11,3 +11,7 @@ endif assert(has_not_changed, 'Shared library has changed.') assert(not is_disabler(lib), 'Shared library is a disabler.') + +shared_library('mylib3', 'libfile2.c', c_shared_args : ['-DWORK']) +build_target('mylib4', 'libfile2.c', target_type: 'shared_library', c_shared_args : ['-DWORK'], c_static_args : ['-DBREAK']) +library('mylib5', 'libfile2.c', c_shared_args : ['-DWORK'])