summaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2025-12-05 09:15:06 -0800
committerDylan Baker <dylan@pnwbakers.com>2025-12-17 14:04:17 -0800
commita152da9206891caad17fd9271aff04073e811784 (patch)
treedfbcf9fd6eb8be2906ec0f140691d48841c1e753 /mesonbuild
parent7a1655acd29e5ba50a2951ad6c8db934fa7a6eb9 (diff)
downloadmeson-a152da9206891caad17fd9271aff04073e811784.tar.gz
build|interpreter: use typed_kwargs for link_with
This replaces the long explanation of `external_library`s in the `link_with` parameter to the simpler one used by declare_dependency. Additionally, declare_dependency now checks that a target is linkable when adding it. This just catches the problem before it goes down into the build layer giving a better error message. There is a bug in the declare_dependency annotations, in that they don't mark Executable as acceptable. So I've fixed that.
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/build.py18
-rw-r--r--mesonbuild/interpreter/kwargs.py3
-rw-r--r--mesonbuild/interpreter/type_checking.py13
3 files changed, 19 insertions, 15 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 50d83fa9f..f32010917 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -796,7 +796,7 @@ class BuildTarget(Target):
self.external_deps: T.List[dependencies.Dependency] = []
self.include_dirs: T.List['IncludeDirs'] = []
self.link_language = kwargs.get('link_language')
- self.link_targets: T.List[LibTypes] = []
+ self.link_targets: T.List[BuildTargetTypes] = []
self.link_whole_targets: T.List[StaticTargetTypes] = []
self.depend_files: T.List[File] = []
self.link_depends: T.List[T.Union[File, BuildTargetTypes]] = []
@@ -1468,18 +1468,6 @@ class BuildTarget(Target):
def link(self, targets: T.List[BuildTargetTypes]) -> None:
for t in targets:
- if not isinstance(t, (Target, CustomTargetIndex)):
- if isinstance(t, dependencies.ExternalLibrary):
- raise MesonException(textwrap.dedent('''\
- An external library was used in link_with keyword argument, which
- is reserved for libraries built as part of this project. External
- libraries must be passed using the dependencies keyword argument
- instead, because they are conceptually "external dependencies",
- just like those detected with the dependency() function.
- '''))
- raise InvalidArguments(f'{t!r} is not a target.')
- if not t.is_linkable_target():
- raise InvalidArguments(f"Link target '{t!s}' is not linkable.")
if isinstance(self, StaticLibrary) and self.install and t.is_internal():
# When we're a static library and we link_with to an
# internal/convenience library, promote to link_whole.
@@ -2758,6 +2746,10 @@ class BothLibraries(SecondLevelHolder):
def get_id(self) -> str:
return self.get_default_object().get_id()
+ def is_linkable_target(self) -> bool:
+ # For polymorphism with build targets
+ return True
+
class CommandBase:
depend_files: T.List[File]
diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py
index e7d2ac9a8..6adad72e7 100644
--- a/mesonbuild/interpreter/kwargs.py
+++ b/mesonbuild/interpreter/kwargs.py
@@ -349,6 +349,7 @@ class _BaseBuildTarget(TypedDict):
link_depends: T.List[T.Union[str, File, build.GeneratedTypes]]
link_language: T.Optional[str]
link_whole: T.List[build.StaticTargetTypes]
+ link_with: T.List[build.BuildTargetTypes]
name_prefix: T.Optional[str]
name_suffix: T.Optional[str]
native: MachineChoice
@@ -494,7 +495,7 @@ class FuncDeclareDependency(TypedDict):
include_directories: T.List[T.Union[build.IncludeDirs, str]]
link_args: T.List[str]
link_whole: T.List[build.StaticTargetTypes]
- link_with: T.List[build.LibTypes]
+ link_with: T.List[build.BuildTargetTypes]
objects: T.List[build.ExtractedObjects]
sources: T.List[T.Union[FileOrString, build.GeneratedTypes]]
variables: T.Dict[str, str]
diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py
index 2d9f2a11e..3512925ee 100644
--- a/mesonbuild/interpreter/type_checking.py
+++ b/mesonbuild/interpreter/type_checking.py
@@ -440,13 +440,23 @@ D_MODULE_VERSIONS_KW: KwargInfo[T.List[T.Union[str, int]]] = KwargInfo(
_LINK_WITH_ERROR = 'Dependency and external_library objects must go in the "dependencies" keyword argument'
+def _link_with_validator(values: T.List[T.Union[BothLibraries, SharedLibrary, StaticLibrary,
+ CustomTarget, CustomTargetIndex, Jar, Executable,
+ ]]
+ ) -> T.Optional[str]:
+ for value in values:
+ if not value.is_linkable_target():
+ return f'Link target "{value!s}" is not linkable'
+ return None
+
# Allow Dependency for the better error message? But then in other cases it will list this as one of the allowed types!
LINK_WITH_KW: KwargInfo[T.List[T.Union[BothLibraries, SharedLibrary, StaticLibrary, CustomTarget, CustomTargetIndex, Jar, Executable]]] = KwargInfo(
'link_with',
ContainerTypeInfo(list, (BothLibraries, SharedLibrary, StaticLibrary, CustomTarget, CustomTargetIndex, Jar, Executable)),
listify=True,
default=[],
- extra_types={Dependency: lambda _: _LINK_WITH_ERROR}
+ extra_types={Dependency: lambda _: _LINK_WITH_ERROR},
+ validator=_link_with_validator,
)
def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, CustomTargetIndex]]) -> T.Optional[str]:
@@ -729,6 +739,7 @@ _BUILD_TARGET_KWS: T.List[KwargInfo] = [
DEPENDENCIES_KW,
INCLUDE_DIRECTORIES.evolve(name='d_import_dirs'),
LINK_WHOLE_KW,
+ LINK_WITH_KW,
_NAME_PREFIX_KW,
_NAME_PREFIX_KW.evolve(name='name_suffix', validator=_name_suffix_validator),
RUST_CRATE_TYPE_KW,