diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md index 6adc4218bda1..2018b9575aed 100644 --- a/docs/markdown/Builtin-options.md +++ b/docs/markdown/Builtin-options.md @@ -79,6 +79,7 @@ machine](#specifying-options-per-machine) section for details. | genvslite {vs2022} | vs2022 | Setup multi-builtype ninja build directories and Visual Studio solution | no | no | | buildtype {plain, debug,
debugoptimized, release, minsize, custom} | debug | Build type to use | no | no | | debug | true | Enable debug symbols and other information | no | no | +| default_both_libraries {shared, static, auto} | shared | Default library type for both_libraries | no | no | | default_library {shared, static, both} | shared | Default library type | no | yes | | errorlogs | true | Whether to print the logs from failing tests. | no | no | | install_umask {preserve, 0000-0777} | 022 | Default umask to apply on permissions of installed files | no | no | @@ -177,6 +178,19 @@ fails. `vsenv` is `true` by default when using the `vs` backend. + +#### Details for `default_both_libraries` + +Since `1.6.0`, you can select the default type of library selected when using +a `both_libraries` object. This can be either 'shared' (default value, compatible +with previous meson versions), 'static', or 'auto'. With auto, the value from +`default_library` option is used, unless it is 'both', in which case 'shared' +is used instead. + +When `default_both_libraries` is 'auto', passing a [[@both_libs]] dependecy +in [[both_libraries]] will link the static dependency with the static lib, +and the shared dependency with the shared lib. + ## Base options These are set in the same way as universal options, either by diff --git a/docs/markdown/snippets/alias_target_of_both_libraries.md b/docs/markdown/snippets/alias_target_of_both_libraries.md new file mode 100644 index 000000000000..ab77a6556576 --- /dev/null +++ b/docs/markdown/snippets/alias_target_of_both_libraries.md @@ -0,0 +1,5 @@ +## `alias_target` of `both_libraries` + +Previously, when passing a [[@both_libs]] object to [[alias_target]], the alias +would only point to the shared library. It now points to both the static and the +shared library. diff --git a/docs/markdown/snippets/default_both_libraries.md b/docs/markdown/snippets/default_both_libraries.md new file mode 100644 index 000000000000..dc9cb6bca3a8 --- /dev/null +++ b/docs/markdown/snippets/default_both_libraries.md @@ -0,0 +1,11 @@ +## New built-in option for default both_libraries + +`both_libraries` targets used to be considered as a shared library by default. +There is now the `default_both_libraries` option to change this default. + +When `default_both_libraries` is 'auto', [[both_libraries]] with dependencies +that are [[@both_libs]] themselves will link with the same kind of library. +For example, if `libA` is a [[@both_libs]] and `libB` is a [[@both_libs]] +linked with `libA` (or with an internal dependency on `libA`), +the static lib of `libB` will link with the static lib of `libA`, and the +shared lib of `libA` will link with the shared lib of `libB`. diff --git a/docs/markdown/snippets/dep_as_shared_as_static.md b/docs/markdown/snippets/dep_as_shared_as_static.md new file mode 100644 index 000000000000..a84e9eeaa182 --- /dev/null +++ b/docs/markdown/snippets/dep_as_shared_as_static.md @@ -0,0 +1,8 @@ +## New `as_static` and `as_shared` methods on internal dependencies + +[[@dep]] object returned by [[declare_dependency]] now has `.as_static()` and +`.as_shared()` methods, to convert to a dependency that prefers the `static` +or the `shared` version of the linked [[@both_libs]] target. + +When the same dependency is used without those methods, the +`default_both_libraries` option determines which version is used. diff --git a/docs/yaml/functions/alias_target.yaml b/docs/yaml/functions/alias_target.yaml index bc14f84da2fe..9833569018f7 100644 --- a/docs/yaml/functions/alias_target.yaml +++ b/docs/yaml/functions/alias_target.yaml @@ -9,6 +9,9 @@ description: | are built. Dependencies can be any build target. Since 0.60.0, this includes [[@run_tgt]]. + *Since 1.6.0* passing a [[@both_libs]] object builds both shared and + static libraries. + posargs: target_name: type: str diff --git a/docs/yaml/objects/dep.yaml b/docs/yaml/objects/dep.yaml index 76543d2c1ab9..28d93d79f7f6 100644 --- a/docs/yaml/objects/dep.yaml +++ b/docs/yaml/objects/dep.yaml @@ -221,3 +221,28 @@ methods: pkgconfig_define: type: list[str] description: See [[dep.get_pkgconfig_variable]] + + - name: as_static + returns: dep + since: 1.6.0 + description: | + Only for dependencies created with [[declare_dependency]], + returns a copy of the dependency object that prefer the `static` version + of [[both_libraries]]. + kwargs: + recursive: + type: bool + description: If true, this is recursively applied to dependencies + + - name: as_shared + returns: dep + since: 1.6.0 + description: | + Only for dependencies created with [[declare_dependency]], + returns a copy of the dependency object that prefer the `shared` version + of [[both_libraries]]. + kwargs: + recursive: + type: bool + description: If true, this is recursively applied to dependencies + \ No newline at end of file diff --git a/mesonbuild/build.py b/mesonbuild/build.py index a7a43b40cffe..5eff0ed805c5 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -137,6 +137,7 @@ def get_target_macos_dylib_install_name(ld) -> str: name.append('.dylib') return ''.join(name) + class InvalidArguments(MesonException): pass @@ -782,8 +783,8 @@ def __init__( # we have to call process_compilers() first and we need to process libraries # from link_with and link_whole first. # See https://github.com/mesonbuild/meson/pull/11957#issuecomment-1629243208. - link_targets = extract_as_list(kwargs, 'link_with') + self.link_targets - link_whole_targets = extract_as_list(kwargs, 'link_whole') + self.link_whole_targets + link_targets = self.extract_targets_as_list(kwargs, 'link_with') + link_whole_targets = self.extract_targets_as_list(kwargs, 'link_whole') self.link_targets.clear() self.link_whole_targets.clear() self.link(link_targets) @@ -1731,6 +1732,24 @@ def process_vs_module_defs_kw(self, kwargs: T.Dict[str, T.Any]) -> None: 'a file object, a Custom Target, or a Custom Target Index') self.process_link_depends(path) + def extract_targets_as_list(self, kwargs: T.Dict[str, T.Union[LibTypes, T.Sequence[LibTypes]]], key: T.Literal['link_with', 'link_whole']) -> T.List[LibTypes]: + bl_type = self.environment.coredata.get_option(OptionKey('default_both_libraries')) + if bl_type == 'auto': + bl_type = 'static' if isinstance(self, StaticLibrary) else 'shared' + + def _resolve_both_libs(lib: LibTypes) -> LibTypes: + if isinstance(lib, BothLibraries): + return lib.get(bl_type) + return lib + + self_libs: T.List[LibTypes] = self.link_targets if key == 'link_with' else self.link_whole_targets + lib_list = listify(kwargs.get(key, [])) + self_libs + return [_resolve_both_libs(t) for t in lib_list] + + def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> LibTypes: + """Base case used by BothLibraries""" + return self + class FileInTargetPrivateDir: """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'. @@ -2477,8 +2496,8 @@ def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, No return self.environment.get_shared_module_dir(), '{moduledir_shared}' class BothLibraries(SecondLevelHolder): - def __init__(self, shared: SharedLibrary, static: StaticLibrary) -> None: - self._preferred_library = 'shared' + def __init__(self, shared: SharedLibrary, static: StaticLibrary, preferred_library: Literal['shared', 'static', 'auto']) -> None: + self._preferred_library = preferred_library self.shared = shared self.static = static self.subproject = self.shared.subproject @@ -2486,13 +2505,23 @@ def __init__(self, shared: SharedLibrary, static: StaticLibrary) -> None: def __repr__(self) -> str: return f'' - def get_default_object(self) -> BuildTarget: + def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> LibTypes: + if lib_type == 'static': + return self.static + if lib_type == 'shared': + return self.shared + return self.get_default_object() + + def get_default_object(self) -> T.Union[StaticLibrary, SharedLibrary]: if self._preferred_library == 'shared': return self.shared elif self._preferred_library == 'static': return self.static raise MesonBugException(f'self._preferred_library == "{self._preferred_library}" is neither "shared" nor "static".') + def get_id(self) -> str: + return self.get_default_object().get_id() + class CommandBase: depend_files: T.List[File] @@ -2550,6 +2579,10 @@ def get_internal_static_libraries(self) -> OrderedSet[BuildTargetTypes]: def get_internal_static_libraries_recurse(self, result: OrderedSet[BuildTargetTypes]) -> None: pass + def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> LibTypes: + """Base case used by BothLibraries""" + return self + class CustomTarget(Target, CustomTargetBase, CommandBase): typename = 'custom' @@ -2871,14 +2904,23 @@ class AliasTarget(RunTarget): typename = 'alias' - def __init__(self, name: str, dependencies: T.Sequence['Target'], + def __init__(self, name: str, dependencies: T.Sequence[T.Union[Target, BothLibraries]], subdir: str, subproject: str, environment: environment.Environment): - super().__init__(name, [], dependencies, subdir, subproject, environment) + super().__init__(name, [], list(self._deps_generator(dependencies)), subdir, subproject, environment) def __repr__(self): repr_str = "<{0} {1}>" return repr_str.format(self.__class__.__name__, self.get_id()) + @staticmethod + def _deps_generator(dependencies: T.Sequence[T.Union[Target, BothLibraries]]) -> T.Iterator[Target]: + for dep in dependencies: + if isinstance(dep, BothLibraries): + yield dep.shared + yield dep.static + else: + yield dep + class Jar(BuildTarget): known_kwargs = known_jar_kwargs diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 08e81f0d79d5..fa278d97c07f 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -248,6 +248,14 @@ def generate_system_dependency(self, include_type: str) -> 'Dependency': new_dep.include_type = self._process_include_type_kw({'include_type': include_type}) return new_dep + def get_as_static(self, recursive: bool) -> Dependency: + """Used as base case for internal_dependency""" + return self + + def get_as_shared(self, recursive: bool) -> Dependency: + """Used as base case for internal_dependency""" + return self + class InternalDependency(Dependency): def __init__(self, version: str, incdirs: T.List['IncludeDirs'], compile_args: T.List[str], link_args: T.List[str], @@ -345,6 +353,20 @@ def generate_link_whole_dependency(self) -> Dependency: new_dep.libraries = [] return new_dep + def get_as_static(self, recursive: bool) -> Dependency: + new_dep = copy.copy(self) + new_dep.libraries = [lib.get('static') for lib in self.libraries] + if recursive: + new_dep.ext_deps = [dep.get_as_static(True) for dep in self.ext_deps] + return new_dep + + def get_as_shared(self, recursive: bool) -> Dependency: + new_dep = copy.copy(self) + new_dep.libraries = [lib.get('shared') for lib in self.libraries] + if recursive: + new_dep.ext_deps = [dep.get_as_shared(True) for dep in self.ext_deps] + return new_dep + class HasNativeKwarg: def __init__(self, kwargs: T.Dict[str, T.Any]): self.for_machine = self.get_for_machine_from_kwargs(kwargs) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 9de0f8762e17..bd4d1596231a 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -31,7 +31,7 @@ from ..interpreterbase import Disabler, disablerIfNotFound from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureBroken, FeatureNewKwargs from ..interpreterbase import ObjectHolder, ContextManagerObject -from ..interpreterbase import stringifyUserArguments +from ..interpreterbase import stringifyUserArguments, resolve_second_level_holders from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule from ..optinterpreter import optname_regex @@ -690,6 +690,7 @@ def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwa KwargInfo('version', (str, NoneType)), KwargInfo('objects', ContainerTypeInfo(list, build.ExtractedObjects), listify=True, default=[], since='1.1.0'), ) + @noSecondLevelHolderResolving def func_declare_dependency(self, node: mparser.BaseNode, args: T.List[TYPE_var], kwargs: kwtypes.FuncDeclareDependency) -> dependencies.Dependency: deps = kwargs['dependencies'] @@ -1875,6 +1876,7 @@ def func_shared_lib(self, node: mparser.BaseNode, @permittedKwargs(known_library_kwargs) @typed_pos_args('both_libraries', str, varargs=SOURCES_VARARGS) @typed_kwargs('both_libraries', *LIBRARY_KWS, allow_unknown=True) + @noSecondLevelHolderResolving def func_both_lib(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.BothLibraries: @@ -1892,6 +1894,7 @@ def func_shared_module(self, node: mparser.BaseNode, @permittedKwargs(known_library_kwargs) @typed_pos_args('library', str, varargs=SOURCES_VARARGS) @typed_kwargs('library', *LIBRARY_KWS, allow_unknown=True) + @noSecondLevelHolderResolving def func_library(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.Executable: @@ -1909,12 +1912,16 @@ def func_jar(self, node: mparser.BaseNode, @permittedKwargs(known_build_target_kwargs) @typed_pos_args('build_target', str, varargs=SOURCES_VARARGS) @typed_kwargs('build_target', *BUILD_TARGET_KWS, allow_unknown=True) + @noSecondLevelHolderResolving def func_build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.BuildTarget ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary, build.SharedModule, build.BothLibraries, build.Jar]: target_type = kwargs['target_type'] + if target_type not in {'both_libraries', 'library'}: + args, kwargs = resolve_second_level_holders(args, kwargs) + if target_type == 'executable': return self.build_target(node, args, kwargs, build.Executable) elif target_type == 'shared_library': @@ -2158,10 +2165,11 @@ def func_run_target(self, node: mparser.FunctionNode, args: T.Tuple[str], return tg @FeatureNew('alias_target', '0.52.0') - @typed_pos_args('alias_target', str, varargs=build.Target, min_varargs=1) + @typed_pos_args('alias_target', str, varargs=(build.Target, build.BothLibraries), min_varargs=1) @noKwargs - def func_alias_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[build.Target]], - kwargs: 'TYPE_kwargs') -> build.AliasTarget: + @noSecondLevelHolderResolving + def func_alias_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[T.Union[build.Target, build.BothLibraries]]], + kwargs: TYPE_kwargs) -> build.AliasTarget: name, deps = args if any(isinstance(d, build.RunTarget) for d in deps): FeatureNew.single_use('alias_target that depends on run_targets', '0.60.0', self.subproject) @@ -3229,6 +3237,11 @@ def add_target(self, name: str, tobj: build.Target) -> None: def build_both_libraries(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.BothLibraries: shared_lib = self.build_target(node, args, kwargs, build.SharedLibrary) static_lib = self.build_target(node, args, kwargs, build.StaticLibrary) + preferred_library = self.coredata.get_option(OptionKey('default_both_libraries')) + if preferred_library == 'auto': + preferred_library = self.coredata.get_option(OptionKey('default_library')) + if preferred_library == 'both': + preferred_library = 'shared' if self.backend.name == 'xcode': # Xcode is a bit special in that you can't (at least for the moment) @@ -3260,14 +3273,16 @@ def build_both_libraries(self, node: mparser.BaseNode, args: T.Tuple[str, Source # Keep only compilers used for linking static_lib.compilers = {k: v for k, v in static_lib.compilers.items() if k in compilers.clink_langs} - return build.BothLibraries(shared_lib, static_lib) + return build.BothLibraries(shared_lib, static_lib, preferred_library) def build_library(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library): default_library = self.coredata.get_option(OptionKey('default_library', subproject=self.subproject)) assert isinstance(default_library, str), 'for mypy' if default_library == 'shared': + args, kwargs = resolve_second_level_holders(args, kwargs) return self.build_target(node, args, T.cast('kwtypes.StaticLibrary', kwargs), build.SharedLibrary) elif default_library == 'static': + args, kwargs = resolve_second_level_holders(args, kwargs) return self.build_target(node, args, T.cast('kwtypes.SharedLibrary', kwargs), build.StaticLibrary) elif default_library == 'both': return self.build_both_libraries(node, args, kwargs) diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 155cfd23e56e..2cd55321bfcb 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -41,6 +41,10 @@ class EnvironmentSeparatorKW(TypedDict): separator: str + class InternalDependencyAsKW(TypedDict): + + recursive: bool + _ERROR_MSG_KW: KwargInfo[T.Optional[str]] = KwargInfo('error_message', (str, NoneType)) @@ -462,6 +466,8 @@ def __init__(self, dep: Dependency, interpreter: 'Interpreter'): 'include_type': self.include_type_method, 'as_system': self.as_system_method, 'as_link_whole': self.as_link_whole_method, + 'as_static': self.as_static_method, + 'as_shared': self.as_shared_method, }) def found(self) -> bool: @@ -580,6 +586,28 @@ def as_link_whole_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> D new_dep = self.held_object.generate_link_whole_dependency() return new_dep + @FeatureNew('dependency.as_static', '1.6.0') + @noPosargs + @typed_kwargs( + 'dependency.as_static', + KwargInfo('recursive', bool, default=False), + ) + def as_static_method(self, args: T.List[TYPE_var], kwargs: InternalDependencyAsKW) -> Dependency: + if not isinstance(self.held_object, InternalDependency): + raise InterpreterException('as_static method is only supported on declare_dependency() objects') + return self.held_object.get_as_static(kwargs['recursive']) + + @FeatureNew('dependency.as_shared', '1.6.0') + @noPosargs + @typed_kwargs( + 'dependency.as_shared', + KwargInfo('recursive', bool, default=False), + ) + def as_shared_method(self, args: T.List[TYPE_var], kwargs: InternalDependencyAsKW) -> Dependency: + if not isinstance(self.held_object, InternalDependency): + raise InterpreterException('as_shared method is only supported on declare_dependency() objects') + return self.held_object.get_as_shared(kwargs['recursive']) + _EXTPROG = T.TypeVar('_EXTPROG', bound=ExternalProgram) class _ExternalProgramHolder(ObjectHolder[_EXTPROG]): diff --git a/mesonbuild/options.py b/mesonbuild/options.py index 020c2e623cb4..f1f3554c27ea 100644 --- a/mesonbuild/options.py +++ b/mesonbuild/options.py @@ -63,6 +63,7 @@ 'buildtype', 'debug', 'default_library', + 'default_both_libraries', 'errorlogs', 'genvslite', 'install_umask', @@ -624,6 +625,7 @@ def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffi (OptionKey('debug'), BuiltinOption(UserBooleanOption, 'Enable debug symbols and other information', True)), (OptionKey('default_library'), BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both'], yielding=False)), + (OptionKey('default_both_libraries'), BuiltinOption(UserComboOption, 'Default library type for both_libraries', 'shared', choices=['shared', 'static', 'auto'])), (OptionKey('errorlogs'), BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True)), (OptionKey('install_umask'), BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022')), (OptionKey('layout'), BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat'])), diff --git a/test cases/common/178 bothlibraries/meson.build b/test cases/common/178 bothlibraries/meson.build index 62f2061f8d67..654d94e66f80 100644 --- a/test cases/common/178 bothlibraries/meson.build +++ b/test cases/common/178 bothlibraries/meson.build @@ -2,6 +2,7 @@ project('both libraries linking test', 'c', 'cpp') both_libs = both_libraries('mylib', 'libfile.c') dep = declare_dependency(link_with: both_libs) +alias_target('alias', both_libs) exe_shared = executable('prog-shared', 'main.c', link_with : both_libs.get_shared_lib()) exe_static = executable('prog-static', 'main.c', c_args : ['-DSTATIC_COMPILATION'], diff --git a/test cases/common/273 both libraries/meson.build b/test cases/common/273 both libraries/meson.build new file mode 100644 index 000000000000..00da1c8e6cf5 --- /dev/null +++ b/test cases/common/273 both libraries/meson.build @@ -0,0 +1,113 @@ +project( + 'test both libraries', + 'c', + meson_version: '>= 1.6.0', +) + +expected = 0 + + +with_bl = both_libraries( + 'with_bl', + files('src/both_libraries.c'), + c_shared_args: ['-DEXPORT'], +) + +with_bl_dep = declare_dependency( + link_with: with_bl, +) + + +if get_option('use_dep') + lib_deps = [with_bl_dep] + lib_links = [] +else + lib_deps = [] + lib_links = [with_bl] +endif + + +with_library = library( + 'with_library', + files('src/library.c'), + c_shared_args: ['-DEXPORT'], + link_with: lib_links, + dependencies: lib_deps, +) + +with_library_dep = declare_dependency( + link_with: with_library, +) + + +if get_option('default_library') == 'shared' + expected += 1 + if get_option('default_both_libraries') in ['shared', 'auto'] + expected += 1 + endif +elif get_option('default_library') == 'both' + if get_option('default_both_libraries') in ['shared', 'auto'] + expected += 2 + endif +else + if get_option('default_both_libraries') == 'shared' + expected += 1 + endif +endif + + +if get_option('use_dep') + main_deps = [with_library_dep] + main_links = [] +else + main_deps = [] + main_links = [with_library] +endif + +main = executable( + 'main', + files('src/main.c'), + c_args: [f'-DEXPECTED=@expected@'], + link_with: main_links, + dependencies: main_deps, +) +test('test both libs', main) + + +if get_option('default_library') == 'both' and get_option('default_both_libraries') == 'auto' + # With those options, even if the both_libraries defaults to 'shared', + # 'static' version is used when linking to the static part of another both_libraries. + + if get_option('use_dep') + main_static_deps = [with_library_dep.as_static(recursive: true)] + main_static_links = [] + else + main_static_deps = [] + main_static_links = [with_library.get_static_lib()] + endif + main_static = executable( + 'main_static', + files('src/main.c'), + c_args: [f'-DEXPECTED=0'], + link_with: main_static_links, + dependencies: main_static_deps, + ) + test('test static', main_static) + + + if get_option('use_dep') + main_shared_deps = [with_library_dep.as_shared(recursive: true)] + main_shared_links = [] + else + main_shared_deps = [] + main_shared_links = [with_library.get_shared_lib()] + endif + main_shared = executable( + 'main_shared', + files('src/main.c'), + c_args: [f'-DEXPECTED=2'], + link_with: main_shared_links, + dependencies: main_shared_deps, + ) + test('test shared', main_shared) +endif diff --git a/test cases/common/273 both libraries/meson.options b/test cases/common/273 both libraries/meson.options new file mode 100644 index 000000000000..2e3c357ae0b2 --- /dev/null +++ b/test cases/common/273 both libraries/meson.options @@ -0,0 +1 @@ +option('use_dep', type: 'boolean', value: false) diff --git a/test cases/common/273 both libraries/src/api.h b/test cases/common/273 both libraries/src/api.h new file mode 100644 index 000000000000..a20ded3642d4 --- /dev/null +++ b/test cases/common/273 both libraries/src/api.h @@ -0,0 +1,15 @@ +#pragma once + +#if defined EXPORT + #if defined _WIN32 || defined __CYGWIN__ + #define API __declspec(dllexport) + #else + #if defined __GNUC__ + #define API __attribute__((visibility("default"))) + #else + #define API + #endif + #endif +#else + #define API +#endif diff --git a/test cases/common/273 both libraries/src/both_libraries.c b/test cases/common/273 both libraries/src/both_libraries.c new file mode 100644 index 000000000000..ab1bd1fd9965 --- /dev/null +++ b/test cases/common/273 both libraries/src/both_libraries.c @@ -0,0 +1,10 @@ +#include "both_libraries.h" + +int both_libraries_function(void) +{ +#if defined EXPORT + return 1; +#else + return 0; +#endif +} diff --git a/test cases/common/273 both libraries/src/both_libraries.h b/test cases/common/273 both libraries/src/both_libraries.h new file mode 100644 index 000000000000..39c4c8430154 --- /dev/null +++ b/test cases/common/273 both libraries/src/both_libraries.h @@ -0,0 +1,5 @@ +#pragma once + +#include "api.h" + +int API both_libraries_function(void); diff --git a/test cases/common/273 both libraries/src/library.c b/test cases/common/273 both libraries/src/library.c new file mode 100644 index 000000000000..bdd965f7fb96 --- /dev/null +++ b/test cases/common/273 both libraries/src/library.c @@ -0,0 +1,12 @@ +#include "library.h" +#include "both_libraries.h" + +int library_function(void) +{ + int sum = both_libraries_function(); +#if defined EXPORT + return sum + 1; +#else + return sum; +#endif +} diff --git a/test cases/common/273 both libraries/src/library.h b/test cases/common/273 both libraries/src/library.h new file mode 100644 index 000000000000..7f57af4f136d --- /dev/null +++ b/test cases/common/273 both libraries/src/library.h @@ -0,0 +1,5 @@ +#pragma once + +#include "api.h" + +int API library_function(void); diff --git a/test cases/common/273 both libraries/src/main.c b/test cases/common/273 both libraries/src/main.c new file mode 100644 index 000000000000..1b367896d189 --- /dev/null +++ b/test cases/common/273 both libraries/src/main.c @@ -0,0 +1,8 @@ +#include "library.h" + + +int main(void) +{ + int sum = library_function(); + return sum == EXPECTED ? 0 : 1; +} diff --git a/test cases/common/273 both libraries/test.json b/test cases/common/273 both libraries/test.json new file mode 100644 index 000000000000..2aba26e48a3a --- /dev/null +++ b/test cases/common/273 both libraries/test.json @@ -0,0 +1,20 @@ +{ + "matrix": { + "options": { + "default_library": [ + { "val": "shared" }, + { "val": "static" }, + { "val": "both" } + ], + "default_both_libraries": [ + { "val": "shared" }, + { "val": "static" }, + { "val": "auto" } + ], + "use_dep": [ + { "val": false }, + { "val": true } + ] + } + } +}