compilers: move get_compile_check_args() to Compiler
This is groundwork to put _build_wrapper in the base Compiler, which is needed to make the D compilers truly type safe.
This commit is contained in:
parent
e039727e63
commit
8291e947f5
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
import contextlib, os.path, re, tempfile
|
import contextlib, os.path, re, tempfile
|
||||||
|
import enum
|
||||||
import itertools
|
import itertools
|
||||||
import typing as T
|
import typing as T
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
@ -165,6 +166,14 @@ def is_known_suffix(fname: 'mesonlib.FileOrString') -> bool:
|
||||||
|
|
||||||
return suffix in all_suffixes
|
return suffix in all_suffixes
|
||||||
|
|
||||||
|
|
||||||
|
class CompileCheckMode(enum.Enum):
|
||||||
|
|
||||||
|
PREPROCESS = 'preprocess'
|
||||||
|
COMPILE = 'compile'
|
||||||
|
LINK = 'link'
|
||||||
|
|
||||||
|
|
||||||
cuda_buildtype_args = {'plain': [],
|
cuda_buildtype_args = {'plain': [],
|
||||||
'debug': [],
|
'debug': [],
|
||||||
'debugoptimized': [],
|
'debugoptimized': [],
|
||||||
|
@ -716,14 +725,16 @@ class Compiler(metaclass=abc.ABCMeta):
|
||||||
suffix = 'obj'
|
suffix = 'obj'
|
||||||
return os.path.join(dirname, 'output.' + suffix)
|
return os.path.join(dirname, 'output.' + suffix)
|
||||||
|
|
||||||
def get_compiler_args_for_mode(self, mode: str) -> T.List[str]:
|
def get_compiler_args_for_mode(self, mode: CompileCheckMode) -> T.List[str]:
|
||||||
# TODO: mode should really be an enum
|
# TODO: mode should really be an enum
|
||||||
args = [] # type: T.List[str]
|
args = [] # type: T.List[str]
|
||||||
args += self.get_always_args()
|
args += self.get_always_args()
|
||||||
if mode == 'compile':
|
if mode is CompileCheckMode.COMPILE:
|
||||||
args += self.get_compile_only_args()
|
args += self.get_compile_only_args()
|
||||||
if mode == 'preprocess':
|
elif mode is CompileCheckMode.PREPROCESS:
|
||||||
args += self.get_preprocess_only_args()
|
args += self.get_preprocess_only_args()
|
||||||
|
else:
|
||||||
|
assert mode is CompileCheckMode.LINK
|
||||||
return args
|
return args
|
||||||
|
|
||||||
def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArgs:
|
def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArgs:
|
||||||
|
@ -761,7 +772,7 @@ class Compiler(metaclass=abc.ABCMeta):
|
||||||
if mode != 'preprocess':
|
if mode != 'preprocess':
|
||||||
output = self._get_compile_output(tmpdirname, mode)
|
output = self._get_compile_output(tmpdirname, mode)
|
||||||
commands += self.get_output_args(output)
|
commands += self.get_output_args(output)
|
||||||
commands.extend(self.get_compiler_args_for_mode(mode))
|
commands.extend(self.get_compiler_args_for_mode(CompileCheckMode(mode)))
|
||||||
# extra_args must be last because it could contain '/link' to
|
# extra_args must be last because it could contain '/link' to
|
||||||
# pass args to VisualStudio's linker. In that case everything
|
# pass args to VisualStudio's linker. In that case everything
|
||||||
# in the command line after '/link' is given to the linker.
|
# in the command line after '/link' is given to the linker.
|
||||||
|
@ -1106,6 +1117,21 @@ class Compiler(metaclass=abc.ABCMeta):
|
||||||
def module_name_to_filename(self, module_name: str) -> str:
|
def module_name_to_filename(self, module_name: str) -> str:
|
||||||
raise EnvironmentError('{} does not implement module_name_to_filename'.format(self.id))
|
raise EnvironmentError('{} does not implement module_name_to_filename'.format(self.id))
|
||||||
|
|
||||||
|
def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
|
||||||
|
"""Arguments to pass the compiler and/or linker for checks.
|
||||||
|
|
||||||
|
The default implementation turns off optimizations. mode should be
|
||||||
|
one of:
|
||||||
|
|
||||||
|
Examples of things that go here:
|
||||||
|
- extra arguments for error checking
|
||||||
|
"""
|
||||||
|
return self.get_no_optimization_args()
|
||||||
|
|
||||||
|
def get_no_optimization_args(self) -> T.List[str]:
|
||||||
|
"""Arguments to the compiler to turn off all optimizations."""
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def get_args_from_envvars(lang: str,
|
def get_args_from_envvars(lang: str,
|
||||||
for_machine: MachineChoice,
|
for_machine: MachineChoice,
|
||||||
|
|
|
@ -26,6 +26,7 @@ from .compilers import (
|
||||||
gnu_winlibs,
|
gnu_winlibs,
|
||||||
msvc_winlibs,
|
msvc_winlibs,
|
||||||
Compiler,
|
Compiler,
|
||||||
|
CompileCheckMode,
|
||||||
)
|
)
|
||||||
from .c_function_attributes import CXX_FUNC_ATTRIBUTES, C_FUNC_ATTRIBUTES
|
from .c_function_attributes import CXX_FUNC_ATTRIBUTES, C_FUNC_ATTRIBUTES
|
||||||
from .mixins.clike import CLikeCompiler
|
from .mixins.clike import CLikeCompiler
|
||||||
|
@ -90,11 +91,11 @@ class CPPCompiler(CLikeCompiler, Compiler):
|
||||||
code = 'class breakCCompiler;int main(void) { return 0; }\n'
|
code = 'class breakCCompiler;int main(void) { return 0; }\n'
|
||||||
return self._sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code)
|
return self._sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code)
|
||||||
|
|
||||||
def get_compiler_check_args(self) -> T.List[str]:
|
def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
|
||||||
# -fpermissive allows non-conforming code to compile which is necessary
|
# -fpermissive allows non-conforming code to compile which is necessary
|
||||||
# for many C++ checks. Particularly, the has_header_symbol check is
|
# for many C++ checks. Particularly, the has_header_symbol check is
|
||||||
# too strict without this and always fails.
|
# too strict without this and always fails.
|
||||||
return super().get_compiler_check_args() + ['-fpermissive']
|
return super().get_compiler_check_args(mode) + ['-fpermissive']
|
||||||
|
|
||||||
def has_header_symbol(self, hname: str, symbol: str, prefix: str,
|
def has_header_symbol(self, hname: str, symbol: str, prefix: str,
|
||||||
env: 'Environment', *,
|
env: 'Environment', *,
|
||||||
|
@ -605,9 +606,9 @@ class VisualStudioLikeCPPCompilerMixin(CompilerMixinBase):
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
def get_compiler_check_args(self) -> T.List[str]:
|
def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
|
||||||
# XXX: this is a hack because so much GnuLike stuff is in the base CPPCompiler class.
|
# XXX: this is a hack because so much GnuLike stuff is in the base CPPCompiler class.
|
||||||
return CLikeCompiler.get_compiler_check_args(self)
|
return Compiler.get_compiler_check_args(self, mode)
|
||||||
|
|
||||||
|
|
||||||
class CPP11AsCPP14Mixin(CompilerMixinBase):
|
class CPP11AsCPP14Mixin(CompilerMixinBase):
|
||||||
|
@ -739,7 +740,7 @@ class ArmCPPCompiler(ArmCompiler, CPPCompiler):
|
||||||
def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
|
def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def get_compiler_check_args(self) -> T.List[str]:
|
def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
@ -768,7 +769,7 @@ class CcrxCPPCompiler(CcrxCompiler, CPPCompiler):
|
||||||
def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
|
def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def get_compiler_check_args(self) -> T.List[str]:
|
def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
class C2000CPPCompiler(C2000Compiler, CPPCompiler):
|
class C2000CPPCompiler(C2000Compiler, CPPCompiler):
|
||||||
|
@ -802,5 +803,5 @@ class C2000CPPCompiler(C2000Compiler, CPPCompiler):
|
||||||
def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
|
def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def get_compiler_check_args(self) -> T.List[str]:
|
def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
|
||||||
return []
|
return []
|
||||||
|
|
|
@ -37,6 +37,7 @@ from ... import mlog
|
||||||
from ...linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker
|
from ...linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker
|
||||||
from ...mesonlib import LibType
|
from ...mesonlib import LibType
|
||||||
from .. import compilers
|
from .. import compilers
|
||||||
|
from ..compilers import CompileCheckMode
|
||||||
from .visualstudio import VisualStudioLikeCompiler
|
from .visualstudio import VisualStudioLikeCompiler
|
||||||
|
|
||||||
if T.TYPE_CHECKING:
|
if T.TYPE_CHECKING:
|
||||||
|
@ -184,13 +185,6 @@ class CLikeCompiler(Compiler):
|
||||||
def get_no_optimization_args(self) -> T.List[str]:
|
def get_no_optimization_args(self) -> T.List[str]:
|
||||||
return ['-O0']
|
return ['-O0']
|
||||||
|
|
||||||
def get_compiler_check_args(self) -> T.List[str]:
|
|
||||||
'''
|
|
||||||
Get arguments useful for compiler checks such as being permissive in
|
|
||||||
the code quality and not doing any optimization.
|
|
||||||
'''
|
|
||||||
return self.get_no_optimization_args()
|
|
||||||
|
|
||||||
def get_output_args(self, target: str) -> T.List[str]:
|
def get_output_args(self, target: str) -> T.List[str]:
|
||||||
return ['-o', target]
|
return ['-o', target]
|
||||||
|
|
||||||
|
@ -296,7 +290,7 @@ class CLikeCompiler(Compiler):
|
||||||
|
|
||||||
source_name = os.path.join(work_dir, sname)
|
source_name = os.path.join(work_dir, sname)
|
||||||
binname = sname.rsplit('.', 1)[0]
|
binname = sname.rsplit('.', 1)[0]
|
||||||
mode = 'link'
|
mode = CompileCheckMode.LINK
|
||||||
if self.is_cross:
|
if self.is_cross:
|
||||||
binname += '_cross'
|
binname += '_cross'
|
||||||
if self.exe_wrapper is None:
|
if self.exe_wrapper is None:
|
||||||
|
@ -305,7 +299,7 @@ class CLikeCompiler(Compiler):
|
||||||
# on OSX the compiler binary is the same but you need
|
# on OSX the compiler binary is the same but you need
|
||||||
# a ton of compiler flags to differentiate between
|
# a ton of compiler flags to differentiate between
|
||||||
# arm and x86_64. So just compile.
|
# arm and x86_64. So just compile.
|
||||||
mode = 'compile'
|
mode = CompileCheckMode.COMPILE
|
||||||
cargs, largs = self._get_basic_compiler_args(environment, mode)
|
cargs, largs = self._get_basic_compiler_args(environment, mode)
|
||||||
extra_flags = cargs + self.linker_to_compiler_args(largs)
|
extra_flags = cargs + self.linker_to_compiler_args(largs)
|
||||||
|
|
||||||
|
@ -432,7 +426,7 @@ class CLikeCompiler(Compiler):
|
||||||
def _get_compiler_check_args(self, env: 'Environment',
|
def _get_compiler_check_args(self, env: 'Environment',
|
||||||
extra_args: T.Union[None, arglist.CompilerArgs, T.List[str]],
|
extra_args: T.Union[None, arglist.CompilerArgs, T.List[str]],
|
||||||
dependencies: T.Optional[T.List['Dependency']],
|
dependencies: T.Optional[T.List['Dependency']],
|
||||||
mode: str = 'compile') -> arglist.CompilerArgs:
|
mode: CompileCheckMode = CompileCheckMode.COMPILE) -> arglist.CompilerArgs:
|
||||||
# TODO: the caller should handle the listfing of these arguments
|
# TODO: the caller should handle the listfing of these arguments
|
||||||
if extra_args is None:
|
if extra_args is None:
|
||||||
extra_args = []
|
extra_args = []
|
||||||
|
@ -460,7 +454,7 @@ class CLikeCompiler(Compiler):
|
||||||
cargs += ca
|
cargs += ca
|
||||||
largs += la
|
largs += la
|
||||||
|
|
||||||
cargs += self.get_compiler_check_args()
|
cargs += self.get_compiler_check_args(mode)
|
||||||
|
|
||||||
# on MSVC compiler and linker flags must be separated by the "/link" argument
|
# on MSVC compiler and linker flags must be separated by the "/link" argument
|
||||||
# at this point, the '/link' argument may already be part of extra_args, otherwise, it is added here
|
# at this point, the '/link' argument may already be part of extra_args, otherwise, it is added here
|
||||||
|
@ -482,10 +476,10 @@ class CLikeCompiler(Compiler):
|
||||||
def _build_wrapper(self, code: str, env: 'Environment',
|
def _build_wrapper(self, code: str, env: 'Environment',
|
||||||
extra_args: T.Union[None, arglist.CompilerArgs, T.List[str]] = None,
|
extra_args: T.Union[None, arglist.CompilerArgs, T.List[str]] = None,
|
||||||
dependencies: T.Optional[T.List['Dependency']] = None,
|
dependencies: T.Optional[T.List['Dependency']] = None,
|
||||||
mode: str = 'compile', want_output: bool = False,
|
mode: str = CompileCheckMode.COMPILE, want_output: bool = False,
|
||||||
disable_cache: bool = False,
|
disable_cache: bool = False,
|
||||||
temp_dir: str = None) -> T.Iterator[T.Optional[compilers.CompileResult]]:
|
temp_dir: str = None) -> T.Iterator[T.Optional[compilers.CompileResult]]:
|
||||||
args = self._get_compiler_check_args(env, extra_args, dependencies, mode)
|
args = self._get_compiler_check_args(env, extra_args, dependencies, CompileCheckMode(mode))
|
||||||
if disable_cache or want_output:
|
if disable_cache or want_output:
|
||||||
with self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir) as r:
|
with self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir) as r:
|
||||||
yield r
|
yield r
|
||||||
|
@ -720,7 +714,7 @@ class CLikeCompiler(Compiler):
|
||||||
#endif
|
#endif
|
||||||
{delim}\n{define}'''
|
{delim}\n{define}'''
|
||||||
args = self._get_compiler_check_args(env, extra_args, dependencies,
|
args = self._get_compiler_check_args(env, extra_args, dependencies,
|
||||||
mode='preprocess').to_native()
|
mode=CompileCheckMode.PREPROCESS).to_native()
|
||||||
func = functools.partial(self.cached_compile, code.format(**fargs), env.coredata, extra_args=args, mode='preprocess')
|
func = functools.partial(self.cached_compile, code.format(**fargs), env.coredata, extra_args=args, mode='preprocess')
|
||||||
if disable_cache:
|
if disable_cache:
|
||||||
func = functools.partial(self.compile, code.format(**fargs), extra_args=args, mode='preprocess', temp_dir=env.scratch_dir)
|
func = functools.partial(self.compile, code.format(**fargs), extra_args=args, mode='preprocess', temp_dir=env.scratch_dir)
|
||||||
|
@ -966,7 +960,7 @@ class CLikeCompiler(Compiler):
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
'''
|
'''
|
||||||
args = self.get_compiler_check_args()
|
args = self.get_compiler_check_args(CompileCheckMode.COMPILE)
|
||||||
n = 'symbols_have_underscore_prefix'
|
n = 'symbols_have_underscore_prefix'
|
||||||
with self._build_wrapper(code, env, extra_args=args, mode='compile', want_output=True, temp_dir=env.scratch_dir) as p:
|
with self._build_wrapper(code, env, extra_args=args, mode='compile', want_output=True, temp_dir=env.scratch_dir) as p:
|
||||||
if p.returncode != 0:
|
if p.returncode != 0:
|
||||||
|
|
Loading…
Reference in New Issue