aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2021-10-08 12:20:35 +0200
committerDaniel Mensinger <daniel@mensinger-ka.de>2021-10-08 20:09:43 +0200
commit7639b70796c7199120711afefb405bb31e110051 (patch)
tree85122df453974ab100ef931906674ca772c8c2a0
parent3f8c78b3172cfc78762cb0bf294c5aaafc18ca44 (diff)
downloadmeson-7639b70796c7199120711afefb405bb31e110051.zip
meson-7639b70796c7199120711afefb405bb31e110051.tar.gz
meson-7639b70796c7199120711afefb405bb31e110051.tar.bz2
cmake: handle arguments in the [binaries] section of the machine file
Sometimes, the machine file can include compiler command line options, in order to pick the correct multilib. For example, Meson uses "$cc --print-search-dirs" to find the library search path, where $cc is the cc from the machine file. Because the outputs of "gcc -m32 --print-search-dirs" and "gcc --print-search-dirs" are different, this only works if you have [binaries] cc = ['gcc', '-m32'] in the machine file. Right now, however, the cmake module assumes that the compiler listed in the machine file is either a compiler, or a "launcher" followed by the compiler. Check if the second argument starts with a slash (for Microsoft-like compilers) or a dash (for everyone else), and if so presume that the CMAKE_*_COMPILER_LAUNCHER need not be defined.
-rw-r--r--mesonbuild/cmake/toolchain.py23
-rw-r--r--unittests/linuxliketests.py32
2 files changed, 49 insertions, 6 deletions
diff --git a/mesonbuild/cmake/toolchain.py b/mesonbuild/cmake/toolchain.py
index 50ff10c..316f57c 100644
--- a/mesonbuild/cmake/toolchain.py
+++ b/mesonbuild/cmake/toolchain.py
@@ -16,6 +16,7 @@ from pathlib import Path
from .traceparser import CMakeTraceParser
from ..envconfig import CMakeSkipCompilerTest
from ..mesonlib import MachineChoice
+from ..compilers import VisualStudioLikeCompiler
from .common import language_map, cmake_get_generator_args
from .. import mlog
@@ -27,6 +28,7 @@ from textwrap import dedent
if T.TYPE_CHECKING:
from .executor import CMakeExecutor
from ..environment import Environment
+ from ..compilers import Compiler
class CMakeExecScope(Enum):
SUBPROJECT = 'subproject'
@@ -182,21 +184,30 @@ class CMakeToolchain:
# Set the compiler variables
for lang, comp_obj in self.compilers.items():
- exe_list = [make_abs(x) for x in comp_obj.get_exelist()]
prefix = 'CMAKE_{}_'.format(language_map.get(lang, lang.upper()))
+ exe_list = comp_obj.get_exelist()
if not exe_list:
continue
- elif len(exe_list) == 2:
- defaults[prefix + 'COMPILER'] = [exe_list[1]]
- defaults[prefix + 'COMPILER_LAUNCHER'] = [exe_list[0]]
- else:
- defaults[prefix + 'COMPILER'] = exe_list
+
+ if len(exe_list) >= 2 and not self.is_cmdline_option(comp_obj, exe_list[1]):
+ defaults[prefix + 'COMPILER_LAUNCHER'] = [make_abs(exe_list[0])]
+ exe_list = exe_list[1:]
+
+ exe_list[0] = make_abs(exe_list[0])
+ defaults[prefix + 'COMPILER'] = exe_list
if comp_obj.get_id() == 'clang-cl':
defaults['CMAKE_LINKER'] = comp_obj.get_linker_exelist()
return defaults
+ @staticmethod
+ def is_cmdline_option(compiler: 'Compiler', arg: str) -> bool:
+ if isinstance(compiler, VisualStudioLikeCompiler):
+ return arg.startswith('/')
+ else:
+ return arg.startswith('-')
+
def update_cmake_compiler_state(self) -> None:
# Check if all variables are already cached
if self.cmakestate.languages.issuperset(self.compilers.keys()):
diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py
index 991a0c2..81cca06 100644
--- a/unittests/linuxliketests.py
+++ b/unittests/linuxliketests.py
@@ -1697,3 +1697,35 @@ class LinuxlikeTests(BasePlatformTests):
obj_files = p.stdout.strip().split('\n')
self.assertEqual(len(obj_files), 1)
self.assertTrue(obj_files[0].endswith('-prelink.o'))
+
+ def do_one_test_with_nativefile(self, testdir, args):
+ testdir = os.path.join(self.common_test_dir, testdir)
+ with tempfile.TemporaryDirectory() as d:
+ p = Path(d) / 'nativefile'
+ with p.open('wt', encoding='utf-8') as f:
+ f.write(f'''[binaries]
+ c = {args}
+ ''')
+ self.init(testdir, extra_args=['--native-file=' + str(p)])
+ self.build()
+
+ def test_cmake_multilib(self):
+ '''
+ Test that the cmake module handles multilib paths correctly.
+ '''
+ # Verify that "gcc -m32" works
+ try:
+ self.do_one_test_with_nativefile('1 trivial', "['gcc', '-m32']")
+ except subprocess.CalledProcessError as e:
+ raise SkipTest('Not GCC, or GCC does not have the -m32 option')
+ self.wipe()
+
+ # Verify that cmake works
+ try:
+ self.do_one_test_with_nativefile('../cmake/1 basic', "['gcc']")
+ except subprocess.CalledProcessError as e:
+ raise SkipTest('Could not build basic cmake project')
+ self.wipe()
+
+ # If so, we can test that cmake works with "gcc -m32"
+ self.do_one_test_with_nativefile('../cmake/1 basic', "['gcc', '-m32']")