aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/environment.py4
-rwxr-xr-xrun_unittests.py77
-rw-r--r--test cases/unit/5 compiler detection/compiler wrapper.py6
-rw-r--r--test cases/unit/5 compiler detection/meson.build8
-rw-r--r--test cases/unit/5 compiler detection/trivial.c6
-rw-r--r--test cases/unit/5 compiler detection/trivial.cc6
-rw-r--r--test cases/unit/5 compiler detection/trivial.m5
-rw-r--r--test cases/unit/5 compiler detection/trivial.mm9
8 files changed, 118 insertions, 3 deletions
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 405be0e..3021770 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -373,7 +373,7 @@ class Environment:
C, C++, ObjC, ObjC++, Fortran so consolidate it here.
'''
if self.is_cross_build() and want_cross:
- compilers = mesonlib.stringlistify(self.cross_info.config['binaries'][lang])
+ compilers = [mesonlib.stringlistify(self.cross_info.config['binaries'][lang])]
ccache = []
is_cross = True
if self.cross_info.need_exe_wrapper():
@@ -381,7 +381,7 @@ class Environment:
else:
exe_wrap = []
elif evar in os.environ:
- compilers = shlex.split(os.environ[evar])
+ compilers = [shlex.split(os.environ[evar])]
ccache = []
is_cross = False
exe_wrap = None
diff --git a/run_unittests.py b/run_unittests.py
index 16ff354..a17d6fe 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -24,7 +24,7 @@ from pathlib import PurePath
import mesonbuild.compilers
import mesonbuild.environment
import mesonbuild.mesonlib
-from mesonbuild.mesonlib import is_windows
+from mesonbuild.mesonlib import is_windows, is_osx
from mesonbuild.environment import detect_ninja, Environment
from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram
@@ -725,6 +725,81 @@ class AllPlatformTests(BasePlatformTests):
# target internal dependency include_directories: source dir
self.assertPathBasenameEqual(incs[7], 'sub1')
+ def test_compiler_detection(self):
+ '''
+ Test that automatic compiler detection and setting from the environment
+ both work just fine. This is needed because while running project tests
+ and other unit tests, we always read CC/CXX/etc from the environment.
+ '''
+ gnu = mesonbuild.compilers.GnuCompiler
+ clang = mesonbuild.compilers.ClangCompiler
+ intel = mesonbuild.compilers.IntelCompiler
+ msvc = mesonbuild.compilers.VisualStudioCCompiler
+ langs = (('c', 'CC'), ('cpp', 'CXX'), ('objc', 'OBJC'), ('objcpp', 'OBJCXX'))
+ testdir = os.path.join(self.unit_test_dir, '5 compiler detection')
+ env = Environment(testdir, self.builddir, self.meson_command,
+ get_fake_options(self.prefix), [])
+ for lang, evar in langs:
+ evalue = None
+ # Detect with evar and do sanity checks on that
+ if evar in os.environ:
+ ecc = getattr(env, 'detect_{}_compiler'.format(lang))(False)
+ # Pop it so we don't use it for the next detection
+ evalue = os.environ.pop(evar)
+ # Very rough/strict heuristics. Would never work for actual
+ # compiler detection, but should be ok for the tests.
+ if os.path.basename(evalue).startswith('g'):
+ self.assertIsInstance(ecc, gnu)
+ elif 'clang' in os.path.basename(evalue):
+ self.assertIsInstance(ecc, clang)
+ elif os.path.basename(evalue).startswith('ic'):
+ self.assertIsInstance(ecc, intel)
+ elif os.path.basename(evalue).startswith('cl'):
+ self.assertIsInstance(ecc, msvc)
+ else:
+ raise AssertionError('Unknown compiler {!r}'.format(evalue))
+ # Check that we actually used the evalue correctly as the compiler
+ self.assertEqual(ecc.get_exelist(), shlex.split(evalue))
+ # Do auto-detection of compiler based on platform, PATH, etc.
+ cc = getattr(env, 'detect_{}_compiler'.format(lang))(False)
+ # Check compiler type
+ if isinstance(cc, gnu):
+ if is_osx():
+ self.assertEqual(cc.gcc_type, mesonbuild.compilers.GCC_OSX)
+ elif is_windows():
+ self.assertEqual(cc.gcc_type, mesonbuild.compilers.GCC_MINGW)
+ else:
+ self.assertEqual(cc.gcc_type, mesonbuild.compilers.GCC_STANDARD)
+ if isinstance(cc, clang):
+ if is_osx():
+ self.assertEqual(cc.clang_type, mesonbuild.compilers.CLANG_OSX)
+ elif is_windows():
+ # Not implemented yet
+ self.assertEqual(cc.clang_type, mesonbuild.compilers.CLANG_WIN)
+ else:
+ self.assertEqual(cc.clang_type, mesonbuild.compilers.CLANG_STANDARD)
+ if isinstance(cc, intel):
+ if is_osx():
+ self.assertEqual(cc.icc_type, mesonbuild.compilers.ICC_OSX)
+ elif is_windows():
+ self.assertEqual(cc.icc_type, mesonbuild.compilers.ICC_WIN)
+ else:
+ self.assertEqual(cc.icc_type, mesonbuild.compilers.ICC_STANDARD)
+ # Set evar ourselves to a wrapper script that just calls the same
+ # exelist. This is meant to test that setting something like
+ # `ccache gcc` or `distcc ccache gcc` works fine.
+ wrapper = os.path.join(testdir, 'compiler wrapper.py')
+ wrapper = [sys.executable, wrapper] + cc.get_exelist()
+ wrapper_s = ''
+ for w in wrapper:
+ wrapper_s += shlex.quote(w) + ' '
+ os.environ[evar] = wrapper_s
+ wcc = getattr(env, 'detect_{}_compiler'.format(lang))(False)
+ # Must be the same type since it's a wrapper around the same exelist
+ self.assertIs(type(cc), type(wcc))
+ # Ensure that the exelist is correct
+ self.assertEqual(wcc.get_exelist(), wrapper)
+
class WindowsTests(BasePlatformTests):
'''
diff --git a/test cases/unit/5 compiler detection/compiler wrapper.py b/test cases/unit/5 compiler detection/compiler wrapper.py
new file mode 100644
index 0000000..fedd343
--- /dev/null
+++ b/test cases/unit/5 compiler detection/compiler wrapper.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python3
+
+import sys
+import subprocess
+
+sys.exit(subprocess.call(sys.argv[1:]))
diff --git a/test cases/unit/5 compiler detection/meson.build b/test cases/unit/5 compiler detection/meson.build
new file mode 100644
index 0000000..5491c64
--- /dev/null
+++ b/test cases/unit/5 compiler detection/meson.build
@@ -0,0 +1,8 @@
+project('trivial test',
+ ['c', 'cpp', 'objc', 'objcpp'],
+ meson_version : '>=0.27.0')
+
+executable('trivialc', 'trivial.c')
+executable('trivialcpp', 'trivial.cpp')
+executable('trivialobjc', 'trivial.m')
+executable('trivialobjcpp', 'trivial.mm')
diff --git a/test cases/unit/5 compiler detection/trivial.c b/test cases/unit/5 compiler detection/trivial.c
new file mode 100644
index 0000000..24ac454
--- /dev/null
+++ b/test cases/unit/5 compiler detection/trivial.c
@@ -0,0 +1,6 @@
+#include<stdio.h>
+
+int main(int argc, char **argv) {
+ printf("Trivial test is working.\n");
+ return 0;
+}
diff --git a/test cases/unit/5 compiler detection/trivial.cc b/test cases/unit/5 compiler detection/trivial.cc
new file mode 100644
index 0000000..8aa907b
--- /dev/null
+++ b/test cases/unit/5 compiler detection/trivial.cc
@@ -0,0 +1,6 @@
+#include<iostream>
+
+int main(int argc, char **argv) {
+ std::cout << "C++ seems to be working." << std::endl;
+ return 0;
+}
diff --git a/test cases/unit/5 compiler detection/trivial.m b/test cases/unit/5 compiler detection/trivial.m
new file mode 100644
index 0000000..f2e2315
--- /dev/null
+++ b/test cases/unit/5 compiler detection/trivial.m
@@ -0,0 +1,5 @@
+#import<stdio.h>
+
+int main(int argc, char **argv) {
+ return 0;
+} \ No newline at end of file
diff --git a/test cases/unit/5 compiler detection/trivial.mm b/test cases/unit/5 compiler detection/trivial.mm
new file mode 100644
index 0000000..927e810
--- /dev/null
+++ b/test cases/unit/5 compiler detection/trivial.mm
@@ -0,0 +1,9 @@
+#import<stdio.h>
+
+class MyClass {
+};
+
+int main(int argc, char **argv) {
+ return 0;
+}
+