diff options
-rw-r--r-- | mesonbuild/environment.py | 4 | ||||
-rwxr-xr-x | run_unittests.py | 77 | ||||
-rw-r--r-- | test cases/unit/5 compiler detection/compiler wrapper.py | 6 | ||||
-rw-r--r-- | test cases/unit/5 compiler detection/meson.build | 8 | ||||
-rw-r--r-- | test cases/unit/5 compiler detection/trivial.c | 6 | ||||
-rw-r--r-- | test cases/unit/5 compiler detection/trivial.cc | 6 | ||||
-rw-r--r-- | test cases/unit/5 compiler detection/trivial.m | 5 | ||||
-rw-r--r-- | test cases/unit/5 compiler detection/trivial.mm | 9 |
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; +} + |