summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2025-10-15 11:33:51 -0700
committerDylan Baker <dylan@pnwbakers.com>2025-10-20 09:22:25 -0700
commit28e1684abaa8c6fe6e06048bf58f2b0e6b530763 (patch)
treea2ccc9543de7767fcd93f72783723be10ef34406
parent16d84666b9072245ff7c5960ad9f1948fbdfd32b (diff)
downloadmeson-28e1684abaa8c6fe6e06048bf58f2b0e6b530763.tar.gz
build: Ensure that `vala_*` properties always exist, and are correct
This allows us to do a lot less proxy checking for vala, and lot more "If this thing says it's going to output vala, it's going to output vala. By only setting them when they use vala, we can also be sure that the fields aren't meaningless.
-rw-r--r--mesonbuild/backend/ninjabackend.py51
-rw-r--r--mesonbuild/build.py44
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py6
3 files changed, 60 insertions, 41 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 50917aeef..f1f28043c 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -748,7 +748,7 @@ class NinjaBackend(backends.Backend):
for src in genlist.get_outputs():
if self.environment.is_header(src):
header_deps.append(self.get_target_generated_dir(target, genlist, src))
- if 'vala' in target.compilers and not isinstance(target, build.Executable):
+ if target.vala_header:
vala_header = File.from_built_file(self.get_target_dir(target), target.vala_header)
header_deps.append(vala_header)
# Recurse and find generated headers
@@ -923,7 +923,7 @@ class NinjaBackend(backends.Backend):
# a language that is handled below, such as C or C++
transpiled_sources: T.List[str]
- if 'vala' in target.compilers:
+ if target.uses_vala():
# Sources consumed by valac are filtered out. These only contain
# C/C++ sources, objects, generated libs, and unknown sources now.
target_sources, generated_sources, \
@@ -1614,7 +1614,7 @@ class NinjaBackend(backends.Backend):
description = 'Creating JAR $out'
self.add_rule(NinjaRule(rule, command, [], description))
- def determine_dep_vapis(self, target) -> T.List[str]:
+ def determine_dep_vapis(self, target: build.BuildTarget) -> T.List[str]:
"""
Peek into the sources of BuildTargets we're linking with, and if any of
them was built with Vala, assume that it also generated a .vapi file of
@@ -1623,16 +1623,15 @@ class NinjaBackend(backends.Backend):
"""
result: OrderedSet[str] = OrderedSet()
for dep in itertools.chain(target.link_targets, target.link_whole_targets):
- if not dep.is_linkable_target():
+ if not (isinstance(dep, build.BuildTarget) and dep.is_linkable_target()):
continue
for i in dep.sources:
- if hasattr(i, 'fname'):
- i = i.fname
if i.split('.')[-1] in compilers.lang_suffixes['vala']:
- vapiname = dep.vala_vapi
- fullname = os.path.join(self.get_target_dir(dep), vapiname)
- result.add(fullname)
- break
+ if dep.vala_vapi is not None:
+ vapiname = dep.vala_vapi
+ fullname = os.path.join(self.get_target_dir(dep), vapiname)
+ result.add(fullname)
+ break
return list(result)
def split_vala_sources(self, t: build.BuildTarget) -> \
@@ -1751,28 +1750,30 @@ class NinjaBackend(backends.Backend):
# Library name
args += ['--library', target.name]
# Outputted header
- hname = os.path.join(self.get_target_dir(target), target.vala_header)
- args += ['--header', hname]
- if self.is_unity(target):
- # Without this the declarations will get duplicated in the .c
- # files and cause a build failure when all of them are
- # #include-d in one .c file.
- # https://github.com/mesonbuild/meson/issues/1969
- args += ['--use-header']
- valac_outputs.append(hname)
+ if target.vala_header is not None:
+ hname = os.path.join(self.get_target_dir(target), target.vala_header)
+ args += ['--header', hname]
+ if self.is_unity(target):
+ # Without this the declarations will get duplicated in the .c
+ # files and cause a build failure when all of them are
+ # #include-d in one .c file.
+ # https://github.com/mesonbuild/meson/issues/1969
+ args += ['--use-header']
+ valac_outputs.append(hname)
# Outputted vapi file
- vapiname = os.path.join(self.get_target_dir(target), target.vala_vapi)
- # Force valac to write the vapi and gir files in the target build dir.
- # Without this, it will write it inside c_out_dir
- args += ['--vapi', os.path.join('..', target.vala_vapi)]
- valac_outputs.append(vapiname)
+ if target.vala_vapi is not None:
+ vapiname = os.path.join(self.get_target_dir(target), target.vala_vapi)
+ # Force valac to write the vapi and gir files in the target build dir.
+ # Without this, it will write it inside c_out_dir
+ args += ['--vapi', os.path.join('..', target.vala_vapi)]
+ valac_outputs.append(vapiname)
# Install header and vapi to default locations if user requests this
if len(target.install_dir) > 1 and target.install_dir[1] is True:
target.install_dir[1] = self.environment.get_includedir()
if len(target.install_dir) > 2 and target.install_dir[2] is True:
target.install_dir[2] = os.path.join(self.environment.get_datadir(), 'vala', 'vapi')
# Generate GIR if requested
- if isinstance(target.vala_gir, str):
+ if target.vala_gir is not None:
girname = os.path.join(self.get_target_dir(target), target.vala_gir)
args += ['--gir', os.path.join('..', target.vala_gir)]
valac_outputs.append(girname)
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 201cb9a79..00be8bd57 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -816,6 +816,9 @@ class BuildTarget(Target):
self.both_lib: T.Optional[T.Union[StaticLibrary, SharedLibrary]] = None
# Track build_rpath entries so we can remove them at install time
self.rpath_dirs_to_remove: T.Set[bytes] = set()
+ self.vala_header: T.Optional[str] = None
+ self.vala_vapi: T.Optional[str] = None
+ self.vala_gir: T.Optional[str] = None
self.process_sourcelist(sources)
# Objects can be:
# 1. Preexisting objects provided by the user with the `objects:` kwarg
@@ -835,6 +838,7 @@ class BuildTarget(Target):
self.link_whole_targets.clear()
self.link(link_targets)
self.link_whole(link_whole_targets)
+ self._set_vala_args(kwargs)
if not any([[src for src in self.sources if not is_header(src)], self.generated, self.objects,
self.link_whole_targets, self.structured_sources, kwargs.pop('_allow_no_sources', False)]):
@@ -845,6 +849,12 @@ class BuildTarget(Target):
self.validate_install()
self.check_module_linking()
+ def _set_vala_args(self, kwargs: BuildTargetKeywordArguments) -> None:
+ if self.uses_vala():
+ self.vala_header = kwargs.get('vala_header') or self.name + '.h'
+ self.vala_vapi = kwargs.get('vala_vapi') or self.name + '.vapi'
+ self.vala_gir = kwargs.get('vala_gir')
+
def post_init(self) -> None:
''' Initialisations and checks requiring the final list of compilers to be known
'''
@@ -866,10 +876,14 @@ class BuildTarget(Target):
if self.structured_sources:
raise MesonException('structured sources are only supported in Rust targets')
- if 'vala' in self.compilers and self.is_linkable_target():
- self.outputs += [self.vala_header, self.vala_vapi]
- self.install_tag += ['devel', 'devel']
- if self.vala_gir:
+ if self.is_linkable_target():
+ if self.vala_header is not None:
+ self.outputs.append(self.vala_header)
+ self.install_tag.append('devel')
+ if self.vala_vapi is not None:
+ self.outputs.append(self.vala_vapi)
+ self.install_tag.append('devel')
+ if self.vala_gir is not None:
self.outputs.append(self.vala_gir)
self.install_tag.append('devel')
@@ -1246,11 +1260,6 @@ class BuildTarget(Target):
self.add_pch('c', extract_as_list(kwargs, 'c_pch'))
self.add_pch('cpp', extract_as_list(kwargs, 'cpp_pch'))
- if not isinstance(self, Executable) or kwargs.get('export_dynamic', False):
- self.vala_header = kwargs.get('vala_header') or self.name + '.h'
- self.vala_vapi = kwargs.get('vala_vapi') or self.name + '.vapi'
- self.vala_gir = kwargs.get('vala_gir')
-
self.link_args = extract_as_list(kwargs, 'link_args')
for i in self.link_args:
if not isinstance(i, str):
@@ -1746,6 +1755,9 @@ class BuildTarget(Target):
def uses_fortran(self) -> bool:
return 'fortran' in self.compilers
+ def uses_vala(self) -> bool:
+ return 'vala' in self.compilers
+
def uses_swift_cpp_interop(self) -> bool:
return self.swift_interoperability_mode == 'cpp' and 'swift' in self.compilers
@@ -2169,13 +2181,13 @@ class Executable(BuildTarget):
environment: Environment,
compilers: T.Dict[str, 'Compiler'],
kwargs: ExecutableKeywordArguments):
+ self.export_dynamic = kwargs.get('export_dynamic', False)
super().__init__(name, subdir, subproject, for_machine, sources, structured_sources, objects,
environment, compilers, kwargs)
self.win_subsystem = kwargs.get('win_subsystem') or 'console'
self.pie = self._extract_pic_pie(kwargs, 'pie', 'b_pie')
assert kwargs.get('android_exe_type') is None or kwargs.get('android_exe_type') in {'application', 'executable'}
# Check for export_dynamic
- self.export_dynamic = kwargs.get('export_dynamic', False)
self.implib_name = kwargs.get('implib')
# Only linkwithable if using export_dynamic
self.is_linkwithable = self.export_dynamic
@@ -2185,6 +2197,12 @@ class Executable(BuildTarget):
self.vs_module_defs: T.Optional[File] = None
self.process_vs_module_defs_kw(kwargs)
+ def _set_vala_args(self, kwargs: BuildTargetKeywordArguments) -> None:
+ # These don't get generated if the executable doesn't have
+ # export_dynamic set to true.
+ if self.export_dynamic:
+ super()._set_vala_args(kwargs)
+
def post_init(self) -> None:
super().post_init()
machine = self.environment.machines[self.for_machine]
@@ -2286,7 +2304,7 @@ class Executable(BuildTarget):
"""
return self.debug_filename
- def is_linkable_target(self):
+ def is_linkable_target(self) -> bool:
return self.is_linkwithable
def get_command(self) -> 'ImmutableListProtocol[str]':
@@ -2429,7 +2447,7 @@ class StaticLibrary(BuildTarget):
else:
self.rust_crate_type = 'staticlib' if rust_abi == 'c' else 'rlib'
- def is_linkable_target(self):
+ def is_linkable_target(self) -> bool:
return True
def is_internal(self) -> bool:
@@ -2724,7 +2742,7 @@ class SharedLibrary(BuildTarget):
def type_suffix(self):
return "@sha"
- def is_linkable_target(self):
+ def is_linkable_target(self) -> bool:
return True
def set_static(self, static_library: StaticLibrary) -> None:
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index d5a78c10e..c4f56091a 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -993,7 +993,7 @@ class BuildTargetHolder(ObjectHolder[_BuildTarget]):
@noKwargs
@InterpreterObject.method('vala_header')
def vala_header_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> mesonlib.File:
- if not hasattr(self._target_object, 'vala_header'):
+ if self._target_object.vala_header is None:
raise mesonlib.MesonException("Attempted to get a Vala header from a target that doesn't generate one")
assert self.interpreter.backend is not None, 'for mypy'
@@ -1005,7 +1005,7 @@ class BuildTargetHolder(ObjectHolder[_BuildTarget]):
@noKwargs
@InterpreterObject.method('vala_vapi')
def vala_vapi_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> mesonlib.File:
- if not hasattr(self._target_object, 'vala_vapi'):
+ if self._target_object.vala_vapi is None:
raise mesonlib.MesonException("Attempted to get a Vala VAPI from a target that doesn't generate one")
assert self.interpreter.backend is not None, 'for mypy'
@@ -1017,7 +1017,7 @@ class BuildTargetHolder(ObjectHolder[_BuildTarget]):
@noKwargs
@InterpreterObject.method('vala_gir')
def vala_gir_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> mesonlib.File:
- if not hasattr(self._target_object, 'vala_gir'):
+ if self._target_object.vala_gir is None:
raise mesonlib.MesonException("Attempted to get a Vala GIR from a target that doesn't generate one")
assert self.interpreter.backend is not None, 'for mypy'