aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2022-10-13 14:01:50 -0400
committerXavier Claessens <xavier.claessens@collabora.com>2022-10-23 12:21:46 +0200
commit65590e6e4b59e08d0c1a16067524479ed822ad27 (patch)
tree24ef5a84dd057754db7b0b969e5e4aa78fbc3e77
parent5e0f22896f7e007d790c9b606e7b7a940470eff0 (diff)
downloadmeson-65590e6e4b59e08d0c1a16067524479ed822ad27.zip
meson-65590e6e4b59e08d0c1a16067524479ed822ad27.tar.gz
meson-65590e6e4b59e08d0c1a16067524479ed822ad27.tar.bz2
Add cc.preprocess() method for c-like compilers
This introduce a new type of BuildTarget: CompileTarget. From ninja backend POV it is the same thing as any other build target, except that it skips the final link step. It could be used in the future for transpilers too.
-rw-r--r--mesonbuild/backend/backends.py2
-rw-r--r--mesonbuild/backend/ninjabackend.py3
-rw-r--r--mesonbuild/build.py43
-rw-r--r--mesonbuild/interpreter/compiler.py38
4 files changed, 83 insertions, 3 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 8943464..9776642 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -792,6 +792,8 @@ class Backend:
def object_filename_from_source(self, target: build.BuildTarget, source: 'FileOrString') -> str:
assert isinstance(source, mesonlib.File)
+ if isinstance(target, build.CompileTarget):
+ return target.sources_map[source]
build_dir = self.environment.get_build_dir()
rel_src = source.rel_to_builddir(self.build_to_src)
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 8dd21f5..7d90ac1 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -986,6 +986,9 @@ class NinjaBackend(backends.Backend):
obj_list.append(o)
compiled_sources.append(s)
source2object[s] = o
+ if isinstance(target, build.CompileTarget):
+ # Skip the link stage for this special type of target
+ return
linker, stdlib_args = self.determine_linker_and_stdlib_args(target)
if isinstance(target, build.StaticLibrary) and target.prelink:
final_obj_list = self.generate_prelink(target, obj_list)
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index bf87071..14cc235 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -2581,6 +2581,44 @@ class CustomTarget(Target, CommandBase):
def __len__(self) -> int:
return len(self.outputs)
+class CompileTarget(BuildTarget):
+ '''
+ Target that only compile sources without linking them together.
+ It can be used as preprocessor, or transpiler.
+ '''
+
+ typename = 'compile'
+
+ def __init__(self,
+ name: str,
+ subdir: str,
+ subproject: str,
+ environment: environment.Environment,
+ sources: T.List[File],
+ output_templ: str,
+ compiler: Compiler,
+ kwargs):
+ compilers = {compiler.get_language(): compiler}
+ super().__init__(name, subdir, subproject, compiler.for_machine,
+ sources, None, [], environment, compilers, kwargs)
+ self.filename = name
+ self.compiler = compiler
+ self.output_templ = output_templ
+ self.outputs = []
+ for f in sources:
+ plainname = os.path.basename(f.fname)
+ basename = os.path.splitext(plainname)[0]
+ self.outputs.append(output_templ.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname))
+ self.sources_map = dict(zip(sources, self.outputs))
+
+ def type_suffix(self) -> str:
+ return "@compile"
+
+ @property
+ def is_unity(self) -> bool:
+ return False
+
+
class RunTarget(Target, CommandBase):
typename = 'run'
@@ -2705,7 +2743,7 @@ class CustomTargetIndex(HoldableObject):
typename: T.ClassVar[str] = 'custom'
- target: CustomTarget
+ target: T.Union[CustomTarget, CompileTarget]
output: str
def __post_init__(self) -> None:
@@ -2716,8 +2754,7 @@ class CustomTargetIndex(HoldableObject):
return f'{self.target.name}[{self.output}]'
def __repr__(self):
- return '<CustomTargetIndex: {!r}[{}]>'.format(
- self.target, self.target.get_outputs().index(self.output))
+ return '<CustomTargetIndex: {!r}[{}]>'.format(self.target, self.output)
def get_outputs(self) -> T.List[str]:
return [self.output]
diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py
index b46e502..7397321 100644
--- a/mesonbuild/interpreter/compiler.py
+++ b/mesonbuild/interpreter/compiler.py
@@ -4,6 +4,7 @@
import enum
import functools
+import os
import typing as T
from .. import build
@@ -79,6 +80,11 @@ if T.TYPE_CHECKING:
header_prefix: str
header_required: T.Union[bool, coredata.UserFeatureOption]
+ class PreprocessKW(TypedDict):
+ output: str
+ compile_args: T.List[str]
+ include_directories: T.List[build.IncludeDirs]
+
class _TestMode(enum.Enum):
@@ -184,6 +190,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
'first_supported_link_argument': self.first_supported_link_argument_method,
'symbols_have_underscore_prefix': self.symbols_have_underscore_prefix_method,
'get_argument_syntax': self.get_argument_syntax_method,
+ 'preprocess': self.preprocess_method,
})
@property
@@ -734,3 +741,34 @@ class CompilerHolder(ObjectHolder['Compiler']):
@noKwargs
def get_argument_syntax_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.compiler.get_argument_syntax()
+
+ @FeatureNew('compiler.preprocess', '0.64.0')
+ @typed_pos_args('compiler.preprocess', varargs=(mesonlib.File, str), min_varargs=1)
+ @typed_kwargs(
+ 'compiler.preprocess',
+ KwargInfo('output', str, default='@PLAINNAME@.i'),
+ KwargInfo('compile_args', ContainerTypeInfo(list, str), listify=True, default=[]),
+ _INCLUDE_DIRS_KW,
+ )
+ def preprocess_method(self, args: T.Tuple[T.List['mesonlib.FileOrString']], kwargs: 'PreprocessKW') -> T.List[build.CustomTargetIndex]:
+ compiler = self.compiler.get_preprocessor()
+ sources = self.interpreter.source_strings_to_files(args[0])
+ tg_kwargs = {
+ f'{self.compiler.language}_args': kwargs['compile_args'],
+ 'build_by_default': False,
+ 'include_directories': kwargs['include_directories'],
+ }
+ tg = build.CompileTarget(
+ 'preprocessor',
+ self.interpreter.subdir,
+ self.subproject,
+ self.environment,
+ sources,
+ kwargs['output'],
+ compiler,
+ tg_kwargs)
+ 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.
+ private_dir = os.path.relpath(self.interpreter.backend.get_target_private_dir(tg), self.interpreter.subdir)
+ return [build.CustomTargetIndex(tg, os.path.join(private_dir, o)) for o in tg.outputs]