aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2018-11-04 19:56:08 +0200
committerGitHub <noreply@github.com>2018-11-04 19:56:08 +0200
commit1eb455f8696643b625b10a85551ff9fd28dd7d2a (patch)
treef6fa0bb549b609d3db1fea05181e7ff92c6b1fa3
parent253c581412d7f2b09af353dd83d943454bd555be (diff)
parentac6d4338cce68f5040825fb9bfb95dd147390e76 (diff)
downloadmeson-1eb455f8696643b625b10a85551ff9fd28dd7d2a.zip
meson-1eb455f8696643b625b10a85551ff9fd28dd7d2a.tar.gz
meson-1eb455f8696643b625b10a85551ff9fd28dd7d2a.tar.bz2
Merge pull request #4250 from jon-turney/windows-clang-cl
Add support for clang-cl on Windows
-rw-r--r--azure-pipelines.yml4
-rw-r--r--ci/azure-steps.yml23
-rw-r--r--mesonbuild/backend/backends.py4
-rw-r--r--mesonbuild/backend/ninjabackend.py19
-rw-r--r--mesonbuild/build.py2
-rw-r--r--mesonbuild/compilers/__init__.py4
-rw-r--r--mesonbuild/compilers/c.py33
-rw-r--r--mesonbuild/compilers/cpp.py23
-rw-r--r--mesonbuild/compilers/d.py2
-rw-r--r--mesonbuild/dependencies/boost.py4
-rw-r--r--mesonbuild/environment.py31
-rw-r--r--mesonbuild/interpreter.py30
-rw-r--r--mesonbuild/modules/windows.py2
-rwxr-xr-xrun_project_tests.py26
-rwxr-xr-xrun_unittests.py42
-rwxr-xr-xtest cases/common/100 manygen/subdir/manygen.py32
-rw-r--r--test cases/common/100 manygen/subdir/meson.build5
-rw-r--r--test cases/common/112 spaces backslash/meson.build2
-rw-r--r--test cases/common/123 llvm ir and assembly/meson.build11
-rw-r--r--test cases/common/124 cpp and asm/meson.build2
-rw-r--r--test cases/common/127 no buildincdir/meson.build2
-rw-r--r--test cases/common/13 pch/mixed/meson.build3
-rw-r--r--test cases/common/132 generated assembly/meson.build4
-rw-r--r--test cases/common/138 c cpp and asm/meson.build2
-rw-r--r--test cases/common/143 C and CPP link/meson.build5
-rw-r--r--test cases/common/186 has link arg/meson.build2
-rw-r--r--test cases/common/190 openmp/meson.build3
-rw-r--r--test cases/common/204 function attributes/meson.build6
-rw-r--r--test cases/common/206 argument syntax/meson.build2
-rw-r--r--test cases/common/91 default options/meson.build5
-rw-r--r--test cases/windows/16 gui app/meson.build10
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