From 5e0f22896f7e007d790c9b606e7b7a940470eff0 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 13 Oct 2022 13:54:10 -0400 Subject: Compilers: Add a preprocessor mode for clike compilers A compiler object can now return a list of "modes", they are new compiler object specialized for a specific task. --- mesonbuild/backend/ninjabackend.py | 4 +++- mesonbuild/compilers/compilers.py | 12 ++++++++++++ mesonbuild/compilers/mixins/clike.py | 18 ++++++++++++++++++ mesonbuild/compilers/mixins/visualstudio.py | 5 +++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 2747c27..8dd21f5 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1983,7 +1983,7 @@ class NinjaBackend(backends.Backend): @classmethod def compiler_to_rule_name(cls, compiler: Compiler) -> str: - return cls.get_compiler_rule_name(compiler.get_language(), compiler.for_machine) + return cls.get_compiler_rule_name(compiler.get_language(), compiler.for_machine, compiler.mode) @classmethod def compiler_to_pch_rule_name(cls, compiler: Compiler) -> str: @@ -2362,6 +2362,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) self.generate_llvm_ir_compile_rule(compiler) self.generate_compile_rule_for(langname, compiler) self.generate_pch_rule_for(langname, compiler) + for mode in compiler.get_modes(): + self.generate_compile_rule_for(langname, mode) def generate_generator_list_rules(self, target): # CustomTargets have already written their rules and diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 53b4307..b3191a8 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -494,6 +494,7 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta): language: str id: str warn_args: T.Dict[str, T.List[str]] + mode: str = 'COMPILER' def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, info: 'MachineInfo', @@ -513,6 +514,7 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta): self.linker = linker self.info = info self.is_cross = is_cross + self.modes: T.List[Compiler] = [] def __repr__(self) -> str: repr_str = "<{0}: v{1} `{2}`>" @@ -531,6 +533,9 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta): def get_id(self) -> str: return self.id + def get_modes(self) -> T.List[Compiler]: + return self.modes + def get_linker_id(self) -> str: # There is not guarantee that we have a dynamic linker instance, as # some languages don't have separate linkers and compilers. In those @@ -1050,6 +1055,9 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta): def get_preprocess_only_args(self) -> T.List[str]: raise EnvironmentException('This compiler does not have a preprocessor') + def get_preprocess_to_file_args(self) -> T.List[str]: + return self.get_preprocess_only_args() + def get_default_include_dirs(self) -> T.List[str]: # TODO: This is a candidate for returning an immutable list return [] @@ -1290,6 +1298,10 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta): def needs_static_linker(self) -> bool: raise NotImplementedError(f'There is no static linker for {self.language}') + def get_preprocessor(self) -> Compiler: + """Get compiler's preprocessor. + """ + raise EnvironmentException(f'{self.get_id()} does not support preprocessor') def get_global_options(lang: str, comp: T.Type[Compiler], diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index cc78639..e1baa84 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -27,6 +27,7 @@ import itertools import os import re import subprocess +import copy import typing as T from pathlib import Path @@ -145,6 +146,8 @@ class CLikeCompiler(Compiler): self.exe_wrapper = None else: self.exe_wrapper = exe_wrapper + # Lazy initialized in get_preprocessor() + self.preprocessor: T.Optional[Compiler] = None def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CLikeCompilerArgs: # This is correct, mypy just doesn't understand co-operative inheritance @@ -1328,3 +1331,18 @@ class CLikeCompiler(Compiler): def get_disable_assert_args(self) -> T.List[str]: return ['-DNDEBUG'] + + @functools.lru_cache(maxsize=None) + def can_compile(self, src: 'mesonlib.FileOrString') -> bool: + # Files we preprocess can be anything, e.g. .in + if self.mode == 'PREPROCESSOR': + return True + return super().can_compile(src) + + def get_preprocessor(self) -> Compiler: + if not self.preprocessor: + self.preprocessor = copy.copy(self) + self.preprocessor.exelist = self.exelist + self.get_preprocess_to_file_args() + self.preprocessor.mode = 'PREPROCESSOR' + self.modes.append(self.preprocessor) + return self.preprocessor diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index dc5e962..76ce9c1 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -159,6 +159,9 @@ class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta): def get_preprocess_only_args(self) -> T.List[str]: return ['/EP'] + def get_preprocess_to_file_args(self) -> T.List[str]: + return ['/EP', '/P'] + def get_compile_only_args(self) -> T.List[str]: return ['/c'] @@ -173,6 +176,8 @@ class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta): return ['/fsanitize=address'] def get_output_args(self, target: str) -> T.List[str]: + if self.mode == 'PREPROCESSOR': + return ['/Fi' + target] if target.endswith('.exe'): return ['/Fe' + target] return ['/Fo' + target] -- cgit v1.1