aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorVolker Weißmann <volker.weissmann@gmx.de>2023-05-21 18:29:36 +0200
committerJussi Pakkanen <jpakkane@gmail.com>2023-05-21 22:12:57 +0300
commit12a2dc86ca736249b2ea4d47ae36b165225a3fdf (patch)
treeb9cb9208f1905e2422c77164f5a8a4fe3c8fb4b6 /mesonbuild
parentc6db870fc7fbc9f6c3098ff439d59b49f7255df2 (diff)
downloadmeson-12a2dc86ca736249b2ea4d47ae36b165225a3fdf.zip
meson-12a2dc86ca736249b2ea4d47ae36b165225a3fdf.tar.gz
meson-12a2dc86ca736249b2ea4d47ae36b165225a3fdf.tar.bz2
Allow generator.process(generator.process(...))
Fixes #1141
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/backend/ninjabackend.py5
-rw-r--r--mesonbuild/backend/vs2010backend.py119
-rw-r--r--mesonbuild/build.py49
3 files changed, 108 insertions, 65 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index cd4cfb1..4cb680b 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2513,6 +2513,9 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
return args
def generate_genlist_for_target(self, genlist: build.GeneratedList, target: build.BuildTarget) -> None:
+ for x in genlist.depends:
+ if isinstance(x, build.GeneratedList):
+ self.generate_genlist_for_target(x, target)
generator = genlist.get_generator()
subdir = genlist.subdir
exe = generator.get_exe()
@@ -2524,7 +2527,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
sole_output = os.path.join(self.get_target_private_dir(target), outfilelist[i])
else:
sole_output = f'{curfile}'
- infilename = curfile.rel_to_builddir(self.build_to_src)
+ infilename = curfile.rel_to_builddir(self.build_to_src, self.get_target_private_dir(target))
base_args = generator.get_arglist(infilename)
outfiles = genlist.get_outputs_for(curfile)
outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles]
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index ab14a2d..310b1bc 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -118,67 +118,74 @@ class Vs2010Backend(backends.Backend):
def get_target_private_dir(self, target):
return os.path.join(self.get_target_dir(target), target.get_id())
+ def generate_genlist_for_target(self, genlist: T.Union[build.GeneratedList, build.CustomTarget, build.CustomTargetIndex], target: build.BuildTarget, parent_node: ET.Element, generator_output_files: T.List[str], custom_target_include_dirs: T.List[str], custom_target_output_files: T.List[str]) -> None:
+ if isinstance(genlist, build.GeneratedList):
+ for x in genlist.depends:
+ self.generate_genlist_for_target(x, target, parent_node, [], [], [])
+ target_private_dir = self.relpath(self.get_target_private_dir(target), self.get_target_dir(target))
+ down = self.target_to_build_root(target)
+ if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)):
+ for i in genlist.get_outputs():
+ # Path to the generated source from the current vcxproj dir via the build root
+ ipath = os.path.join(down, self.get_target_dir(genlist), i)
+ custom_target_output_files.append(ipath)
+ idir = self.relpath(self.get_target_dir(genlist), self.get_target_dir(target))
+ if idir not in custom_target_include_dirs:
+ custom_target_include_dirs.append(idir)
+ else:
+ generator = genlist.get_generator()
+ exe = generator.get_exe()
+ infilelist = genlist.get_inputs()
+ outfilelist = genlist.get_outputs()
+ source_dir = os.path.join(down, self.build_to_src, genlist.subdir)
+ idgroup = ET.SubElement(parent_node, 'ItemGroup')
+ samelen = len(infilelist) == len(outfilelist)
+ for i, curfile in enumerate(infilelist):
+ if samelen:
+ sole_output = os.path.join(target_private_dir, outfilelist[i])
+ else:
+ sole_output = ''
+ infilename = os.path.join(down, curfile.rel_to_builddir(self.build_to_src, target_private_dir))
+ deps = self.get_custom_target_depend_files(genlist, True)
+ base_args = generator.get_arglist(infilename)
+ outfiles_rel = genlist.get_outputs_for(curfile)
+ outfiles = [os.path.join(target_private_dir, of) for of in outfiles_rel]
+ generator_output_files += outfiles
+ args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)
+ for x in base_args]
+ args = self.replace_outputs(args, target_private_dir, outfiles_rel)
+ args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir())
+ .replace("@BUILD_DIR@", target_private_dir)
+ for x in args]
+ args = [x.replace("@CURRENT_SOURCE_DIR@", source_dir) for x in args]
+ args = [x.replace("@SOURCE_ROOT@", self.environment.get_source_dir())
+ .replace("@BUILD_ROOT@", self.environment.get_build_dir())
+ for x in args]
+ args = [x.replace('\\', '/') for x in args]
+ # Always use a wrapper because MSBuild eats random characters when
+ # there are many arguments.
+ tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target))
+ cmd, _ = self.as_meson_exe_cmdline(
+ exe,
+ self.replace_extra_args(args, genlist),
+ workdir=tdir_abs,
+ capture=outfiles[0] if generator.capture else None,
+ force_serialize=True
+ )
+ deps = cmd[-1:] + deps
+ abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target))
+ os.makedirs(abs_pdir, exist_ok=True)
+ cbs = ET.SubElement(idgroup, 'CustomBuild', Include=infilename)
+ ET.SubElement(cbs, 'Command').text = ' '.join(self.quote_arguments(cmd))
+ ET.SubElement(cbs, 'Outputs').text = ';'.join(outfiles)
+ ET.SubElement(cbs, 'AdditionalInputs').text = ';'.join(deps)
+
def generate_custom_generator_commands(self, target, parent_node):
generator_output_files = []
custom_target_include_dirs = []
custom_target_output_files = []
- target_private_dir = self.relpath(self.get_target_private_dir(target), self.get_target_dir(target))
- down = self.target_to_build_root(target)
for genlist in target.get_generated_sources():
- if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)):
- for i in genlist.get_outputs():
- # Path to the generated source from the current vcxproj dir via the build root
- ipath = os.path.join(down, self.get_target_dir(genlist), i)
- custom_target_output_files.append(ipath)
- idir = self.relpath(self.get_target_dir(genlist), self.get_target_dir(target))
- if idir not in custom_target_include_dirs:
- custom_target_include_dirs.append(idir)
- else:
- generator = genlist.get_generator()
- exe = generator.get_exe()
- infilelist = genlist.get_inputs()
- outfilelist = genlist.get_outputs()
- source_dir = os.path.join(down, self.build_to_src, genlist.subdir)
- idgroup = ET.SubElement(parent_node, 'ItemGroup')
- for i, curfile in enumerate(infilelist):
- if len(infilelist) == len(outfilelist):
- sole_output = os.path.join(target_private_dir, outfilelist[i])
- else:
- sole_output = ''
- infilename = os.path.join(down, curfile.rel_to_builddir(self.build_to_src))
- deps = self.get_custom_target_depend_files(genlist, True)
- base_args = generator.get_arglist(infilename)
- outfiles_rel = genlist.get_outputs_for(curfile)
- outfiles = [os.path.join(target_private_dir, of) for of in outfiles_rel]
- generator_output_files += outfiles
- args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)
- for x in base_args]
- args = self.replace_outputs(args, target_private_dir, outfiles_rel)
- args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir())
- .replace("@BUILD_DIR@", target_private_dir)
- for x in args]
- args = [x.replace("@CURRENT_SOURCE_DIR@", source_dir) for x in args]
- args = [x.replace("@SOURCE_ROOT@", self.environment.get_source_dir())
- .replace("@BUILD_ROOT@", self.environment.get_build_dir())
- for x in args]
- args = [x.replace('\\', '/') for x in args]
- # Always use a wrapper because MSBuild eats random characters when
- # there are many arguments.
- tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target))
- cmd, _ = self.as_meson_exe_cmdline(
- exe,
- self.replace_extra_args(args, genlist),
- workdir=tdir_abs,
- capture=outfiles[0] if generator.capture else None,
- force_serialize=True
- )
- deps = cmd[-1:] + deps
- abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target))
- os.makedirs(abs_pdir, exist_ok=True)
- cbs = ET.SubElement(idgroup, 'CustomBuild', Include=infilename)
- ET.SubElement(cbs, 'Command').text = ' '.join(self.quote_arguments(cmd))
- ET.SubElement(cbs, 'Outputs').text = ';'.join(outfiles)
- ET.SubElement(cbs, 'AdditionalInputs').text = ';'.join(deps)
+ self.generate_genlist_for_target(genlist, target, parent_node, generator_output_files, custom_target_include_dirs, custom_target_output_files)
return generator_output_files, custom_target_output_files, custom_target_include_dirs
def generate(self):
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 5743236..7b23a1d 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -1668,6 +1668,34 @@ You probably should put it in link_with instead.''')
'use shared_library() with `override_options: [\'b_lundef=false\']` instead.')
link_target.force_soname = True
+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'.
+ """
+
+ def __init__(self, fname: str):
+ self.fname = fname
+
+class FileMaybeInTargetPrivateDir:
+ """Union between 'File' and 'FileInTargetPrivateDir'"""
+
+ def __init__(self, inner: T.Union[File, FileInTargetPrivateDir]):
+ self.inner = inner
+
+ @property
+ def fname(self) -> str:
+ return self.inner.fname
+
+ def rel_to_builddir(self, build_to_src: str, target_private_dir: str) -> str:
+ if isinstance(self.inner, FileInTargetPrivateDir):
+ return os.path.join(target_private_dir, self.inner.fname)
+ return self.inner.rel_to_builddir(build_to_src)
+
+ def absolute_path(self, srcdir: str, builddir: str) -> str:
+ if isinstance(self.inner, FileInTargetPrivateDir):
+ raise RuntimeError('Unreachable code')
+ return self.inner.absolute_path(srcdir, builddir)
+
class Generator(HoldableObject):
def __init__(self, exe: T.Union['Executable', programs.ExternalProgram],
arguments: T.List[str],
@@ -1727,10 +1755,14 @@ class Generator(HoldableObject):
output.depends.add(e)
if isinstance(e, CustomTargetIndex):
output.depends.add(e.target)
-
- if isinstance(e, (CustomTarget, CustomTargetIndex, GeneratedList)):
+ if isinstance(e, (CustomTarget, CustomTargetIndex)):
output.depends.add(e)
fs = [File.from_built_file(state.subdir, f) for f in e.get_outputs()]
+ elif isinstance(e, GeneratedList):
+ if preserve_path_from:
+ raise InvalidArguments("generator.process: 'preserve_path_from' is not allowed if one input is a 'generated_list'.")
+ output.depends.add(e)
+ fs = [FileInTargetPrivateDir(f) for f in e.get_outputs()]
elif isinstance(e, str):
fs = [File.from_source_file(state.environment.source_dir, state.subdir, e)]
else:
@@ -1741,6 +1773,7 @@ class Generator(HoldableObject):
abs_f = f.absolute_path(state.environment.source_dir, state.environment.build_dir)
if not self.is_parent_path(preserve_path_from, abs_f):
raise InvalidArguments('generator.process: When using preserve_path_from, all input files must be in a subdirectory of the given dir.')
+ f = FileMaybeInTargetPrivateDir(f)
output.add_file(f, state)
return output
@@ -1758,9 +1791,9 @@ class GeneratedList(HoldableObject):
def __post_init__(self) -> None:
self.name = self.generator.exe
self.depends: T.Set[GeneratedTypes] = set()
- self.infilelist: T.List['File'] = []
+ self.infilelist: T.List[FileMaybeInTargetPrivateDir] = []
self.outfilelist: T.List[str] = []
- self.outmap: T.Dict[File, T.List[str]] = {}
+ self.outmap: T.Dict[FileMaybeInTargetPrivateDir, T.List[str]] = {}
self.extra_depends = [] # XXX: Doesn't seem to be used?
self.depend_files: T.List[File] = []
@@ -1776,7 +1809,7 @@ class GeneratedList(HoldableObject):
# know the absolute path of
self.depend_files.append(File.from_absolute_file(path))
- def add_preserved_path_segment(self, infile: File, outfiles: T.List[str], state: T.Union['Interpreter', 'ModuleState']) -> T.List[str]:
+ def add_preserved_path_segment(self, infile: FileMaybeInTargetPrivateDir, outfiles: T.List[str], state: T.Union['Interpreter', 'ModuleState']) -> T.List[str]:
result: T.List[str] = []
in_abs = infile.absolute_path(state.environment.source_dir, state.environment.build_dir)
assert os.path.isabs(self.preserve_path_from)
@@ -1786,7 +1819,7 @@ class GeneratedList(HoldableObject):
result.append(os.path.join(path_segment, of))
return result
- def add_file(self, newfile: File, state: T.Union['Interpreter', 'ModuleState']) -> None:
+ def add_file(self, newfile: FileMaybeInTargetPrivateDir, state: T.Union['Interpreter', 'ModuleState']) -> None:
self.infilelist.append(newfile)
outfiles = self.generator.get_base_outnames(newfile.fname)
if self.preserve_path_from:
@@ -1794,13 +1827,13 @@ class GeneratedList(HoldableObject):
self.outfilelist += outfiles
self.outmap[newfile] = outfiles
- def get_inputs(self) -> T.List['File']:
+ def get_inputs(self) -> T.List[FileMaybeInTargetPrivateDir]:
return self.infilelist
def get_outputs(self) -> T.List[str]:
return self.outfilelist
- def get_outputs_for(self, filename: 'File') -> T.List[str]:
+ def get_outputs_for(self, filename: FileMaybeInTargetPrivateDir) -> T.List[str]:
return self.outmap[filename]
def get_generator(self) -> 'Generator':