Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/markdown/snippets/permit_generator_any_target.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Allow using generator with any [[@build_tgt]] object

Passing any build target to `generator.process()` is now allowed.
132 changes: 71 additions & 61 deletions mesonbuild/backend/vs2010backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,75 +163,85 @@ def detect_toolset(self) -> None:
def get_target_private_dir(self, target: build.AnyTargetType) -> str:
return os.path.join(self.get_target_dir(target), target.get_id())

def generate_genlist_for_target(
def generate_gensrc_for_target(
self, genlist: build.GeneratedTypes,
target: build.BuildTarget | build.CustomTarget,
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, [], [], [])
self.generate_genlist_for_target(genlist, target, parent_node, generator_output_files)
return

down = self.target_to_build_root(target)
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)

def generate_genlist_for_target(
self, genlist: build.GeneratedList,
target: build.BuildTarget | build.CustomTarget,
parent_node: ET.Element,
generator_output_files: T.List[str]) -> None:
for x in genlist.depends:
if isinstance(x, build.GeneratedList):
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, self.get_target_private_dir(target)))
deps = self.get_target_depend_files(genlist, True)
deps += self.get_paths_for_dep_outputs(target, genlist.extra_depends)
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,
env=genlist.env
)
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)
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, self.get_target_private_dir(target)))
deps = self.get_target_depend_files(genlist, True)
deps += self.get_paths_for_dep_outputs(target, genlist.extra_depends)
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,
env=genlist.env
)
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: build.BuildTarget | build.CustomTarget, parent_node: ET.Element
Expand All @@ -240,7 +250,7 @@ def generate_custom_generator_commands(
custom_target_include_dirs: list[str] = []
custom_target_output_files: list[str] = []
for genlist in target.get_generated_sources():
self.generate_genlist_for_target(genlist, target, parent_node, generator_output_files, custom_target_include_dirs, custom_target_output_files)
self.generate_gensrc_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,
Expand Down
6 changes: 3 additions & 3 deletions mesonbuild/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2005,7 +2005,7 @@ def get_arglist(self, inname: str) -> T.List[str]:
basename = os.path.splitext(plainname)[0]
return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.arglist]

