interpreter, modules: add current_build_dir and use it for joining to environment.get_build_dir()

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini authored and Paolo Bonzini committed 2026-10-30 19:32:29 +01:00
1 parent 9bf28f40e9
commit 83fba12da2
14 files changed
+62 -40

No files matched your search

+2 -2
View File
@@ -124,13 +124,13 @@ class PackageState:
def has_both_machines(self) -> bool:
return bool(self.cfg.host and self.cfg.build)
def get_env_dict(self, environment: Environment, subdir: str) -> T.Dict[str, str]:
def get_env_dict(self, environment: Environment, subdir: str, build_subdir: str) -> T.Dict[str, str]:
"""Get environment variables for this package."""
# Common variables for build.rs and crates
# https://doc.rust-lang.org/cargo/reference/environment-variables.html
# OUT_DIR is the directory where build.rs generate files. In our case,
# it's the directory where meson/meson.build places generated files.
out_dir = os.path.join(environment.build_dir, subdir, 'meson')
out_dir = os.path.join(environment.build_dir, build_subdir, 'meson')
os.makedirs(out_dir, exist_ok=True)
version_arr = self.manifest.package.version.split('.')
version_arr += [''] * (4 - len(version_arr))
+15 -5
View File
@@ -2864,7 +2864,7 @@ class Interpreter(InterpreterBase, HoldableObject):
raise InvalidArguments(f'Build subdir "{build_subdir}" in "{target}" exists in source tree.')
if '..' in build_subdir:
raise InvalidArguments(f'Build subdir "{build_subdir}" in "{target}" contains ..')
self.create_build_subdir(os.path.join(self.subdir, build_subdir))
self.create_build_subdir(os.path.join(self.current_build_dir(), build_subdir))
@TypedArgs(
'configure_file',
@@ -2971,7 +2971,7 @@ class Interpreter(InterpreterBase, HoldableObject):
build_subdir = kwargs['build_subdir']
self.validate_build_subdir(build_subdir, output)
ofile_rpath = os.path.join(self.subdir, build_subdir, output)
ofile_rpath = os.path.join(self.current_build_dir(), build_subdir, output)
if ofile_rpath in self.configure_file_outputs:
mesonbuildfile = os.path.join(self.subdir, 'meson.build')
current_call = f"{mesonbuildfile}:{self.current_node.lineno}"
@@ -3058,7 +3058,7 @@ class Interpreter(InterpreterBase, HoldableObject):
elif kwargs['copy']:
if len(inputs_abs) != 1:
raise InterpreterException('Exactly one input file must be given in copy mode')
self.create_build_subdir(self.subdir)
self.create_build_subdir(self.current_build_dir())
shutil.copyfile(inputs_abs[0], ofile_abs)
src_stat = os.stat(inputs_abs[0])
os.utime(ofile_abs, ns=(src_stat.st_atime_ns, src_stat.st_mtime_ns))
@@ -3083,7 +3083,7 @@ class Interpreter(InterpreterBase, HoldableObject):
install_tag = kwargs['install_tag']
self.build.data.append(build.Data([cfile], idir, idir_name, install_mode, self.subproject,
install_tag=install_tag, data_type='configure'))
return mesonlib.File.from_built_file(self.subdir, output)
return mesonlib.File.from_built_file(self.current_build_dir(), output)
def extract_incdirs(self, prospectives: T.List[T.Union[str, build.IncludeDirs]],
is_d_import_dirs: bool = False
@@ -3569,7 +3569,7 @@ class Interpreter(InterpreterBase, HoldableObject):
self.environment.build_dir)
results.append(mesonlib.File.from_built_relative(rel))
else:
results.append(mesonlib.File.from_built_file(self.subdir, s))
results.append(mesonlib.File.from_built_file(self.current_build_dir(), s))
continue
except SandboxViolationError:
if not self.relaxed(InterpreterRuleRelaxation.ALLOW_SANDBOX_VIOLATION):
@@ -4232,6 +4232,16 @@ class Interpreter(InterpreterBase, HoldableObject):
def is_subproject(self) -> bool:
return self.subproject != ''
def current_build_dir(self) -> str:
"""Return the directory of the current meson.build in the build tree, relative to the build directory.
Unlike self.subdir, which is relative to the source tree, this has a different
prefix for subprojects that are built for the build machine.
"""
project = self.current_build_project()
# self.subdir is always inside the directory of the subproject.
return project.builddir + self.subdir[len(project.subdir):]
@TypedArgs(
'set_variable',
pos_types=[
+1 -1
View File
@@ -202,7 +202,7 @@ class MesonMain(MesonInterpreterObject):
@InterpreterObject.method('current_build_dir')
def current_build_dir_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
src = self.interpreter.environment.build_dir
sub = self.interpreter.subdir
sub = self.interpreter.current_build_dir()
if sub == '':
return src
return os.path.join(src, sub)
+2 -1
View File
@@ -42,6 +42,7 @@ class ModuleState:
self.subproject_dir = interpreter.subproject_dir
self.subproject = interpreter.subproject
self.subdir = interpreter.subdir
self.current_build_dir = interpreter.current_build_dir()
self.root_subdir = interpreter.root_subdir
self.environment = interpreter.environment
self.project_name = interpreter.active_projectname
@@ -72,7 +73,7 @@ class ModuleState:
dirs_str.extend([f'{prefix}{i}' for i in dirs.abs_string_list(srcdir, builddir)])
if implicit:
build_cur_dir = os.path.normpath(os.path.join(builddir, self.subdir))
build_cur_dir = os.path.normpath(os.path.join(builddir, self.current_build_dir))
dirs_str.append(f'{prefix}{build_cur_dir}')
source_cur_dir = os.path.normpath(os.path.join(srcdir, self.subdir))
dirs_str.append(f'{prefix}{source_cur_dir}')
+5 -5
View File
@@ -375,7 +375,7 @@ class QtBaseModule(ExtensionModule):
path_from_rcc = os.path.normpath(os.path.join(rcc_dirname, resource_path))
# a)
if path_from_rcc.startswith(state.environment.build_dir):
result.append(File(is_built=True, subdir=state.subdir, fname=resource_path))
result.append(File(is_built=True, subdir=state.current_build_dir, fname=resource_path))
# b)
else:
result.append(File(is_built=False, subdir=state.subdir, fname=path_from_rcc))
@@ -706,7 +706,7 @@ class QtBaseModule(ExtensionModule):
raise MesonException('qt.compile_translations: Cannot specify both ts_files and qresource')
if os.path.dirname(qresource) != '':
raise MesonException('qt.compile_translations: qresource file name must not contain a subdirectory.')
qresource_file = File.from_built_file(state.subdir, qresource)
qresource_file = File.from_built_file(state.current_build_dir, qresource)
infile_abs = os.path.join(state.environment.source_dir, qresource_file.relative_name())
outfile_abs = os.path.join(state.environment.build_dir, qresource_file.relative_name())
os.makedirs(os.path.dirname(outfile_abs), exist_ok=True)
@@ -773,7 +773,7 @@ class QtBaseModule(ExtensionModule):
content_files.append(s)
elif isinstance(s, build.GeneratedList):
for gen_src in s.get_outputs():
content_files.append(File.from_built_file(state.subdir, gen_src))
content_files.append(File.from_built_file(state.current_build_dir, gen_src))
else:
content_files.append(File.from_source_file(
state.environment.get_source_dir(),
@@ -784,7 +784,7 @@ class QtBaseModule(ExtensionModule):
def _gen_qrc(self, state: ModuleState, kwargs: GenQrcKwArgs) -> File:
fileout = File.from_built_file(state.subdir, kwargs['output'])
fileout = File.from_built_file(state.current_build_dir, kwargs['output'])
fileout_abs = os.path.join(state.environment.build_dir, fileout.relative_name())
if not os.path.isdir(state.environment.build_dir):
os.mkdir(state.environment.build_dir)
@@ -813,7 +813,7 @@ class QtBaseModule(ExtensionModule):
#Foo.Bar/1.0 foo.bar/auto foo.bar
import_re = re.compile(r'^(' + _MODULE_NAME_RE + r')(/((\d+(\.\d+)?)|auto))?$')
fileout = File.from_built_file(state.subdir, kwargs['output'])
fileout = File.from_built_file(state.current_build_dir, kwargs['output'])
fileout_abs = os.path.join(state.environment.build_dir, fileout.relative_name())
if not os.path.isdir(state.environment.build_dir):
os.mkdir(state.environment.build_dir)
+1 -1
View File
@@ -395,7 +395,7 @@ class CmakeModule(ExtensionModule):
name = kwargs['name']
(ofile_path, ofile_fname) = os.path.split(os.path.join(state.subdir, f'{name}Config.cmake'))
(ofile_path, ofile_fname) = os.path.split(os.path.join(state.current_build_dir, f'{name}Config.cmake'))
ofile_abs = os.path.join(state.environment.build_dir, ofile_path, ofile_fname)
install_dir = kwargs['install_dir']
+4 -3
View File
@@ -64,6 +64,7 @@ class ExternalProject(NewExtensionModule):
})
self.subdir = Path(state.subdir)
self.current_build_dir = Path(state.current_build_dir)
self.project_version = state.project_version
self.subproject = state.subproject
self.env = state.environment
@@ -74,8 +75,8 @@ class ExternalProject(NewExtensionModule):
self.user_env = env
self.src_dir = Path(self.env.get_source_dir(), self.subdir)
self.build_dir = Path(self.env.get_build_dir(), self.subdir, 'build')
self.install_dir = Path(self.env.get_build_dir(), self.subdir, 'dist')
self.build_dir = Path(self.env.get_build_dir(), self.current_build_dir, 'build')
self.install_dir = Path(self.env.get_build_dir(), self.current_build_dir, 'dist')
_p = self.env.coredata.optstore.get_value_for(OptionKey('prefix'))
assert isinstance(_p, str), 'for mypy'
self.prefix = Path(_p)
@@ -261,7 +262,7 @@ class ExternalProject(NewExtensionModule):
description='Generating external project {}',
)
idir = build.InstallDir(self.subdir.as_posix(),
idir = build.InstallDir(self.current_build_dir.as_posix(),
Path('dist', self.rel_prefix).as_posix(),
install_dir='.',
install_dir_name='.',
+10 -8
View File
@@ -1212,7 +1212,7 @@ class GnomeModule(ExtensionModule):
girfile = f'{ns}-{nsversion}.gir'
srcdir = os.path.join(state.environment.get_source_dir(), state.subdir)
builddir = os.path.join(state.environment.get_build_dir(), state.subdir)
builddir = os.path.join(state.environment.get_build_dir(), state.current_build_dir)
depends: T.List[TargetDepends] = []
# hack - this cast represents how sources are defined for the
@@ -1285,7 +1285,8 @@ class GnomeModule(ExtensionModule):
if self._gir_has_option('--sources-top-dirs'):
scan_command += ['--sources-top-dirs', os.path.join(state.environment.get_source_dir(), state.root_subdir)]
scan_command += ['--sources-top-dirs', os.path.join(state.environment.get_build_dir(), state.root_subdir)]
scan_command += ['--sources-top-dirs', os.path.join(state.environment.get_build_dir(),
state.current_build_project.builddir)]
if kwargs['doc_format'] is not None and self._gir_has_option('--doc-format'):
scan_command += ['--doc-format', kwargs['doc_format']]
@@ -1323,7 +1324,7 @@ class GnomeModule(ExtensionModule):
typelib_target = self._make_typelib_target(
state, typelib_output, typelib_cmd, generated_files, kwargs)
self._devenv_prepend('GI_TYPELIB_PATH', os.path.join(state.environment.get_build_dir(), state.subdir))
self._devenv_prepend('GI_TYPELIB_PATH', os.path.join(state.environment.get_build_dir(), state.current_build_dir))
rv = [scan_target, typelib_target]
@@ -1332,7 +1333,7 @@ class GnomeModule(ExtensionModule):
@TypedArgs('gnome.compile_schemas', kw_types=[_BUILD_BY_DEFAULT.evolve(since='0.40.0'), DEPEND_FILES_KW])
def compile_schemas(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'CompileSchemas') -> ModuleReturnValue:
srcdir = os.path.join(state.build_to_src, state.subdir)
outdir = state.subdir
outdir = state.current_build_dir
cmd: CommandList = [self._find_tool(state, 'glib-compile-schemas'), '--targetdir', outdir, srcdir]
if state.subdir == '':
@@ -1351,7 +1352,7 @@ class GnomeModule(ExtensionModule):
depend_files=state._interpreter.source_strings_to_files(kwargs['depend_files']),
description='Compiling gschemas {}',
)
self._devenv_prepend('GSETTINGS_SCHEMA_DIR', os.path.join(state.environment.get_build_dir(), state.subdir))
self._devenv_prepend('GSETTINGS_SCHEMA_DIR', os.path.join(state.environment.get_build_dir(), state.current_build_dir))
return ModuleReturnValue(target_g, [target_g])
@TypedArgs(
@@ -1569,6 +1570,7 @@ class GnomeModule(ExtensionModule):
'--sourcedir=' + state.environment.get_source_dir(),
'--builddir=' + state.environment.get_build_dir(),
'--subdir=' + state.subdir,
'--build-subdir=' + state.current_build_dir,
'--headerdirs', *header_dirs,
'--mainfile=' + main_file,
'--modulename=' + modulename,
@@ -1642,7 +1644,7 @@ class GnomeModule(ExtensionModule):
check_env = ['DOC_MODULE=' + modulename,
'DOC_MAIN_SGML_FILE=' + main_file]
check_args = (targetname + '-check', check_cmd)
check_workdir = os.path.join(state.environment.get_build_dir(), state.subdir)
check_workdir = os.path.join(state.environment.get_build_dir(), state.current_build_dir)
state.test(check_args, env=check_env, workdir=check_workdir, depends=[custom_target])
res: T.List[T.Union[build.Target, mesonlib.ExecutableSerialisation]] = [custom_target, alias_target]
if kwargs['install']:
@@ -2324,7 +2326,7 @@ class GnomeModule(ExtensionModule):
def generate_vapi(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenerateVapi') -> ModuleReturnValue:
created_values: T.List[T.Union[Dependency, build.Data]] = []
library = args[0]
build_dir = os.path.join(state.environment.get_build_dir(), state.subdir)
build_dir = os.path.join(state.environment.get_build_dir(), state.current_build_dir)
source_dir = os.path.join(state.environment.get_source_dir(), state.subdir)
pkg_cmd, vapi_depends, vapi_packages, vapi_includes, packages = self._extract_vapi_packages(state, kwargs['packages'])
cmd: CommandList = [state.find_program('vapigen'), '--quiet', f'--library={library}', f'--directory={build_dir}']
@@ -2344,7 +2346,7 @@ class GnomeModule(ExtensionModule):
elif isinstance(i, GirTarget):
link_with += self._get_vapi_link_with(i)
subdir = os.path.join(state.environment.get_build_dir(),
i.get_subdir())
i.get_builddir())
gir_file = os.path.join(subdir, i.get_outputs()[0])
cmd.append(gir_file)
inputs.append(i)
+10 -9
View File
@@ -85,10 +85,11 @@ class HotdocTargetBuilder:
self.builddir = state.environment.get_build_dir()
self.sourcedir = state.environment.get_source_dir()
self.subdir = state.subdir
self.current_build_dir = state.current_build_dir
self.build_command = state.environment.get_build_command()
self.cmd: T.List[TYPE_var] = ['conf', '--project-name', name, "--disable-incremental-build",
'--output', os.path.join(self.builddir, self.subdir, self.name + '-doc')]
'--output', os.path.join(self.builddir, self.current_build_dir, self.name + '-doc')]
self._extra_extension_paths: set[str] = set()
self.extra_depends: list[build.BuildTargetProto] = []
@@ -170,7 +171,7 @@ class HotdocTargetBuilder:
value = self.kwargs.pop('gi_c_source_roots')
value.extend([
os.path.join(self.sourcedir, self.state.root_subdir),
os.path.join(self.builddir, self.state.root_subdir)
os.path.join(self.builddir, self.state.current_build_project.builddir)
])
self.cmd += ['--gi-c-source-roots'] + value
@@ -279,7 +280,7 @@ class HotdocTargetBuilder:
if not os.path.isdir(_dir):
raise InvalidArguments(f'"{_dir}" is not a directory.')
return os.path.relpath(_dir, os.path.join(self.builddir, self.subdir))
return os.path.relpath(_dir, os.path.join(self.builddir, self.current_build_dir))
def check_forbidden_args(self) -> None:
for arg in ['conf_file']:
@@ -306,15 +307,15 @@ class HotdocTargetBuilder:
fullname = self.name + '-doc'
hotdoc_config_name = fullname + '.json'
hotdoc_config_path = os.path.join(
self.builddir, self.subdir, hotdoc_config_name)
self.builddir, self.current_build_dir, hotdoc_config_name)
with open(hotdoc_config_path, 'w', encoding='utf-8') as f:
f.write('{}')
self.cmd += ['--conf-file', hotdoc_config_path]
self.include_paths.add(os.path.join(self.builddir, self.subdir))
self.include_paths.add(os.path.join(self.builddir, self.current_build_dir))
self.include_paths.add(os.path.join(self.sourcedir, self.subdir))
depfile = os.path.join(self.builddir, self.subdir, self.name + '.deps')
depfile = os.path.join(self.builddir, self.current_build_dir, self.name + '.deps')
self.cmd += ['--deps-file-dest', depfile]
for path in self.include_paths:
@@ -326,13 +327,13 @@ class HotdocTargetBuilder:
target_cmd = self.build_command + ["--internal", "hotdoc"] + \
self.hotdoc.get_command() + ['run', '--conf-file', hotdoc_config_name] + \
['--builddir', os.path.join(self.builddir, self.subdir)]
['--builddir', os.path.join(self.builddir, self.current_build_dir)]
target = HotdocTarget(fullname,
subdir=self.subdir,
environment=self.state.environment,
hotdoc_conf=File.from_built_file(
self.subdir, hotdoc_config_name),
self.current_build_dir, hotdoc_config_name),
extra_extension_paths=self._extra_extension_paths,
extra_assets=self._extra_assets,
subprojects=self._subprojects,
@@ -367,7 +368,7 @@ class HotdocTargetBuilder:
"--install", install_from,
"--docdir", install_to,
'--name', self.name,
'--builddir', os.path.join(self.builddir, self.subdir)] +
'--builddir', os.path.join(self.builddir, self.current_build_dir)] +
self.hotdoc.get_command() +
['run', '--conf-file', hotdoc_config_name])
install_script.tag = 'doc'
+2 -2
View File
@@ -246,10 +246,10 @@ class XgettextProgram:
if estimated_cmdline_length < mesonlib.get_rsp_threshold():
return None
rsp_file = Path(self.interpreter.environment.build_dir, self.interpreter.subdir, name+'.rsp')
rsp_file = Path(self.interpreter.environment.build_dir, self.interpreter.current_build_dir(), name+'.rsp')
rsp_file.write_text(source_list, encoding='utf-8')
return mesonlib.File.from_built_file(self.interpreter.subdir, rsp_file.name)
return mesonlib.File.from_built_file(self.interpreter.current_build_dir(), rsp_file.name)
@staticmethod
def _get_source_id(sources: T.Iterable[SourcesType]) -> T.Iterable[str]:
+1 -1
View File
@@ -296,7 +296,7 @@ class RustCrate(ModuleObject):
@TypedArgs('rust_crate.env')
def env_method(self, state: ModuleState, args: T.List, kwargs: TYPE_kwargs) -> T.Dict[str, str]:
"""Returns environment variables for this package."""
return self.package.get_env_dict(state.environment, state.subdir)
return self.package.get_env_dict(state.environment, state.subdir, state.current_build_dir)
@TypedArgs('rust_crate.rust_dependency_map')
def rust_dependency_map_method(self, state: ModuleState, args: T.List, kwargs: TYPE_kwargs) -> T.Dict[str, str]:
+2 -2
View File
@@ -100,9 +100,9 @@ class SnippetsModule(NewExtensionModule):
# define {api} {api}_IMPORT extern
#endif
''')
header_path = Path(state.environment.get_build_dir(), state.subdir, header_name)
header_path = Path(state.environment.get_build_dir(), state.current_build_dir, header_name)
header_path.write_text(content, encoding='utf-8')
return mesonlib.File.from_built_file(state.subdir, header_name)
return mesonlib.File.from_built_file(state.current_build_dir, header_name)
def initialize(*args: T.Any, **kwargs: T.Any) -> SnippetsModule:
return SnippetsModule()
@@ -1,3 +1,9 @@
#include "config.h"
#if IS_CROSS_BUILD != EXPECTED_CROSS_BUILD
#error "config.h was generated for the wrong machine"
#endif
#ifndef GLOBAL_CROSS_BUILD
#error "add_global_arguments() was not applied"
#endif
@@ -1,6 +1,7 @@
project('both', 'c')
cross = meson.is_cross_build() ? 1 : 0
configure_file(output : 'config.h', configuration : {'IS_CROSS_BUILD': cross})
add_project_arguments(f'-DPROJECT_CROSS_BUILD=@cross@', language : 'c')
e = executable('main', 'main.c', c_args : f'-DEXPECTED_CROSS_BUILD=@cross@')