aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/compilers/detect.py91
-rw-r--r--mesonbuild/compilers/mixins/clang.py7
2 files changed, 77 insertions, 21 deletions
diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py
index f16e40f..255812c 100644
--- a/mesonbuild/compilers/detect.py
+++ b/mesonbuild/compilers/detect.py
@@ -340,7 +340,7 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin
guess_gcc_or_lcc = None
if guess_gcc_or_lcc:
- defines = _get_gnu_compiler_defines(compiler)
+ defines = _get_gnu_compiler_defines(compiler, lang)
if not defines:
popen_exceptions[join_args(compiler)] = 'no pre-processor defines'
continue
@@ -449,7 +449,7 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin
if 'clang' in out or 'Clang' in out:
linker = None
- defines = _get_clang_compiler_defines(compiler)
+ defines = _get_clang_compiler_defines(compiler, lang)
# Even if the for_machine is darwin, we could be using vanilla
# clang.
@@ -676,7 +676,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C
guess_gcc_or_lcc = 'lcc'
if guess_gcc_or_lcc:
- defines = _get_gnu_compiler_defines(compiler)
+ defines = _get_gnu_compiler_defines(compiler, 'fortran')
if not defines:
popen_exceptions[join_args(compiler)] = 'no pre-processor defines'
continue
@@ -843,7 +843,7 @@ def _detect_objc_or_objcpp_compiler(env: 'Environment', lang: str, for_machine:
continue
version = search_version(out)
if 'Free Software Foundation' in out:
- defines = _get_gnu_compiler_defines(compiler)
+ defines = _get_gnu_compiler_defines(compiler, lang)
if not defines:
popen_exceptions[join_args(compiler)] = 'no pre-processor defines'
continue
@@ -855,7 +855,7 @@ def _detect_objc_or_objcpp_compiler(env: 'Environment', lang: str, for_machine:
defines, linker=linker)
if 'clang' in out:
linker = None
- defines = _get_clang_compiler_defines(compiler)
+ defines = _get_clang_compiler_defines(compiler, lang)
if not defines:
popen_exceptions[join_args(compiler)] = 'no pre-processor defines'
continue
@@ -1329,19 +1329,43 @@ def detect_masm_compiler(env: 'Environment', for_machine: MachineChoice) -> Comp
# GNU/Clang defines and version
# =============================
-def _get_gnu_compiler_defines(compiler: T.List[str]) -> T.Dict[str, str]:
+def _get_gnu_compiler_defines(compiler: T.List[str], lang: str) -> T.Dict[str, str]:
"""
Get the list of GCC pre-processor defines
"""
+ from .mixins.gnu import _LANG_MAP as gnu_LANG_MAP
+
+ def _try_obtain_compiler_defines(args: T.List[str]) -> str:
+ mlog.debug(f'Running command: {join_args(args)}')
+ p, output, error = Popen_safe(compiler + args, write='', stdin=subprocess.PIPE)
+ if p.returncode != 0:
+ raise EnvironmentException('Unable to get gcc pre-processor defines:\n'
+ f'Compiler stdout:\n{output}\n-----\n'
+ f'Compiler stderr:\n{error}\n-----\n')
+ return output
+
# Arguments to output compiler pre-processor defines to stdout
# gcc, g++, and gfortran all support these arguments
- args = compiler + ['-E', '-dM', '-']
- mlog.debug(f'Running command: {join_args(args)}')
- p, output, error = Popen_safe(args, write='', stdin=subprocess.PIPE)
- if p.returncode != 0:
- raise EnvironmentException('Unable to detect gcc pre-processor defines:\n'
- f'Compiler stdout:\n{output}\n-----\n'
- f'Compiler stderr:\n{error}\n-----\n')
+ baseline_test_args = ['-E', '-dM', '-']
+ try:
+ # We assume that when _get_gnu_compiler_defines is called, it's
+ # close enough to a GCCish compiler so we reuse the _LANG_MAP
+ # from the GCC mixin. This isn't a dangerous assumption because
+ # we fallback if the detection fails anyway.
+
+ # We might not have a match for Fortran, so fallback to detection
+ # based on the driver.
+ lang = gnu_LANG_MAP[lang]
+
+ # The compiler may not infer the target language based on the driver name
+ # so first, try with '-cpp -x lang', then fallback without given it's less
+ # portable. We try with '-cpp' as GCC needs it for Fortran at least, and
+ # it seems to do no harm.
+ output = _try_obtain_compiler_defines(['-cpp', '-x', lang] + baseline_test_args)
+ except (EnvironmentException, KeyError):
+ mlog.debug(f'pre-processor extraction using -cpp -x {lang} failed, falling back w/o lang')
+ output = _try_obtain_compiler_defines(baseline_test_args)
+
# Parse several lines of the type:
# `#define ___SOME_DEF some_value`
# and extract `___SOME_DEF`
@@ -1358,17 +1382,42 @@ def _get_gnu_compiler_defines(compiler: T.List[str]) -> T.Dict[str, str]:
defines[rest[0]] = rest[1]
return defines
-def _get_clang_compiler_defines(compiler: T.List[str]) -> T.Dict[str, str]:
+def _get_clang_compiler_defines(compiler: T.List[str], lang: str) -> T.Dict[str, str]:
"""
Get the list of Clang pre-processor defines
"""
- args = compiler + ['-E', '-dM', '-']
- mlog.debug(f'Running command: {join_args(args)}')
- p, output, error = Popen_safe(args, write='', stdin=subprocess.PIPE)
- if p.returncode != 0:
- raise EnvironmentException('Unable to get clang pre-processor defines:\n'
- f'Compiler stdout:\n{output}\n-----\n'
- f'Compiler stderr:\n{error}\n-----\n')
+ from .mixins.clang import _LANG_MAP as clang_LANG_MAP
+
+ def _try_obtain_compiler_defines(args: T.List[str]) -> str:
+ mlog.debug(f'Running command: {join_args(args)}')
+ p, output, error = Popen_safe(compiler + args, write='', stdin=subprocess.PIPE)
+ if p.returncode != 0:
+ raise EnvironmentException('Unable to get clang pre-processor defines:\n'
+ f'Compiler stdout:\n{output}\n-----\n'
+ f'Compiler stderr:\n{error}\n-----\n')
+ return output
+
+ # Arguments to output compiler pre-processor defines to stdout
+ baseline_test_args = ['-E', '-dM', '-']
+ try:
+ # We assume that when _get_clang_compiler_defines is called, it's
+ # close enough to a Clangish compiler so we reuse the _LANG_MAP
+ # from the Clang mixin. This isn't a dangerous assumption because
+ # we fallback if the detection fails anyway.
+
+ # We might not have a match for Fortran, so fallback to detection
+ # based on the driver.
+ lang = clang_LANG_MAP[lang]
+
+ # The compiler may not infer the target language based on the driver name
+ # so first, try with '-cpp -x lang', then fallback without given it's less
+ # portable. We try with '-cpp' as GCC needs it for Fortran at least, and
+ # it seems to do no harm.
+ output = _try_obtain_compiler_defines(['-cpp', '-x', lang] + baseline_test_args)
+ except (EnvironmentException, KeyError):
+ mlog.debug(f'pre-processor extraction using -cpp -x {lang} failed, falling back w/o lang')
+ output = _try_obtain_compiler_defines(baseline_test_args)
+
defines: T.Dict[str, str] = {}
for line in output.split('\n'):
if not line:
diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py
index a9bf566..de9d8f8 100644
--- a/mesonbuild/compilers/mixins/clang.py
+++ b/mesonbuild/compilers/mixins/clang.py
@@ -36,6 +36,13 @@ clang_optimization_args: T.Dict[str, T.List[str]] = {
's': ['-Oz'],
}
+_LANG_MAP = {
+ 'c': 'c',
+ 'cpp': 'c++',
+ 'objc': 'objective-c',
+ 'objcpp': 'objective-c++',
+}
+
class ClangCompiler(GnuLikeCompiler):
id = 'clang'