compiler.preprocess: add depends kwarg

This patch adds 'depends' keyword to compiler.preprocess().
It allows to execute other targets before doing the preprocessing.
Test-case is added to demonstrate that functionality: it
generates the header before preprocessing the C source that
uses that generated header.

Thanks to @bruchar1 for getting this patch to work.
pull/12750/head
Stas Sergeev 10 months ago committed by Dylan Baker
parent 1ca2c74d16
commit 92f638e1f9
  1. 5
      docs/markdown/snippets/preprocess-depends.md
  2. 7
      docs/yaml/objects/compiler.yaml
  3. 11
      mesonbuild/backend/backends.py
  4. 2
      mesonbuild/backend/ninjabackend.py
  5. 13
      mesonbuild/build.py
  6. 11
      mesonbuild/interpreter/compiler.py
  7. 0
      test cases/common/259 preprocess/foo.x
  8. 7
      test cases/common/259 preprocess/meson.build

@ -0,0 +1,5 @@
## `depends` kwarg now supported by compiler.preprocess()
It is now possible to specify the dependent targets with `depends:`
for compiler.preprocess(). These targets should be built before the
preprocessing starts.

@ -681,3 +681,10 @@ methods:
type: dep | list[dep]
description: Additionally dependencies required.
since: 1.1.0
depends:
type: list[build_tgt | custom_tgt]
description: |
Specifies that this target depends on the specified
target(s). These targets should be built before starting
to preprocess an input.
since: 1.4.0

@ -2012,7 +2012,9 @@ class Backend:
def compiler_to_generator(self, target: build.BuildTarget,
compiler: 'Compiler',
sources: _ALL_SOURCES_TYPE,
output_templ: str) -> build.GeneratedList:
output_templ: str,
depends: T.Optional[T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]] = None,
) -> build.GeneratedList:
'''
Some backends don't support custom compilers. This is a convenience
method to convert a Compiler to a Generator.
@ -2027,9 +2029,12 @@ class Backend:
commands += compiler.get_compile_only_args() + ['@INPUT@']
commands += self.get_source_dir_include_args(target, compiler)
commands += self.get_build_dir_include_args(target, compiler)
generator = build.Generator(exe, args + commands.to_native(), [output_templ], depfile='@PLAINNAME@.d')
generator = build.Generator(exe, args + commands.to_native(),
[output_templ], depfile='@PLAINNAME@.d',
depends=depends)
return generator.process_files(sources, self.interpreter)
def compile_target_to_generator(self, target: build.CompileTarget) -> build.GeneratedList:
all_sources = T.cast('_ALL_SOURCES_TYPE', target.sources) + T.cast('_ALL_SOURCES_TYPE', target.generated)
return self.compiler_to_generator(target, target.compiler, all_sources, target.output_templ)
return self.compiler_to_generator(target, target.compiler, all_sources,
target.output_templ, target.depends)

@ -718,6 +718,8 @@ class NinjaBackend(backends.Backend):
for dep in itertools.chain(target.link_targets, target.link_whole_targets):
if isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
header_deps += self.get_generated_headers(dep)
if isinstance(target, build.CompileTarget):
header_deps.extend(target.get_generated_headers())
target.cached_generated_headers = header_deps
return header_deps

@ -1763,12 +1763,12 @@ class Generator(HoldableObject):
*,
depfile: T.Optional[str] = None,
capture: bool = False,
depends: T.Optional[T.List[T.Union[BuildTarget, 'CustomTarget']]] = None,
depends: T.Optional[T.List[T.Union[BuildTarget, 'CustomTarget', 'CustomTargetIndex']]] = None,
name: str = 'Generator'):
self.exe = exe
self.depfile = depfile
self.capture = capture
self.depends: T.List[T.Union[BuildTarget, 'CustomTarget']] = depends or []
self.depends: T.List[T.Union[BuildTarget, 'CustomTarget', 'CustomTargetIndex']] = depends or []
self.arglist = arguments
self.outputs = output
self.name = name
@ -2763,7 +2763,8 @@ class CompileTarget(BuildTarget):
backend: Backend,
compile_args: T.List[str],
include_directories: T.List[IncludeDirs],
dependencies: T.List[dependencies.Dependency]):
dependencies: T.List[dependencies.Dependency],
depends: T.List[T.Union[BuildTarget, CustomTarget, CustomTargetIndex]]):
compilers = {compiler.get_language(): compiler}
kwargs = {
'build_by_default': False,
@ -2778,6 +2779,7 @@ class CompileTarget(BuildTarget):
self.output_templ = output_templ
self.outputs = []
self.sources_map: T.Dict[File, str] = {}
self.depends = list(depends or [])
for f in self.sources:
self._add_output(f)
for gensrc in self.generated:
@ -2799,6 +2801,11 @@ class CompileTarget(BuildTarget):
self.outputs.append(o)
self.sources_map[f] = o
def get_generated_headers(self) -> T.List[File]:
gen_headers: T.List[File] = []
for dep in self.depends:
gen_headers += [File(True, dep.subdir, o) for o in dep.get_outputs()]
return gen_headers
class RunTarget(Target, CommandBase):

@ -96,6 +96,7 @@ if T.TYPE_CHECKING:
compile_args: T.List[str]
include_directories: T.List[build.IncludeDirs]
dependencies: T.List[dependencies.Dependency]
depends: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]
class _TestMode(enum.Enum):
@ -148,6 +149,12 @@ _DEPENDENCIES_KW: KwargInfo[T.List['dependencies.Dependency']] = KwargInfo(
listify=True,
default=[],
)
_DEPENDS_KW: KwargInfo[T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]] = KwargInfo(
'depends',
ContainerTypeInfo(list, (build.BuildTarget, build.CustomTarget, build.CustomTargetIndex)),
listify=True,
default=[],
)
_INCLUDE_DIRS_KW: KwargInfo[T.List[build.IncludeDirs]] = KwargInfo(
'include_directories',
ContainerTypeInfo(list, build.IncludeDirs),
@ -853,6 +860,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
KwargInfo('compile_args', ContainerTypeInfo(list, str), listify=True, default=[]),
_INCLUDE_DIRS_KW,
_DEPENDENCIES_KW.evolve(since='1.1.0'),
_DEPENDS_KW.evolve(since='1.4.0'),
)
def preprocess_method(self, args: T.Tuple[T.List['mesonlib.FileOrString']], kwargs: 'PreprocessKW') -> T.List[build.CustomTargetIndex]:
compiler = self.compiler.get_preprocessor()
@ -878,7 +886,8 @@ class CompilerHolder(ObjectHolder['Compiler']):
self.interpreter.backend,
kwargs['compile_args'],
kwargs['include_directories'],
kwargs['dependencies'])
kwargs['dependencies'],
kwargs['depends'])
self.interpreter.add_target(tg.name, tg)
# Expose this target as list of its outputs, so user can pass them to
# other targets, list outputs, etc.

@ -13,9 +13,14 @@ bar_x = custom_target(
capture: true,
)
foo_h = import('fs').copyfile('foo.x', 'foo.h')
dep = declare_dependency(compile_args: '-DPLOP=0')
pp_files = cc.preprocess('foo.c', bar_x, 'math.c', output: '@PLAINNAME@.c', dependencies: dep)
pp_files = cc.preprocess('foo.c', bar_x, 'math.c',
output: '@PLAINNAME@.c',
dependencies: dep,
depends: foo_h)
foreach f : pp_files
message(f.full_path())

Loading…
Cancel
Save