summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Builtin-options.md3
-rw-r--r--docs/markdown/snippets/default_both_libraries.md7
-rw-r--r--mesonbuild/build.py35
-rw-r--r--mesonbuild/interpreter/interpreter.py10
-rw-r--r--test cases/common/273 both libraries/meson.build65
-rw-r--r--test cases/common/273 both libraries/meson.options1
-rw-r--r--test cases/common/273 both libraries/src/both_libraries.c10
-rw-r--r--test cases/common/273 both libraries/src/both_libraries.h5
-rw-r--r--test cases/common/273 both libraries/src/library.c6
-rw-r--r--test cases/common/273 both libraries/src/main.c2
-rw-r--r--test cases/common/273 both libraries/test.json4
11 files changed, 122 insertions, 26 deletions
diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md
index 178f793e4..2018b9575 100644
--- a/docs/markdown/Builtin-options.md
+++ b/docs/markdown/Builtin-options.md
@@ -187,6 +187,9 @@ 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
diff --git a/docs/markdown/snippets/default_both_libraries.md b/docs/markdown/snippets/default_both_libraries.md
index 279c43d22..dc9cb6bca 100644
--- a/docs/markdown/snippets/default_both_libraries.md
+++ b/docs/markdown/snippets/default_both_libraries.md
@@ -2,3 +2,10 @@
`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/mesonbuild/build.py b/mesonbuild/build.py
index 122d94774..b86a6a2a6 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -138,14 +138,6 @@ def get_target_macos_dylib_install_name(ld) -> str:
return ''.join(name)
-def extract_targets_as_list(
- kwargs: T.Dict[str, T.Sequence[LibTypes]],
- key: T.Literal['link_with', 'link_whole'],
- self_libs: T.List[LibTypes]) -> T.List[LibTypes]:
- lib_list = listify(kwargs.get(key, [])) + self_libs
- return [t.get_default_object() if isinstance(t, BothLibraries) else t for t in lib_list]
-
-
class InvalidArguments(MesonException):
pass
@@ -791,8 +783,8 @@ class BuildTarget(Target):
# 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_targets_as_list(kwargs, 'link_with', self.link_targets)
- link_whole_targets = extract_targets_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)
@@ -1740,6 +1732,20 @@ class BuildTarget(Target):
'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]
+
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'.
@@ -2495,7 +2501,14 @@ class BothLibraries(SecondLevelHolder):
def __repr__(self) -> str:
return f'<BothLibraries: static={repr(self.static)}; shared={repr(self.shared)}>'
- def get_default_object(self) -> BuildTarget:
+ def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> T.Union[StaticLibrary, SharedLibrary]:
+ 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':
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index e3e1e5b67..7eac40bb8 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -31,7 +31,7 @@ from ..interpreterbase import InterpreterException, InvalidArguments, InvalidCod
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
@@ -1876,6 +1876,7 @@ class Interpreter(InterpreterBase, HoldableObject):
@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:
@@ -1893,6 +1894,7 @@ class Interpreter(InterpreterBase, HoldableObject):
@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:
@@ -1910,12 +1912,16 @@ class Interpreter(InterpreterBase, HoldableObject):
@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':
@@ -3272,8 +3278,10 @@ class Interpreter(InterpreterBase, HoldableObject):
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/test cases/common/273 both libraries/meson.build b/test cases/common/273 both libraries/meson.build
index b80a9ce7d..de7668ce4 100644
--- a/test cases/common/273 both libraries/meson.build
+++ b/test cases/common/273 both libraries/meson.build
@@ -7,38 +7,81 @@ project(
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
-mainlink = executable(
- 'mainlink',
+main = executable(
+ 'main',
files('src/main.c'),
c_args: [f'-DEXPECTED=@expected@'],
- link_with: [with_library],
+ link_with: main_links,
+ dependencies: main_deps,
)
-test('link with', mainlink)
+test('test both libs', main)
-maindep = executable(
- 'maindep',
- files('src/main.c'),
- c_args: [f'-DEXPECTED=@expected@'],
- dependencies: [with_library_dep],
-)
-test('use dep', maindep)
+
+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.
+ main_static = executable(
+ 'main_static',
+ files('src/main.c'),
+ c_args: [f'-DEXPECTED=0'],
+ link_with: with_library.get_static_lib(),
+ )
+ test('test static', main_static)
+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 000000000..2e3c357ae
--- /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/both_libraries.c b/test cases/common/273 both libraries/src/both_libraries.c
new file mode 100644
index 000000000..ab1bd1fd9
--- /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 000000000..39c4c8430
--- /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
index decdb6ce9..bdd965f7f 100644
--- a/test cases/common/273 both libraries/src/library.c
+++ b/test cases/common/273 both libraries/src/library.c
@@ -1,10 +1,12 @@
#include "library.h"
+#include "both_libraries.h"
int library_function(void)
{
+ int sum = both_libraries_function();
#if defined EXPORT
- return 1;
+ return sum + 1;
#else
- return 0;
+ return sum;
#endif
}
diff --git a/test cases/common/273 both libraries/src/main.c b/test cases/common/273 both libraries/src/main.c
index 340322e45..1b367896d 100644
--- a/test cases/common/273 both libraries/src/main.c
+++ b/test cases/common/273 both libraries/src/main.c
@@ -4,5 +4,5 @@
int main(void)
{
int sum = library_function();
- return sum == EXPECTED ? 0 : sum;
+ 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
index 08aa54790..2aba26e48 100644
--- a/test cases/common/273 both libraries/test.json
+++ b/test cases/common/273 both libraries/test.json
@@ -10,6 +10,10 @@
{ "val": "shared" },
{ "val": "static" },
{ "val": "auto" }
+ ],
+ "use_dep": [
+ { "val": false },
+ { "val": true }
]
}
}