Fix missing build project prefixes

A build project prefix ("build.") was introduced in 499f73da1 to separate build
files from host and build targets when cross compiling subprojects.
Additional work was done in 83fba12da. However, this prefix was missing from
some places:
- for generated files, with or without `build_subdir`: those files were
  generated at the same place for both host and build targets.
- for include dirs: was erroring if it was only available in the build
  tree.
- for subdirs
- for generated ast
Additionally, extra_build_dirs were double-prefixed.
This commit is contained in:
Charles Brunet authored and Paolo Bonzini committed 2026-11-04 18:58:43 +01:00
1 parent 9706cac6af
commit fb511f0ab1
15 files changed
+109 -23

No files matched your search

+8 -8
View File
@@ -3092,19 +3092,20 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
return (rel_obj, rel_src)
@lru_cache(maxsize=None)
def generate_inc_dir(self, compiler: 'Compiler', d: str, basedir: str, is_system: bool
def generate_inc_dir(self, compiler: Compiler, d: str, inc_dir: build.IncludeDirs
) -> T.Tuple[ImmutableListProtocol[str], ImmutableListProtocol[str]]:
expdir = os.path.normpath(os.path.join(basedir, d))
expdir = os.path.join(inc_dir.curdir, d)
srctreedir = os.path.normpath(os.path.join(self.build_to_src, expdir))
sargs = compiler.get_include_args(srctreedir, is_system)
sargs = compiler.get_include_args(srctreedir, inc_dir.is_system)
# There may be include dirs where a build directory has not been
# created for some source dir. For example if someone does this:
#
# inc = include_directories('foo/bar/baz')
#
# But never subdir()s into the actual dir.
if os.path.isdir(os.path.join(self.environment.get_build_dir(), expdir)):
bargs = compiler.get_include_args(expdir, is_system)
build_subdir = os.path.normpath(inc_dir.build_project.prefix + expdir)
if os.path.isdir(os.path.join(self.environment.get_build_dir(), build_subdir)):
bargs = compiler.get_include_args(build_subdir, inc_dir.is_system)
else:
bargs = []
return (sargs, bargs)
@@ -3134,7 +3135,6 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
# external deps and must maintain the order in which they are specified.
# Hence, we must reverse the list so that the order is preserved.
for i in reversed(target.get_include_dirs()):
basedir = i.curdir
# Each directory must be added to CompilerArgs individually
# via a separate ``commands +=`` call, in reversed order.
#
@@ -3159,11 +3159,11 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
# appended at once in the original (unreversed) order, making
# the *first*-listed directory appear first instead of last.
for d in reversed(i.incdirs):
sargs, bargs = self.generate_inc_dir(compiler, d, basedir, i.is_system)
sargs, bargs = self.generate_inc_dir(compiler, d, i)
commands += sargs
commands += bargs
for d in i.extra_build_dirs:
commands += compiler.get_include_args(d, i.is_system)
commands += compiler.get_include_args(os.path.normpath(os.path.join(i.curdir, d)), i.is_system)
# Add any embed search dir arguments
for i in target.embed_dirs:
+3 -2
View File
@@ -1046,13 +1046,14 @@ class Vs2010Backend(backends.Backend):
try:
# Add source subdir first so that the build subdir overrides it
args.append('-I' + os.path.join(proj_to_src_root, curdir)) # src dir
args.append('-I' + self.relpath(curdir, target.subdir)) # build dir
args.append('-I' + self.relpath(d.build_project.prefix + curdir,
self.get_target_dir(target))) # build dir
except ValueError:
# Include is on different drive
args.append('-I' + os.path.normpath(curdir))
for i in d.extra_build_dirs:
curdir = os.path.join(d.curdir, i)
args.append('-I' + self.relpath(curdir, target.subdir)) # build dir
args.append('-I' + self.relpath(curdir, self.get_target_dir(target))) # build dir
# Add per-target compile args, f.ex, `c_args : ['/DFOO']`. We set these
# near the end since these are supposed to override everything else.
for l, args in target.extra_args.items():
+10 -8
View File
@@ -734,7 +734,7 @@ class IncludeDirs(HoldableObject):
for idir in self.incdirs:
strlist.append(os.path.join(sourcedir, self.curdir, idir))
strlist.append(os.path.join(builddir, bsubdir, idir))
strlist.extend(os.path.join(builddir, bsubdir, idir) for idir in self.extra_build_dirs)
strlist.extend(os.path.join(builddir, self.curdir, idir) for idir in self.extra_build_dirs)
return strlist
def rel_string_list(self, build_to_src: str, build_root: T.Optional[str] = None) -> T.List[str]:
@@ -748,13 +748,15 @@ class IncludeDirs(HoldableObject):
strlist: T.List[str] = []
bsubdir = self.build_project.prefix + self.curdir
for idirs, add_src in [(self.incdirs, True), (self.extra_build_dirs, False)]:
for idir in idirs:
bld_dir = os.path.normpath(os.path.join(bsubdir, idir))
if build_root is None or os.path.isdir(os.path.join(build_root, bld_dir)):
strlist.append(bld_dir)
if add_src:
strlist.append(os.path.normpath(os.path.join(build_to_src, self.curdir, idir)))
for idir in self.incdirs:
bld_dir = os.path.normpath(os.path.join(bsubdir, idir))
if build_root is None or os.path.isdir(os.path.join(build_root, bld_dir)):
strlist.append(bld_dir)
strlist.append(os.path.normpath(os.path.join(build_to_src, self.curdir, idir)))
for idir in self.extra_build_dirs:
bld_dir = os.path.normpath(os.path.join(self.curdir, idir))
if build_root is None or os.path.isdir(os.path.join(build_root, bld_dir)):
strlist.append(bld_dir)
return strlist
+6 -5
View File
@@ -980,7 +980,7 @@ class Interpreter(InterpreterBase, HoldableObject):
mlog.error(*msg)
raise e
self.create_build_subdir(subdir)
self.create_build_subdir(for_machine.get_prefix() + subdir)
self.global_args_frozen = True
stack = self.format_subproject_stack(fullstack, ':')
@@ -1052,7 +1052,7 @@ class Interpreter(InterpreterBase, HoldableObject):
with mlog.nested(subp_name):
if ast:
self._save_ast(subdir, ast)
self._save_ast(for_machine.get_prefix() + subdir, ast)
subi = Interpreter(new_build, self.backend, subp_name, subdir, self.subproject_dir,
default_options, ast=ast, relaxations=relaxations,
@@ -2713,12 +2713,13 @@ class Interpreter(InterpreterBase, HoldableObject):
if not is_new:
raise InvalidArguments(f'Tried to enter directory "{subdir}", which has already been visited.')
self.create_build_subdir(subdir)
build_subdir = self.current_build_project().prefix + subdir
self.create_build_subdir(build_subdir)
if self.relaxed(InterpreterRuleRelaxation.CARGO_SUBDIR) and \
os.path.exists(os.path.join(self.environment.get_source_dir(), subdir, 'Cargo.toml')):
codeblock = self.cargo.interpret(subdir, self.root_subdir)
self._save_ast(subdir, codeblock)
self._save_ast(build_subdir, codeblock)
self._evaluate_codeblock(codeblock, subdir)
elif not self._evaluate_subdir(self.environment.get_source_dir(), subdir):
buildfilename = os.path.join(subdir, environment.build_filename)
@@ -3116,7 +3117,7 @@ class Interpreter(InterpreterBase, HoldableObject):
src_root = self.environment.get_source_dir()
build_root = self.environment.get_build_dir()
absbase_src = os.path.join(src_root, self.subdir)
absbase_build = os.path.join(build_root, self.subdir)
absbase_build = os.path.join(build_root, self.current_build_dir())
for a in incdir_strings:
if path_is_in_root(Path(a), Path(src_root)):
@@ -0,0 +1,5 @@
project('native subproject build dirs', 'c', meson_version: '>=1.12.0')
subproject('sub', native: true)
subproject('sub', native: false)
subproject('nativeonly', native: true)
@@ -0,0 +1,3 @@
#pragma once
#define FOR_MACHINE @for_machine@
@@ -0,0 +1,3 @@
data = configuration_data()
data.set('for_machine', meson.is_cross_build() ? 1 : 0)
configure_file(input: 'gen.h.in', output: 'gen.h', configuration: data)
@@ -0,0 +1,10 @@
#include "gen.h"
#if FOR_MACHINE != EXPECTED
#error Wrong architecture
#endif
int main(void)
{
return 0;
}
@@ -0,0 +1,8 @@
project('native only', 'c')
subdir('gen')
executable('main', 'main.c',
include_directories: include_directories('gen'),
c_args: '-DEXPECTED=@0@'.format(meson.is_cross_build() ? 1 : 0),
)
@@ -0,0 +1,3 @@
#pragma once
#define FOR_MACHINE @for_machine@
@@ -0,0 +1,3 @@
data = configuration_data()
data.set('for_machine', meson.is_cross_build() ? 1 : 0)
configure_file(input: 'gen.h.in', output: 'gen.h', build_subdir: 'sub2', configuration: data)
@@ -0,0 +1 @@
#pragma once
@@ -0,0 +1,11 @@
#include "gen.h"
#include "static.h"
#if FOR_MACHINE != EXPECTED
#error Wrong architecture
#endif
int main(void)
{
return 0;
}
@@ -0,0 +1,8 @@
project('sub', 'c', meson_version: '>=1.10.0')
subdir('gen')
executable('main', 'main.c',
include_directories: include_directories('inc', 'gen/sub2'),
c_args: '-DEXPECTED=@0@'.format(meson.is_cross_build() ? 1 : 0),
)
+27
View File
@@ -5079,6 +5079,33 @@ class AllPlatformTests(BasePlatformTests):
self.setconf('-Duse-sub=true')
self.build()
def test_native_subproject_build_dirs(self):
# Ensure that in a cross build, a native subproject has include dirs,
# configure_file outputs and subdirs under build.<subdir>, not in the host tree.
crossdir = os.path.join(self.unit_test_dir, '69 cross')
# Reuse the cross test project to generate a native and a cross file
# describing this machine, so the configuration below is treated as a
# cross build (see test_identity_cross).
self.init(crossdir, extra_args=['-Dgenerate=true'])
self.meson_native_files = [os.path.join(self.builddir, "nativefile")]
self.meson_cross_files = [os.path.join(self.builddir, "crossfile")]
self.new_builddir()
testdir = os.path.join(self.unit_test_dir, '146 native subproject build dirs')
self.init(testdir)
self.build()
build_path = Path(self.builddir, 'build.subprojects/sub/gen/sub2/gen.h')
self.assertPathExists(build_path)
self.assertIn('FOR_MACHINE 0', build_path.read_text(encoding='utf8'))
host_path = Path(self.builddir, 'subprojects/sub/gen/sub2/gen.h')
self.assertPathExists(host_path)
self.assertIn('FOR_MACHINE 1', host_path.read_text(encoding='utf8'))
self.assertPathExists(os.path.join(self.builddir, 'build.subprojects/nativeonly'))
self.assertPathDoesNotExist(os.path.join(self.builddir, 'subprojects/nativeonly'))
def test_devenv(self):
testdir = os.path.join(self.unit_test_dir, '90 devenv')
self.init(testdir)