def process_files(self, files: T.Iterable[TargetSources],
def process_files(self, files: T.Iterable[TargetSources | BuildTarget],
subdir: str = '',
preserve_path_from: T.Optional[str] = None,
extra_args: T.Optional[T.List[str]] = None,
Expand All @@ -2020,7 +2020,7 @@ def process_files(self, files: T.Iterable[TargetSources],
extra_depends=list(extra_depends) if extra_depends is not None else [])

for e in files:
if isinstance(e, (CustomTarget, CustomTargetIndex)):
if isinstance(e, (BuildTarget, CustomTarget, CustomTargetIndex)):
output.depends.add(e)
fs = [File.from_built_file(e.get_builddir(), f) for f in e.get_outputs()]
elif isinstance(e, GeneratedList):
Expand Down Expand Up @@ -2059,7 +2059,7 @@ class GeneratedList(HoldableObject):

def __post_init__(self) -> None:
self.name = self.generator.exe
self.depends: T.Set[GeneratedTypes] = set()
self.depends: T.Set[BuildTarget | GeneratedTypes] = set()
self.infilelist: T.List[FileMaybeInTargetPrivateDir] = []
self.outfilelist: T.List[str] = []
self.outmap: T.Dict[FileMaybeInTargetPrivateDir, T.List[str]] = {}
Expand Down
5 changes: 5 additions & 0 deletions mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3256,6 +3256,9 @@ def source_strings_to_files(self, sources: list[kwtypes.BuildTargetObjects], #
def source_strings_to_files(self, sources: list[T.Union[str, build.TargetSources, build.BuildTargetTypes, build.BothLibraries, build.ExtractedObjects]], # type: ignore[overload-overlap]
) -> list[T.Union[build.TargetSources, build.BuildTargetTypes, build.BothLibraries, build.ExtractedObjects]]: ...

@T.overload
def source_strings_to_files(self, sources: list[T.Union[str, build.BuildTarget, build.TargetSources]]) -> list[build.BuildTarget | build.TargetSources]: ... # type: ignore[overload-overlap]

@T.overload
def source_strings_to_files(self, sources: list[T.Union[str, build.TargetSources, build.StructuredSources]],
) -> list[T.Union[build.TargetSources, build.StructuredSources]]: ... # noqa: F811
Expand All @@ -3274,6 +3277,7 @@ def source_strings_to_files(self,
list[mesonlib.File | str | build.BuildTargetTypes],
list[str | build.TargetSources],
list[str | build.TargetSources | build.StructuredSources],
list[str | build.TargetSources | build.BuildTarget],
list[kwtypes.CustomTargetInputs],
list[mesonlib.File | str | build.BuildTargetTypes | build.BothLibraries | build.ExtractedObjects | build.GeneratedTypes],
list[kwtypes.BuildTargetObjects],
Expand All @@ -3285,6 +3289,7 @@ def source_strings_to_files(self,
list[mesonlib.File | build.CustomTarget | build.CustomTargetIndex],
list[build.TargetSources],
list[build.TargetSources | build.StructuredSources],
list[build.TargetSources | build.BuildTarget],
list[mesonlib.File | build.BuildTargetTypes | build.BothLibraries | build.ExtractedObjects | build.GeneratedTypes],
list[build.ObjectTypes | build.GeneratedTypes],
list[CustomTargetSources],
Expand Down
9 changes: 7 additions & 2 deletions mesonbuild/interpreter/interpreterobjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,7 @@ class GeneratorHolder(ObjectHolder[build.Generator]):
def __init__(self, gen: build.Generator, interpreter: 'Interpreter'):
super().__init__(gen, interpreter)

@typed_pos_args('generator.process', min_varargs=1, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList))
@typed_pos_args('generator.process', min_varargs=1, varargs=(str, mesonlib.File, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList))
@typed_kwargs(
'generator.process',
KwargInfo('preserve_path_from', (str, NoneType), since='0.45.0'),
Expand All @@ -1238,7 +1238,7 @@ def __init__(self, gen: build.Generator, interpreter: 'Interpreter'):
)
@InterpreterObject.method('process')
def process_method(self,
args: T.Tuple[T.List[str | build.TargetSources]],
args: T.Tuple[T.List[str | build.BuildTarget | build.TargetSources]],
kwargs: 'kwargs.GeneratorProcess') -> build.GeneratedList:
preserve_path_from = kwargs['preserve_path_from']
if preserve_path_from is not None:
Expand All @@ -1252,6 +1252,11 @@ def process_method(self,
'Calling generator.process with CustomTarget or Index of CustomTarget.',
'0.57.0', self.interpreter.subproject)

if any(isinstance(a, build.BuildTarget) for a in args[0]):
FeatureNew.single_use(
'Calling generator.process with BuildTarget.',
'1.12.0', self.interpreter.subproject)

sources = self.interpreter.source_strings_to_files(args[0])
gl = self.held_object.process_files(sources, self.interpreter.subdir,
preserve_path_from, extra_args=kwargs['extra_args'], env=kwargs['env'],
Expand Down
3 changes: 3 additions & 0 deletions test cases/common/105 generatorcustom/embedded.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
int main(void) {
return 0;
}
5 changes: 3 additions & 2 deletions test cases/common/105 generatorcustom/gen.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#!/usr/bin/env python3

from pathlib import Path
import sys

ifile = sys.argv[1]
ofile = sys.argv[2]

with open(ifile) as f:
resname = f.readline().strip()

resname = Path(ifile).stem

templ = 'const char %s[] = "%s";\n'
with open(ofile, 'w', encoding='utf-8') as f:
Expand Down
2 changes: 1 addition & 1 deletion test cases/common/105 generatorcustom/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
#include "alltogether.h"

int main(void) {
printf("%s - %s - %s - %s\n", res1, res2, res3, res4);
printf("%s - %s - %s - %s - %s\n", res1, res2, res3, res4, embedded);
return 0;
}
4 changes: 3 additions & 1 deletion test cases/common/105 generatorcustom/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ res4 = custom_target('gen-res4',
output : 'res4.txt',
command : [gen_resx, '@OUTPUT@', '4'])

hs = gen.process('res1.txt', 'res2.txt', res3, res4[0])
embedded = executable('embedded', 'embedded.c')

hs = gen.process('res1.txt', 'res2.txt', res3, res4[0], embedded)

allinone = custom_target('alltogether',
input : hs,
Expand Down
Loading