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.
pull/9344/head
Paolo Bonzini 3 years ago committed by Daniel Mensinger
parent 3f8c78b317
commit 7639b70796
  1. 23
      mesonbuild/cmake/toolchain.py
  2. 32
      unittests/linuxliketests.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()):

@ -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']")

Loading…
Cancel
Save