diff options
author | Jon Turney <jon.turney@dronecode.org.uk> | 2018-09-20 20:29:57 +0100 |
---|---|---|
committer | Jon Turney <jon.turney@dronecode.org.uk> | 2018-11-04 15:42:00 +0000 |
commit | 64edfd50691be21fae1e61b8864d6de6fcead1d4 (patch) | |
tree | edff913b3cc3fa1adf558e1b1c860aad8f7a7717 | |
parent | 63f4f9481ebc865b11a06aeecf0c624104d46afd (diff) | |
download | meson-64edfd50691be21fae1e61b8864d6de6fcead1d4.zip meson-64edfd50691be21fae1e61b8864d6de6fcead1d4.tar.gz meson-64edfd50691be21fae1e61b8864d6de6fcead1d4.tar.bz2 |
Detect clang-cl as msvc-like, not clang-like
Handle clang's cl or clang-cl being in PATH, or set in CC/CXX
Future work: checking the name of the executable here seems like a bad idea.
These compilers will fail to be detected if they are renamed.
v2:
Update compiler.get_argument_type() test
Fix comparisons of id inside CCompiler, backends and elsewhere
v3:
ClangClCPPCompiler should be a subclass of ClangClCCompier, as well
Future work: mocking in test_find_library_patterns() is effected, as we
now test for a subclass, rather than self.id in CCompiler.get_library_naming()
-rw-r--r-- | mesonbuild/backend/backends.py | 4 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 14 | ||||
-rw-r--r-- | mesonbuild/build.py | 2 | ||||
-rw-r--r-- | mesonbuild/compilers/__init__.py | 4 | ||||
-rw-r--r-- | mesonbuild/compilers/c.py | 10 | ||||
-rw-r--r-- | mesonbuild/compilers/cpp.py | 6 | ||||
-rw-r--r-- | mesonbuild/dependencies/boost.py | 4 | ||||
-rw-r--r-- | mesonbuild/environment.py | 22 | ||||
-rwxr-xr-x | run_unittests.py | 4 | ||||
-rw-r--r-- | test cases/common/206 argument syntax/meson.build | 2 |
10 files changed, 48 insertions, 24 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 7dc1b83..370e35b 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -23,7 +23,7 @@ import subprocess from ..mesonlib import MesonException, OrderedSet from ..mesonlib import classify_unity_sources from ..mesonlib import File -from ..compilers import CompilerArgs +from ..compilers import CompilerArgs, VisualStudioCCompiler from collections import OrderedDict import shlex from functools import lru_cache @@ -491,7 +491,7 @@ class Backend: return args extra_args = [] # Compiler-specific escaping is needed for -D args but not for any others - if compiler.get_id() == 'msvc': + if isinstance(compiler, VisualStudioCCompiler): # MSVC needs escaping when a -D argument ends in \ or \" for arg in args: if arg.startswith('-D') or arg.startswith('/D'): diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 229980d..b6ed515 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -29,7 +29,7 @@ from .. import build from .. import mlog from .. import dependencies from .. import compilers -from ..compilers import CompilerArgs, CCompiler +from ..compilers import CompilerArgs, CCompiler, VisualStudioCCompiler from ..linkers import ArLinker from ..mesonlib import File, MesonException, OrderedSet from ..mesonlib import get_compiler_for_source, has_path_sep @@ -169,7 +169,7 @@ class NinjaBackend(backends.Backend): Detect the search prefix to use.''' for compiler in self.build.compilers.values(): # Have to detect the dependency format - if compiler.id == 'msvc': + if isinstance(compiler, VisualStudioCCompiler): break else: # None of our compilers are MSVC, we're done. @@ -1604,7 +1604,7 @@ rule FORTRAN_DEP_HACK%s compile_only_args=' '.join(compiler.get_compile_only_args()) ) description = ' description = Compiling %s object $out.\n' % compiler.get_display_language() - if compiler.get_id() == 'msvc': + if isinstance(compiler, VisualStudioCCompiler): deps = ' deps = msvc\n' else: deps = ' deps = gcc\n' @@ -1636,7 +1636,7 @@ rule FORTRAN_DEP_HACK%s if d != '$out' and d != '$in': d = quote_func(d) quoted_depargs.append(d) - if compiler.get_id() == 'msvc': + if isinstance(compiler, VisualStudioCCompiler): output = '' else: output = ' '.join(compiler.get_output_args('$out')) @@ -1648,7 +1648,7 @@ rule FORTRAN_DEP_HACK%s compile_only_args=' '.join(compiler.get_compile_only_args()) ) description = ' description = Precompiling header %s.\n' % '$in' - if compiler.get_id() == 'msvc': + if isinstance(compiler, VisualStudioCCompiler): deps = ' deps = msvc\n' else: deps = ' deps = gcc\n' @@ -1839,7 +1839,7 @@ rule FORTRAN_DEP_HACK%s return compiler.get_no_stdinc_args() def get_compile_debugfile_args(self, compiler, target, objfile): - if compiler.id != 'msvc': + if not isinstance(compiler, VisualStudioCCompiler): return [] # The way MSVC uses PDB files is documented exactly nowhere so # the following is what we have been able to decipher via @@ -2203,7 +2203,7 @@ rule FORTRAN_DEP_HACK%s ''.format(target.get_basename()) raise InvalidArguments(msg) compiler = target.compilers[lang] - if compiler.id == 'msvc': + if isinstance(compiler, VisualStudioCCompiler): src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[-1]) (commands, dep, dst, objs) = self.generate_msvc_pch_command(target, compiler, pch) extradep = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0]) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index df67c8e..8bb49c0 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1168,7 +1168,7 @@ You probably should put it in link_with instead.''') ''' linker, _ = self.get_clink_dynamic_linker_and_stdlibs() # Mixing many languages with MSVC is not supported yet so ignore stdlibs. - if linker and linker.get_id() in ['msvc', 'llvm', 'dmd']: + if linker and linker.get_id() in ['msvc', 'clang-cl', 'llvm', 'dmd']: return True return False diff --git a/mesonbuild/compilers/__init__.py b/mesonbuild/compilers/__init__.py index 677301e..7050b0c 100644 --- a/mesonbuild/compilers/__init__.py +++ b/mesonbuild/compilers/__init__.py @@ -45,6 +45,8 @@ __all__ = [ 'ClangCPPCompiler', 'ClangObjCCompiler', 'ClangObjCPPCompiler', + 'ClangClCCompiler', + 'ClangClCPPCompiler', 'CompilerArgs', 'CPPCompiler', 'DCompiler', @@ -114,6 +116,7 @@ from .c import ( ArmCCompiler, ArmclangCCompiler, ClangCCompiler, + ClangClCCompiler, GnuCCompiler, ElbrusCCompiler, IntelCCompiler, @@ -124,6 +127,7 @@ from .cpp import ( ArmCPPCompiler, ArmclangCPPCompiler, ClangCPPCompiler, + ClangClCPPCompiler, GnuCPPCompiler, ElbrusCPPCompiler, IntelCPPCompiler, diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 9b24e85..d17dd3a 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -170,7 +170,7 @@ class CCompiler(Compiler): else: # GNU ld and LLVM lld return ['-Wl,--allow-shlib-undefined'] - elif self.id == 'msvc': + elif isinstance(self, VisualStudioCCompiler): # link.exe return ['/FORCE:UNRESOLVED'] # FIXME: implement other linkers @@ -890,7 +890,7 @@ class CCompiler(Compiler): stlibext = ['a'] # We've always allowed libname to be both `foo` and `libfoo`, # and now people depend on it - if strict and self.id != 'msvc': # lib prefix is not usually used with msvc + if strict and not isinstance(self, VisualStudioCCompiler): # lib prefix is not usually used with msvc prefixes = ['lib'] else: prefixes = ['lib', ''] @@ -900,7 +900,7 @@ class CCompiler(Compiler): elif for_windows(env.is_cross_build(), env): # FIXME: .lib files can be import or static so we should read the # file, figure out which one it is, and reject the wrong kind. - if self.id == 'msvc': + if isinstance(self, VisualStudioCCompiler): shlibext = ['lib'] else: shlibext = ['dll.a', 'lib', 'dll'] @@ -1546,6 +1546,10 @@ class VisualStudioCCompiler(CCompiler): def get_argument_syntax(self): return 'msvc' +class ClangClCCompiler(VisualStudioCCompiler): + def __init__(self, exelist, version, is_cross, exe_wrap, is_64): + super().__init__(exelist, version, is_cross, exe_wrap, is_64) + self.id = 'clang-cl' class ArmCCompiler(ArmCompiler, CCompiler): def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 9dc2876..1045c7d 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -19,7 +19,7 @@ from .. import coredata from .. import mlog from ..mesonlib import MesonException, version_compare -from .c import CCompiler, VisualStudioCCompiler +from .c import CCompiler, VisualStudioCCompiler, ClangClCCompiler from .compilers import ( CompilerType, gnu_winlibs, @@ -378,6 +378,10 @@ class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): # so just use the plain C args. return VisualStudioCCompiler.get_compiler_check_args(self) +class ClangClCPPCompiler(VisualStudioCPPCompiler, ClangClCCompiler): + def __init__(self, exelist, version, is_cross, exe_wrap, is_64): + VisualStudioCPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, is_64) + self.id = 'clang-cl' class ArmCPPCompiler(ArmCompiler, CPPCompiler): def __init__(self, exelist, version, compiler_type, is_cross, exe_wrap=None, **kwargs): diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 17f9240..6a8050d 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -288,7 +288,7 @@ class BoostDependency(ExternalDependency): tag = None compiler = self.env.detect_cpp_compiler(self.want_cross) if mesonlib.for_windows(self.want_cross, self.env): - if compiler.get_id() == 'msvc': + if compiler.get_id() in ['msvc', 'clang-cl']: comp_ts_version = compiler.get_toolset_version() compiler_ts = comp_ts_version.split('.') # FIXME - what about other compilers? @@ -320,7 +320,7 @@ class BoostDependency(ExternalDependency): def arch_tag(self): # currently only applies to windows msvc installed binaries - if self.env.detect_cpp_compiler(self.want_cross).get_id() != 'msvc': + if self.env.detect_cpp_compiler(self.want_cross).get_id() not in ['msvc', 'clang-cl']: return '' # pre-compiled binaries only added arch tag for versions > 1.64 if float(self.version) < 1.65: diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 8c6c60e..d9de7db 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -39,6 +39,8 @@ from .compilers import ( ClangCPPCompiler, ClangObjCCompiler, ClangObjCPPCompiler, + ClangClCCompiler, + ClangClCPPCompiler, G95FortranCompiler, GnuCCompiler, GnuCPPCompiler, @@ -190,6 +192,8 @@ def detect_windows_arch(compilers): platform = os.environ.get('Platform', 'x86').lower() if platform == 'x86': return platform + if compiler.id == 'clang-cl' and not compiler.is_64: + return 'x86' if compiler.id == 'gcc' and compiler.has_builtin_define('__i386__'): return 'x86' return os_arch @@ -344,8 +348,8 @@ class Environment: # List of potential compilers. if mesonlib.is_windows(): - self.default_c = ['cl', 'cc', 'gcc', 'clang'] - self.default_cpp = ['cl', 'c++', 'g++', 'clang++'] + self.default_c = ['cl', 'cc', 'gcc', 'clang', 'clang-cl'] + self.default_cpp = ['cl', 'c++', 'g++', 'clang++', 'clang-cl'] else: self.default_c = ['cc', 'gcc', 'clang'] self.default_cpp = ['c++', 'g++', 'clang++'] @@ -537,7 +541,7 @@ This is probably wrong, it should always point to the native compiler.''' % evar for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] - if 'cl' in compiler or 'cl.exe' in compiler: + if not set(['cl', 'cl.exe', 'clang-cl', 'clang-cl.exe']).isdisjoint(compiler): # Watcom C provides it's own cl.exe clone that mimics an older # version of Microsoft's compiler. Since Watcom's cl.exe is # just a wrapper, we skip using it if we detect its presence @@ -606,6 +610,18 @@ This is probably wrong, it should always point to the native compiler.''' % evar compiler_type = CompilerType.ARM_WIN cls = ArmclangCCompiler if lang == 'c' else ArmclangCPPCompiler return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + if 'CL.EXE COMPATIBILITY' in out: + # if this is clang-cl masquerading as cl, detect it as cl, not + # clang + arg = '--version' + try: + p, out, err = Popen_safe(compiler + [arg]) + except OSError as e: + popen_exceptions[' '.join(compiler + [arg])] = e + version = search_version(out) + is_64 = 'Target: x86_64' in out + cls = ClangClCCompiler if lang == 'c' else ClangClCPPCompiler + return cls(compiler, version, is_cross, exe_wrap, is_64) if 'clang' in out: if 'Apple' in out or mesonlib.for_darwin(want_cross, self): compiler_type = CompilerType.CLANG_OSX diff --git a/run_unittests.py b/run_unittests.py index ee80a87..662ca06 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -624,10 +624,6 @@ class InternalTests(unittest.TestCase): with PatchModule(mesonbuild.compilers.c.for_windows, 'mesonbuild.compilers.c.for_windows', true): self._test_all_naming(cc, env, patterns, 'windows-mingw') - cc.id = 'msvc' - with PatchModule(mesonbuild.compilers.c.for_windows, - 'mesonbuild.compilers.c.for_windows', true): - self._test_all_naming(cc, env, patterns, 'windows-msvc') def test_pkgconfig_parse_libs(self): ''' diff --git a/test cases/common/206 argument syntax/meson.build b/test cases/common/206 argument syntax/meson.build index c884f90..216da45 100644 --- a/test cases/common/206 argument syntax/meson.build +++ b/test cases/common/206 argument syntax/meson.build @@ -7,7 +7,7 @@ cc = meson.get_compiler('c') if ['gcc', 'lcc', 'clang'].contains(cc.get_id()) expected = 'gcc' -elif cc.get_id() == 'msvc' +elif ['msvc', 'clang-cl'].contains(cc.get_id()) expected = 'msvc' elif cc.get_id() == 'intel' if host_machine.system() == 'windows' |