aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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]