diff options
| -rw-r--r-- | docs/markdown/snippets/alias_target_of_both_libraries.md | 5 | ||||
| -rw-r--r-- | docs/markdown/snippets/dep_as_shared_as_static.md | 8 | ||||
| -rw-r--r-- | docs/yaml/functions/alias_target.yaml | 3 | ||||
| -rw-r--r-- | docs/yaml/objects/dep.yaml | 25 | ||||
| -rw-r--r-- | mesonbuild/build.py | 23 | ||||
| -rw-r--r-- | mesonbuild/dependencies/base.py | 22 | ||||
| -rw-r--r-- | mesonbuild/interpreter/interpreter.py | 7 | ||||
| -rw-r--r-- | mesonbuild/interpreter/interpreterobjects.py | 28 | ||||
| -rw-r--r-- | test cases/common/178 bothlibraries/meson.build | 1 | ||||
| -rw-r--r-- | test cases/common/273 both libraries/meson.build | 28 |
10 files changed, 143 insertions, 7 deletions
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 000000000..ab77a6556 --- /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/dep_as_shared_as_static.md b/docs/markdown/snippets/dep_as_shared_as_static.md new file mode 100644 index 000000000..a84e9eeaa --- /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 bc14f84da..983356901 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 76543d2c1..28d93d79f 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 b86a6a2a6..5eff0ed80 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1746,6 +1746,10 @@ class BuildTarget(Target): 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'. @@ -2501,7 +2505,7 @@ class BothLibraries(SecondLevelHolder): def __repr__(self) -> str: return f'<BothLibraries: static={repr(self.static)}; shared={repr(self.shared)}>' - def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> T.Union[StaticLibrary, SharedLibrary]: + def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> LibTypes: if lib_type == 'static': return self.static if lib_type == 'shared': @@ -2575,6 +2579,10 @@ class CustomTargetBase: 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' @@ -2896,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 08e81f0d7..fa278d97c 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -248,6 +248,14 @@ class Dependency(HoldableObject): 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 @@ class InternalDependency(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 7eac40bb8..bd4d15962 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2165,10 +2165,11 @@ class Interpreter(InterpreterBase, HoldableObject): 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) diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 155cfd23e..2cd55321b 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -41,6 +41,10 @@ if T.TYPE_CHECKING: separator: str + class InternalDependencyAsKW(TypedDict): + + recursive: bool + _ERROR_MSG_KW: KwargInfo[T.Optional[str]] = KwargInfo('error_message', (str, NoneType)) @@ -462,6 +466,8 @@ class DependencyHolder(ObjectHolder[Dependency]): '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 @@ class DependencyHolder(ObjectHolder[Dependency]): 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/test cases/common/178 bothlibraries/meson.build b/test cases/common/178 bothlibraries/meson.build index 62f2061f8..654d94e66 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 index de7668ce4..00da1c8e6 100644 --- a/test cases/common/273 both libraries/meson.build +++ b/test cases/common/273 both libraries/meson.build @@ -77,11 +77,37 @@ 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: with_library.get_static_lib(), + 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 |
