diff options
31 files changed, 217 insertions, 128 deletions
diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8c36abd..5f7e3c4 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -44,6 +44,10 @@ jobs: arch: x64 compiler: msvc2017 backend: vs2017 + clangclx64ninja: + arch: x64 + compiler: clang-cl + backend: ninja steps: - template: ci/azure-steps.yml diff --git a/ci/azure-steps.yml b/ci/azure-steps.yml index 5c4a058..6303761 100644 --- a/ci/azure-steps.yml +++ b/ci/azure-steps.yml @@ -48,13 +48,34 @@ steps: # add downloads to PATH $env:Path = "$env:SYSTEM_WORKFOLDER;$env:Path" + $origPath = $env:Path # import visual studio variables + if ($env:compiler -eq 'msvc2015') { + $vsver = $env:compiler.Replace('msvc', '') + } else { + $vsver = '2017' + } Set-PSRepository -Name PSGallery -InstallationPolicy Trusted Install-Module Pscx -Scope CurrentUser -AllowClobber Install-Module VSSetup -Scope CurrentUser - $vsver = $env:compiler.Replace('msvc', '') Import-VisualStudioVars -VisualStudioVersion $vsver -Architecture $(arch) + if ($env:compiler -eq 'clang-cl') { + # drop visual studio from PATH + # (but leave INCLUDE, LIB and WindowsSdkDir environment variables set) + $env:Path = $origPath + + # install llvm for clang-cl builds + DownloadFile -Source 'http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe' -Destination LLVM-7.0.0-win64.exe + Start-Process .\LLVM-7.0.0-win64.exe -ArgumentList '/S' -Wait + $env:Path = "C:\Program Files\LLVM\bin;$env:Path" + $env:CC = "clang-cl" + $env:CXX = "clang-cl" + + # and use Windows SDK tools + $env:Path = "$env:WindowsSdkDir\bin\$env:Arch;$env:Path" + } + # add .NET framework tools to path for resgen for C# tests # (always use 32-bit tool, as there doesn't seem to be a 64-bit tool) if ((Get-Command "resgen.exe" -ErrorAction SilentlyContinue) -eq $null) { 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..28c6480 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. @@ -185,7 +185,8 @@ int dummy; # and locale dependent. Any attempt at converting it to # Python strings leads to failure. We _must_ do this detection # in raw byte mode and write the result in raw bytes. - pc = subprocess.Popen(['cl', '/showIncludes', '/c', 'incdetect.c'], + pc = subprocess.Popen([compiler.get_exelist(), + '/showIncludes', '/c', 'incdetect.c'], cwd=self.environment.get_scratch_dir(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdo, _) = pc.communicate() @@ -195,7 +196,7 @@ int dummy; # different locales have different messages with a different # number of colons. Match up to the the drive name 'd:\'. matchre = re.compile(rb"^(.*\s)[a-zA-Z]:\\.*stdio.h$") - for line in stdo.split(b'\r\n'): + for line in re.split(rb'\r?\n', stdo): match = matchre.match(line) if match: with open(tempfilename, 'ab') as binfile: @@ -1604,7 +1605,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 +1637,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 +1649,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 +1840,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 +2204,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..35c71df 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 @@ -392,6 +392,8 @@ class CCompiler(Compiler): return self.compiles(t.format(**fargs), env, extra_args, dependencies) def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): + if callable(extra_args): + extra_args = extra_args(mode) if extra_args is None: extra_args = [] elif isinstance(extra_args, str): @@ -890,7 +892,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 +902,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'] @@ -1296,7 +1298,7 @@ class VisualStudioCCompiler(CCompiler): def get_buildtype_args(self, buildtype): args = compilers.msvc_buildtype_args[buildtype] - if version_compare(self.version, '<18.0'): + if self.id == 'msvc' and version_compare(self.version, '<18.0'): args = [arg for arg in args if arg != '/Gw'] return args @@ -1314,6 +1316,8 @@ class VisualStudioCCompiler(CCompiler): def get_pch_use_args(self, pch_dir, header): base = os.path.basename(header) + if self.id == 'clang-cl': + base = header pchname = self.get_pch_name(header) return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)] @@ -1341,7 +1345,12 @@ class VisualStudioCCompiler(CCompiler): return [] def get_linker_exelist(self): - return ['link'] # FIXME, should have same path as compiler. + # FIXME, should have same path as compiler. + # FIXME, should be controllable via cross-file. + if self.id == 'clang-cl': + return ['lld-link'] + else: + return ['link'] def get_linker_always_args(self): return ['/nologo'] @@ -1449,6 +1458,8 @@ class VisualStudioCCompiler(CCompiler): # http://stackoverflow.com/questions/15259720/how-can-i-make-the-microsoft-c-compiler-treat-unknown-flags-as-errors-rather-t def has_arguments(self, args, env, code, mode): warning_text = '4044' if mode == 'link' else '9002' + if self.id == 'clang-cl' and mode != 'link': + args = args + ['-Werror=unknown-argument'] with self._build_wrapper(code, env, extra_args=args, mode=mode) as p: if p.returncode != 0: return False @@ -1464,7 +1475,7 @@ class VisualStudioCCompiler(CCompiler): # build obviously, which is why we only do this when PCH is on. # This was added in Visual Studio 2013 (MSVC 18.0). Before that it was # always on: https://msdn.microsoft.com/en-us/library/dn502518.aspx - if pch and version_compare(self.version, '>=18.0'): + if pch and self.id == 'msvc' and version_compare(self.version, '>=18.0'): args = ['/FS'] + args return args @@ -1481,7 +1492,7 @@ class VisualStudioCCompiler(CCompiler): def get_instruction_set_args(self, instruction_set): if self.is_64: return vs64_instruction_set_args.get(instruction_set, None) - if self.version.split('.')[0] == '16' and instruction_set == 'avx': + if self.id == 'msvc' and self.version.split('.')[0] == '16' and instruction_set == 'avx': # VS documentation says that this exists and should work, but # it does not. The headers do not contain AVX intrinsics # and the can not be called. @@ -1489,6 +1500,10 @@ class VisualStudioCCompiler(CCompiler): return vs32_instruction_set_args.get(instruction_set, None) def get_toolset_version(self): + if self.id == 'clang-cl': + # I have no idea + return '14.1' + # See boost/config/compiler/visualc.cpp for up to date mapping try: version = int(''.join(self.version.split('.')[0:2])) @@ -1546,6 +1561,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..65a1033 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, @@ -310,12 +310,15 @@ class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): def get_options(self): cpp_stds = ['none', 'c++11', 'vc++11'] - # Visual Studio 2015 and later - if version_compare(self.version, '>=19'): - cpp_stds.extend(['c++14', 'vc++14', 'c++latest', 'vc++latest']) - # Visual Studio 2017 and later - if version_compare(self.version, '>=19.11'): - cpp_stds.extend(['c++17', 'vc++17']) + if self.id == 'clang-cl': + cpp_stds.extend(['c++14', 'vc++14', 'c++17', 'vc++17', 'c++latest']) + else: + # Visual Studio 2015 and later + if version_compare(self.version, '>=19'): + cpp_stds.extend(['c++14', 'vc++14', 'c++latest', 'vc++latest']) + # Visual Studio 2017 and later + if version_compare(self.version, '>=19.11'): + cpp_stds.extend(['c++17', 'vc++17']) opts = CPPCompiler.get_options(self) opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh', @@ -356,7 +359,7 @@ class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): # which means setting the C++ standard version to C++14, in compilers that support it # (i.e., after VS2015U3) # if one is using anything before that point, one cannot set the standard. - if version_compare(self.version, '>=19.00.24210'): + if self.id == 'clang-cl' or version_compare(self.version, '>=19.00.24210'): mlog.warning('MSVC does not support C++11; ' 'attempting best effort; setting the standard to C++14') args.append('/std:c++14') @@ -378,6 +381,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/compilers/d.py b/mesonbuild/compilers/d.py index 099d907..0a59e7f 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -274,6 +274,8 @@ class DCompiler(Compiler): return ['-Wl,-rpath,{}'.format(paths)] def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): + if callable(extra_args): + extra_args = extra_args(mode) if extra_args is None: extra_args = [] elif isinstance(extra_args, str): 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..dfed376 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++'] @@ -359,6 +363,7 @@ class Environment: self.default_rust = ['rustc'] self.default_static_linker = ['ar'] self.vs_static_linker = ['lib'] + self.clang_cl_static_linker = ['llvm-lib'] self.gcc_static_linker = ['gcc-ar'] self.clang_static_linker = ['llvm-ar'] @@ -537,7 +542,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 +611,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 @@ -903,7 +920,7 @@ This is probably wrong, it should always point to the native compiler.''' % evar if evar in os.environ: linkers = [shlex.split(os.environ[evar])] elif isinstance(compiler, compilers.VisualStudioCCompiler): - linkers = [self.vs_static_linker] + linkers = [self.vs_static_linker, self.clang_cl_static_linker] elif isinstance(compiler, compilers.GnuCompiler): # Use gcc-ar if available; needed for LTO linkers = [self.gcc_static_linker, self.default_static_linker] @@ -913,14 +930,14 @@ This is probably wrong, it should always point to the native compiler.''' % evar elif isinstance(compiler, compilers.DCompiler): # Prefer static linkers over linkers used by D compilers if mesonlib.is_windows(): - linkers = [self.vs_static_linker, compiler.get_linker_exelist()] + linkers = [self.vs_static_linker, self.clang_cl_static_linker, compiler.get_linker_exelist()] else: linkers = [self.default_static_linker, compiler.get_linker_exelist()] else: linkers = [self.default_static_linker] popen_exceptions = {} for linker in linkers: - if 'lib' in linker or 'lib.exe' in linker: + if not set(['lib', 'lib.exe', 'llvm-lib', 'llvm-lib.exe']).isdisjoint(linker): arg = '/?' else: arg = '--version' @@ -929,7 +946,7 @@ This is probably wrong, it should always point to the native compiler.''' % evar except OSError as e: popen_exceptions[' '.join(linker + [arg])] = e continue - if '/OUT:' in out or '/OUT:' in err: + if '/OUT:' in out.upper() or '/OUT:' in err.upper(): return VisualStudioLinker(linker) if p.returncode == 0 and ('armar' in linker or 'armar.exe' in linker): return ArmarLinker(linker) diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index c2cfe5c..86b761e 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -38,6 +38,7 @@ import subprocess from collections import namedtuple from pathlib import PurePath import traceback +import functools import importlib @@ -965,7 +966,7 @@ class CompilerHolder(InterpreterObject): def cmd_array_method(self, args, kwargs): return self.compiler.exelist - def determine_args(self, kwargs): + def determine_args(self, kwargs, mode='link'): nobuiltins = kwargs.get('no_builtin_args', False) if not isinstance(nobuiltins, bool): raise InterpreterException('Type of no_builtin_args not a boolean.') @@ -981,7 +982,8 @@ class CompilerHolder(InterpreterObject): if not nobuiltins: opts = self.environment.coredata.compiler_options args += self.compiler.get_option_compile_args(opts) - args += self.compiler.get_option_link_args(opts) + if mode == 'link': + args += self.compiler.get_option_link_args(opts) args += mesonlib.stringlistify(kwargs.get('args', [])) return args @@ -1039,7 +1041,7 @@ class CompilerHolder(InterpreterObject): testname = kwargs.get('name', '') if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs, endl=None) result = self.compiler.run(code, self.environment, extra_args, deps) if len(testname) > 0: @@ -1094,7 +1096,7 @@ class CompilerHolder(InterpreterObject): prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_member must be a string.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) had = self.compiler.has_members(typename, [membername], prefix, self.environment, extra_args, deps) @@ -1122,7 +1124,7 @@ class CompilerHolder(InterpreterObject): prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_members must be a string.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) had = self.compiler.has_members(typename, membernames, prefix, self.environment, extra_args, deps) @@ -1175,7 +1177,7 @@ class CompilerHolder(InterpreterObject): prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_type must be a string.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) had = self.compiler.has_type(typename, prefix, self.environment, extra_args, deps) if had: @@ -1213,7 +1215,7 @@ class CompilerHolder(InterpreterObject): raise InterpreterException('High argument of compute_int must be an int.') if guess is not None and not isinstance(guess, int): raise InterpreterException('Guess argument of compute_int must be an int.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) res = self.compiler.compute_int(expression, low, high, guess, prefix, self.environment, extra_args, deps) mlog.log('Computing int of', mlog.bold(expression, True), msg, res) @@ -1234,7 +1236,7 @@ class CompilerHolder(InterpreterObject): prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of sizeof must be a string.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) esize = self.compiler.sizeof(element, prefix, self.environment, extra_args, deps) mlog.log('Checking for size of', mlog.bold(element, True), msg, esize) @@ -1256,7 +1258,7 @@ class CompilerHolder(InterpreterObject): prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of get_define() must be a string.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) value = self.compiler.get_define(element, prefix, self.environment, extra_args, deps) mlog.log('Fetching value of define', mlog.bold(element, True), msg, value) @@ -1281,7 +1283,7 @@ class CompilerHolder(InterpreterObject): testname = kwargs.get('name', '') if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs, endl=None) result = self.compiler.compiles(code, self.environment, extra_args, deps) if len(testname) > 0: @@ -1311,7 +1313,7 @@ class CompilerHolder(InterpreterObject): testname = kwargs.get('name', '') if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs, endl=None) result = self.compiler.links(code, self.environment, extra_args, deps) if len(testname) > 0: @@ -1338,7 +1340,7 @@ class CompilerHolder(InterpreterObject): prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_header must be a string.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) haz = self.compiler.check_header(hname, prefix, self.environment, extra_args, deps) if haz: @@ -1363,7 +1365,7 @@ class CompilerHolder(InterpreterObject): prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_header must be a string.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) haz = self.compiler.has_header(hname, prefix, self.environment, extra_args, deps) if haz: @@ -1389,7 +1391,7 @@ class CompilerHolder(InterpreterObject): prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_header_symbol must be a string.') - extra_args = self.determine_args(kwargs) + extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) haz = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment, extra_args, deps) if haz: diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index f0d5113..4d0f244 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -60,7 +60,7 @@ class WindowsModule(ExtensionModule): if not rescomp or not rescomp.found(): comp = self.detect_compiler(state.compilers) - if comp.id == 'msvc': + if comp.id == 'msvc' or comp.id == 'clang-cl': rescomp = ExternalProgram('rc', silent=True) else: rescomp = ExternalProgram('windres', silent=True) diff --git a/run_project_tests.py b/run_project_tests.py index 2445dd4..c73567e 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -132,17 +132,17 @@ def platform_fix_name(fname, compiler, env): if fname.startswith('?msvc:'): fname = fname[6:] - if compiler != 'cl': + if compiler != 'msvc': return None if fname.startswith('?gcc:'): fname = fname[5:] - if compiler == 'cl': + if compiler == 'msvc': return None if fname.startswith('?cygwin:'): fname = fname[8:] - if compiler == 'cl' or not mesonlib.for_cygwin(env.is_cross_build(), env): + if compiler == 'msvc' or not mesonlib.for_cygwin(env.is_cross_build(), env): return None return fname @@ -687,14 +687,18 @@ def check_meson_commands_work(): def detect_system_compiler(): global system_compiler - if shutil.which('cl'): - system_compiler = 'cl' - elif shutil.which('cc'): - system_compiler = 'cc' - elif shutil.which('gcc'): - system_compiler = 'gcc' - else: - raise RuntimeError("Could not find C compiler.") + + with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: + env = environment.Environment(None, build_dir, get_fake_options('/')) + try: + comp = env.detect_c_compiler(env.is_cross_build()) + except: + raise RuntimeError("Could not find C compiler.") + system_compiler = comp.get_id() + + # canonicalize for platform_fix_name() + if system_compiler == 'clang-cl': + system_compiler = 'msvc' if __name__ == '__main__': parser = argparse.ArgumentParser(description="Run the test suite of Meson.") diff --git a/run_unittests.py b/run_unittests.py index ee80a87..8aa0425 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -601,7 +601,7 @@ class InternalTests(unittest.TestCase): elif is_cygwin(): self._test_all_naming(cc, env, patterns, 'cygwin') elif is_windows(): - if cc.get_id() == 'msvc': + if cc.get_argument_syntax() == 'msvc': self._test_all_naming(cc, env, patterns, 'windows-msvc') else: self._test_all_naming(cc, env, patterns, 'windows-mingw') @@ -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): ''' @@ -679,7 +675,7 @@ class InternalTests(unittest.TestCase): bar_dep = PkgConfigDependency('bar', env, kwargs) self.assertEqual(bar_dep.get_link_args(), [(p2 / 'libbar.a').as_posix()]) internal_dep = PkgConfigDependency('internal', env, kwargs) - if compiler.get_id() == 'msvc': + if compiler.get_argument_syntax() == 'msvc': self.assertEqual(internal_dep.get_link_args(), []) else: link_args = internal_dep.get_link_args() @@ -1602,6 +1598,7 @@ class AllPlatformTests(BasePlatformTests): clang = mesonbuild.compilers.ClangCompiler intel = mesonbuild.compilers.IntelCompiler msvc = mesonbuild.compilers.VisualStudioCCompiler + clangcl = mesonbuild.compilers.ClangClCCompiler ar = mesonbuild.linkers.ArLinker lib = mesonbuild.linkers.VisualStudioLinker langs = [('c', 'CC'), ('cpp', 'CXX')] @@ -1623,6 +1620,9 @@ class AllPlatformTests(BasePlatformTests): if ebase.startswith('g') or ebase.endswith(('-gcc', '-g++')): self.assertIsInstance(ecc, gnu) self.assertIsInstance(elinker, ar) + elif 'clang-cl' in ebase: + self.assertIsInstance(ecc, clangcl) + self.assertIsInstance(elinker, lib) elif 'clang' in ebase: self.assertIsInstance(ecc, clang) self.assertIsInstance(elinker, ar) @@ -1696,6 +1696,8 @@ class AllPlatformTests(BasePlatformTests): wrapperlinker_s += shlex.quote(w) + ' ' os.environ['AR'] = wrapperlinker_s wlinker = env.detect_static_linker(wcc) + # Pop it so we don't use it for the next detection + evalue = os.environ.pop('AR') # Must be the same type since it's a wrapper around the same exelist self.assertIs(type(cc), type(wcc)) self.assertIs(type(linker), type(wlinker)) @@ -1994,7 +1996,7 @@ int main(int argc, char **argv) { def pbcompile(self, compiler, source, objectfile, extra_args=[]): cmd = compiler.get_exelist() - if compiler.id == 'msvc': + if compiler.get_argument_syntax() == 'msvc': cmd += ['/nologo', '/Fo' + objectfile, '/c', source] + extra_args else: cmd += ['-c', source, '-o', objectfile] + extra_args @@ -2016,7 +2018,7 @@ int main(int argc, char **argv) { def build_static_lib(self, compiler, linker, source, objectfile, outfile, extra_args=None): if extra_args is None: extra_args = [] - if compiler.id == 'msvc': + if compiler.get_argument_syntax() == 'msvc': link_cmd = ['lib', '/NOLOGO', '/OUT:' + outfile, objectfile] else: link_cmd = ['ar', 'csr', outfile, objectfile] @@ -2049,9 +2051,10 @@ int main(int argc, char **argv) { def build_shared_lib(self, compiler, source, objectfile, outfile, impfile, extra_args=None): if extra_args is None: extra_args = [] - if compiler.id == 'msvc': - link_cmd = ['link', '/NOLOGO', '/DLL', '/DEBUG', - '/IMPLIB:' + impfile, '/OUT:' + outfile, objectfile] + if compiler.get_argument_syntax() == 'msvc': + link_cmd = compiler.get_linker_exelist() + [ + '/NOLOGO', '/DLL', '/DEBUG', '/IMPLIB:' + impfile, + '/OUT:' + outfile, objectfile] else: extra_args += ['-fPIC'] link_cmd = compiler.get_exelist() + ['-shared', '-o', outfile, objectfile] @@ -2069,7 +2072,7 @@ int main(int argc, char **argv) { source = os.path.join(tdir, 'alexandria.c') objectfile = os.path.join(tdir, 'alexandria.' + object_suffix) impfile = os.path.join(tdir, 'alexandria.lib') - if cc.id == 'msvc': + if cc.get_argument_syntax() == 'msvc': shlibfile = os.path.join(tdir, 'alexandria.' + shared_suffix) elif is_cygwin(): shlibfile = os.path.join(tdir, 'cygalexandria.' + shared_suffix) @@ -2107,7 +2110,7 @@ int main(int argc, char **argv) { objectfile = os.path.join(testdir, 'foo.' + objext) stlibfile = os.path.join(testdir, 'libfoo.a') impfile = os.path.join(testdir, 'foo.lib') - if cc.id == 'msvc': + if cc.get_argument_syntax() == 'msvc': shlibfile = os.path.join(testdir, 'foo.' + shext) elif is_cygwin(): shlibfile = os.path.join(testdir, 'cygfoo.' + shext) @@ -2449,7 +2452,7 @@ recommended as it is not supported on some platforms''') testdirlib = os.path.join(testdirbase, 'lib') extra_args = None env = get_fake_env(testdirlib, self.builddir, self.prefix) - if env.detect_c_compiler(False).get_id() != 'msvc': + if env.detect_c_compiler(False).get_id() not in ['msvc', 'clang-cl']: # static libraries are not linkable with -l with msvc because meson installs them # as .a files which unix_args_to_native will not know as it expects libraries to use # .lib as extension. For a DLL the import library is installed as .lib. Thus for msvc @@ -3058,7 +3061,7 @@ class WindowsTests(BasePlatformTests): testdir = os.path.join(self.platform_test_dir, '1 basic') env = get_fake_env(testdir, self.builddir, self.prefix) cc = env.detect_c_compiler(False) - if cc.id != 'msvc': + if cc.get_argument_syntax() != 'msvc': raise unittest.SkipTest('Not using MSVC') # To force people to update this test, and also test self.assertEqual(set(cc.ignore_libs), {'c', 'm', 'pthread', 'dl', 'rt'}) @@ -3070,7 +3073,7 @@ class WindowsTests(BasePlatformTests): # resource compiler depfile generation is not yet implemented for msvc env = get_fake_env(testdir, self.builddir, self.prefix) - depfile_works = env.detect_c_compiler(False).get_id() != 'msvc' + depfile_works = env.detect_c_compiler(False).get_id() not in ['msvc', 'clang-cl'] self.init(testdir) self.build() @@ -3097,9 +3100,14 @@ class WindowsTests(BasePlatformTests): self.utime(os.path.join(testdir, 'res', 'resource.h')) self.assertRebuiltTarget('prog_1') - @unittest.skipIf(shutil.which('cl') is None, 'Test only applies to VS') def test_msvc_cpp17(self): testdir = os.path.join(self.unit_test_dir, '45 vscpp17') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = env.detect_c_compiler(False) + if cc.get_argument_syntax() != 'msvc': + raise unittest.SkipTest('Test only applies to MSVC-like compilers') + try: self.init(testdir) except subprocess.CalledProcessError: diff --git a/test cases/common/100 manygen/subdir/manygen.py b/test cases/common/100 manygen/subdir/manygen.py index 7ffd435..0fbc2ec 100755 --- a/test cases/common/100 manygen/subdir/manygen.py +++ b/test cases/common/100 manygen/subdir/manygen.py @@ -6,38 +6,30 @@ from __future__ import print_function # file and a header file. import sys, os -import shutil, subprocess +import subprocess with open(sys.argv[1]) as f: funcname = f.readline().strip() outdir = sys.argv[2] buildtype_args = sys.argv[3] +compiler_type = sys.argv[4] +compiler = sys.argv[5:] if not os.path.isdir(outdir): print('Outdir does not exist.') sys.exit(1) -# Emulate the environment.detect_c_compiler() logic -compiler = os.environ.get('CC', None) -if not compiler: - compiler = shutil.which('cl') or \ - shutil.which('gcc') or \ - shutil.which('clang') or \ - shutil.which('cc') - -compbase = os.path.basename(compiler) -if 'cl' in compbase and 'clang' not in compbase: +if compiler_type == 'msvc': libsuffix = '.lib' is_vs = True - compiler = 'cl' - linker = 'lib' + if any(['clang-cl' in c for c in compiler]): + linker = 'llvm-lib' + else: + linker = 'lib' else: libsuffix = '.a' is_vs = False linker = 'ar' - if compiler is None: - print('No known compilers found.') - sys.exit(1) objsuffix = '.o' @@ -70,9 +62,9 @@ with open(tmpc, 'w') as f: ''' % funcname) if is_vs: - subprocess.check_call([compiler, '/nologo', '/c', buildtype_args, '/Fo' + outo, tmpc]) + subprocess.check_call(compiler + ['/nologo', '/c', buildtype_args, '/Fo' + outo, tmpc]) else: - subprocess.check_call([compiler, '-c', '-o', outo, tmpc]) + subprocess.check_call(compiler + ['-c', '-o', outo, tmpc]) with open(tmpc, 'w') as f: f.write('''int %s_in_lib() { @@ -81,10 +73,10 @@ with open(tmpc, 'w') as f: ''' % funcname) if is_vs: - subprocess.check_call([compiler, '/nologo', '/c', '/Fo' + tmpo, tmpc]) + subprocess.check_call(compiler + ['/nologo', '/c', '/Fo' + tmpo, tmpc]) subprocess.check_call([linker, '/NOLOGO', '/OUT:' + outa, tmpo]) else: - subprocess.check_call([compiler, '-c', '-o', tmpo, tmpc]) + subprocess.check_call(compiler + ['-c', '-o', tmpo, tmpc]) subprocess.check_call([linker, 'csr', outa, tmpo]) os.unlink(tmpo) diff --git a/test cases/common/100 manygen/subdir/meson.build b/test cases/common/100 manygen/subdir/meson.build index 73b4ff7..56f60e6 100644 --- a/test cases/common/100 manygen/subdir/meson.build +++ b/test cases/common/100 manygen/subdir/meson.build @@ -3,7 +3,8 @@ py3_bin = import('python3').find_python() buildtype = get_option('buildtype') buildtype_args = '-Dfooxxx' # a useless compiler argument -if meson.get_compiler('c').get_id() == 'msvc' +cc = meson.get_compiler('c') +if cc.get_argument_syntax() == 'msvc' # We need our manually generated code to use the same CRT as the executable. # Taken from compilers.py since build files do not have access to this. if buildtype == 'debug' @@ -21,5 +22,5 @@ endif generated = custom_target('manygen', output : outfiles, input : ['funcinfo.def'], - command : [py3_bin, gen[0], '@INPUT@', '@OUTDIR@', buildtype_args], + command : [py3_bin, gen[0], '@INPUT@', '@OUTDIR@', buildtype_args, cc.get_argument_syntax(), cc.cmd_array()], ) diff --git a/test cases/common/112 spaces backslash/meson.build b/test cases/common/112 spaces backslash/meson.build index bf614e8..d590494 100644 --- a/test cases/common/112 spaces backslash/meson.build +++ b/test cases/common/112 spaces backslash/meson.build @@ -7,7 +7,7 @@ project('comparer', 'c') include_dir = meson.current_source_dir() + '/include' default_c_args = ['-I' + include_dir] -if meson.get_compiler('c').get_id() == 'msvc' +if meson.get_compiler('c').get_argument_syntax() == 'msvc' default_c_args += ['/Faasm output\\'] # Hack to create the 'asm output' directory in the builddir subdir('asm output') diff --git a/test cases/common/123 llvm ir and assembly/meson.build b/test cases/common/123 llvm ir and assembly/meson.build index 51321fb..a67c6c6 100644 --- a/test cases/common/123 llvm ir and assembly/meson.build +++ b/test cases/common/123 llvm ir and assembly/meson.build @@ -28,15 +28,18 @@ foreach lang : ['c', 'cpp'] # MSVC cannot directly compile assembly files, so we pass it through the # cl.exe pre-processor first and then assemble it with the ml.exe assembler. # Then we can link it into the executable. - if cc_id == 'msvc' - cl = find_program('cl') + if cc.get_argument_syntax() == 'msvc' + cl = cc.cmd_array() if cpu == 'x86' - ml = find_program('ml') + ml = find_program('ml', required: false) elif cpu == 'x86_64' - ml = find_program('ml64') + ml = find_program('ml64', required: false) else error('Unsupported cpu family: "' + cpu + '"') endif + if not ml.found() + error('MESON_SKIP_TEST: ML (masm) not found') + endif # Preprocess file (ml doesn't support pre-processing) preproc_name = lang + square_base + '.i' square_preproc = custom_target(lang + square_impl + 'preproc', diff --git a/test cases/common/124 cpp and asm/meson.build b/test cases/common/124 cpp and asm/meson.build index 9160775..f097084 100644 --- a/test cases/common/124 cpp and asm/meson.build +++ b/test cases/common/124 cpp and asm/meson.build @@ -15,7 +15,7 @@ endif sources = ['trivial.cc'] # If the compiler cannot compile assembly, don't use it -if meson.get_compiler('cpp').get_id() != 'msvc' +if not ['msvc', 'clang-cl'].contains(meson.get_compiler('cpp').get_id()) sources += ['retval-' + cpu + '.S'] cpp_args = ['-DUSE_ASM'] message('Using ASM') diff --git a/test cases/common/127 no buildincdir/meson.build b/test cases/common/127 no buildincdir/meson.build index ac69e8e..53f1a7f 100644 --- a/test cases/common/127 no buildincdir/meson.build +++ b/test cases/common/127 no buildincdir/meson.build @@ -1,5 +1,5 @@ project('nobuilddir', 'c', - default_options : 'werror=true') + default_options : ['werror=true', 'buildtype=plain']) cc = meson.get_compiler('c') diff --git a/test cases/common/13 pch/mixed/meson.build b/test cases/common/13 pch/mixed/meson.build index 7f6033d..f0c3eca 100644 --- a/test cases/common/13 pch/mixed/meson.build +++ b/test cases/common/13 pch/mixed/meson.build @@ -5,8 +5,9 @@ exe = executable( cpp_pch : ['pch/main_pch.cc', 'pch/main.h'], ) +# test pch when only a header is given (not supported by msvc) cc = meson.get_compiler('c') -if cc.get_id() != 'msvc' +if not ['msvc', 'clang-cl'].contains(cc.get_id()) exe2 = executable( 'prog2', files('main.cc', 'func.c'), diff --git a/test cases/common/132 generated assembly/meson.build b/test cases/common/132 generated assembly/meson.build index 6a8744b..5fb7429 100644 --- a/test cases/common/132 generated assembly/meson.build +++ b/test cases/common/132 generated assembly/meson.build @@ -2,8 +2,8 @@ project('generated assembly', 'c') cc = meson.get_compiler('c') -if cc.get_id() == 'msvc' - error('MESON_SKIP_TEST: assembly files cannot be compiled directly by MSVC') +if ['msvc', 'clang-cl'].contains(cc.get_id()) + error('MESON_SKIP_TEST: assembly files cannot be compiled directly by the compiler') endif cpu = host_machine.cpu_family() diff --git a/test cases/common/138 c cpp and asm/meson.build b/test cases/common/138 c cpp and asm/meson.build index 2c3610e..ca820e2 100644 --- a/test cases/common/138 c cpp and asm/meson.build +++ b/test cases/common/138 c cpp and asm/meson.build @@ -9,7 +9,7 @@ if not supported_cpus.contains(cpu) error('MESON_SKIP_TEST unsupported cpu:' + cpu) endif -if meson.get_compiler('c').get_id() == 'msvc' +if meson.get_compiler('c').get_argument_syntax() == 'msvc' error('MESON_SKIP_TEST MSVC can\'t compile assembly') endif diff --git a/test cases/common/143 C and CPP link/meson.build b/test cases/common/143 C and CPP link/meson.build index 55c1b87..af5c54a 100644 --- a/test cases/common/143 C and CPP link/meson.build +++ b/test cases/common/143 C and CPP link/meson.build @@ -25,9 +25,10 @@ libc = static_library('cfoo', ['foo.c', 'foo.h']) # ourselves at configure time and then 'find' it with cxx.find_library(). cxx = meson.get_compiler('cpp') -if cxx.get_id() == 'msvc' +if cxx.get_argument_syntax() == 'msvc' + static_linker = find_program('lib', 'llvm-lib') compile_cmd = ['/c', '@INPUT@', '/Fo@OUTPUT@'] - stlib_cmd = ['lib', '/OUT:@OUTPUT@', '@INPUT@'] + stlib_cmd = [static_linker, '/OUT:@OUTPUT@', '@INPUT@'] else compile_cmd = ['-c', '-fPIC', '@INPUT@', '-o', '@OUTPUT@'] stlib_cmd = ['ar', 'csr', '@OUTPUT@', '@INPUT@'] diff --git a/test cases/common/186 has link arg/meson.build b/test cases/common/186 has link arg/meson.build index e166101..10f2218 100644 --- a/test cases/common/186 has link arg/meson.build +++ b/test cases/common/186 has link arg/meson.build @@ -3,7 +3,7 @@ project('has link arg', 'c', 'cpp') cc = meson.get_compiler('c') cpp = meson.get_compiler('cpp') -if cc.get_id() == 'msvc' +if cc.get_argument_syntax() == 'msvc' is_arg = '/OPT:REF' useless = '/DEBUG' isnt_arg = '/iambroken' diff --git a/test cases/common/190 openmp/meson.build b/test cases/common/190 openmp/meson.build index eb270ab..018bf24 100644 --- a/test cases/common/190 openmp/meson.build +++ b/test cases/common/190 openmp/meson.build @@ -10,6 +10,9 @@ endif if cc.get_id() == 'msvc' and cc.version().version_compare('<17') error('MESON_SKIP_TEST msvc is too old to support OpenMP.') endif +if cc.get_id() == 'clang-cl' + error('MESON_SKIP_TEST clang-cl does not support OpenMP.') +endif if host_machine.system() == 'darwin' error('MESON_SKIP_TEST macOS does not support OpenMP.') endif diff --git a/test cases/common/204 function attributes/meson.build b/test cases/common/204 function attributes/meson.build index e46533f..c906b49 100644 --- a/test cases/common/204 function attributes/meson.build +++ b/test cases/common/204 function attributes/meson.build @@ -19,7 +19,7 @@ project('gcc func attributes', ['c', 'cpp']) c = meson.get_compiler('c') cpp = meson.get_compiler('cpp') -expected_result = c.get_id() != 'msvc' +expected_result = not ['msvc', 'clang-cl'].contains(c.get_id()) # Q: Why is ifunc not in this list or any of the below lists? # A: It's too damn hard to figure out if you actually support it, since it @@ -57,8 +57,6 @@ if c.get_id() != 'intel' attributes += 'weakref' endif -expected_result = c.get_id() != 'msvc' - # These are unsupported on darwin with apple clang 9.1.0 if host_machine.system() != 'darwin' attributes += 'alias' @@ -97,7 +95,7 @@ foreach a : ['dllexport', 'dllimport'] endforeach message('checking get_supported_function_attributes') -if c.get_id() != 'msvc' +if not ['msvc', 'clang-cl'].contains(c.get_id()) multi_expected = attributes else multi_expected = [] 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' diff --git a/test cases/common/91 default options/meson.build b/test cases/common/91 default options/meson.build index 9f45df0..c4c72ef 100644 --- a/test cases/common/91 default options/meson.build +++ b/test cases/common/91 default options/meson.build @@ -6,11 +6,9 @@ project('default options', 'cpp', 'c', default_options : [ 'warning_level=3', ]) -cpp_id = meson.get_compiler('cpp').get_id() - assert(get_option('buildtype') == 'debugoptimized', 'Build type default value wrong.') -if cpp_id == 'msvc' +if meson.get_compiler('cpp').get_argument_syntax() == 'msvc' cpp_eh = get_option('cpp_eh') assert(cpp_eh == 'none', 'MSVC eh value is "' + cpp_eh + '" instead of "none"') else @@ -33,4 +31,3 @@ assert(w_level == '3', 'warning level "' + w_level + '" instead of "3"') # assert(not cc.compiles('int foobar;'), 'Default arg not used in test.') # assert(cc.compiles('int foobar;', no_builtin_args : true), 'No_builtin did not disable builtins.') # endif - diff --git a/test cases/windows/16 gui app/meson.build b/test cases/windows/16 gui app/meson.build index 2435218..224d708 100644 --- a/test cases/windows/16 gui app/meson.build +++ b/test cases/windows/16 gui app/meson.build @@ -17,6 +17,10 @@ console_prog = executable('console_prog', 'console_prog.c', gui_app: false) tester = find_program('gui_app_tester.py') -tool = find_program('objdump', 'dumpbin') -test('is_gui', tester, args: [tool.path(), gui_prog, '2']) -test('not_gui', tester, args: [tool.path(), console_prog, '3']) +tool = find_program('objdump', 'dumpbin', required: false) +# TODO: when 'llvm-objdump -f' emits the subsystem type, we could use that also + +if tool.found() + test('is_gui', tester, args: [tool.path(), gui_prog, '2']) + test('not_gui', tester, args: [tool.path(), console_prog, '3']) +endif |