interpreter: detect and pass compiler to be used for linker tests

Allow using the links method to test that the C++ driver (e.g. g++) can be used to
link C objects.  One usecase is that the C compiler's libsanitizer might not be
compatible with the one included by the C++ driver.

This is theoretically backwards-incompatible, but it should be treated as a
bugfix in my opinion. There is no way in Meson to compile a .c file with the
C++ driver as part of a build target, therefore there would be no reason to
do something like meson.get_compiler(meson.get_compiler('cpp').links(files('main.c')).

Fixes: #7703
pull/9014/head
Paolo Bonzini 4 years ago
parent 90ee43463f
commit 8596b3bcd1
  1. 2
      mesonbuild/compilers/__init__.py
  2. 2
      mesonbuild/compilers/compilers.py
  3. 15
      mesonbuild/interpreter/compiler.py
  4. 4
      mesonbuild/mesonlib/universal.py

@ -34,6 +34,7 @@ __all__ = [
'is_known_suffix', 'is_known_suffix',
'lang_suffixes', 'lang_suffixes',
'sort_clink', 'sort_clink',
'SUFFIX_TO_LANG',
'compiler_from_language', 'compiler_from_language',
'detect_compiler_for', 'detect_compiler_for',
@ -148,6 +149,7 @@ from .compilers import (
lang_suffixes, lang_suffixes,
LANGUAGES_USING_LDFLAGS, LANGUAGES_USING_LDFLAGS,
sort_clink, sort_clink,
SUFFIX_TO_LANG,
) )
from .detect import ( from .detect import (
compiler_from_language, compiler_from_language,

@ -84,6 +84,8 @@ for _l in clink_langs + ('vala',):
clink_suffixes += lang_suffixes[_l] clink_suffixes += lang_suffixes[_l]
clink_suffixes += ('h', 'll', 's') clink_suffixes += ('h', 'll', 's')
all_suffixes = set(itertools.chain(*lang_suffixes.values(), clink_suffixes)) # type: T.Set[str] all_suffixes = set(itertools.chain(*lang_suffixes.values(), clink_suffixes)) # type: T.Set[str]
SUFFIX_TO_LANG = dict(itertools.chain(*(
[(suffix, lang) for suffix in v] for lang, v in lang_suffixes.items()))) # type: T.Dict[str, str]
# Languages that should use LDFLAGS arguments when linking. # Languages that should use LDFLAGS arguments when linking.
LANGUAGES_USING_LDFLAGS = {'objcpp', 'cpp', 'objc', 'c', 'fortran', 'd', 'cuda'} # type: T.Set[str] LANGUAGES_USING_LDFLAGS = {'objcpp', 'cpp', 'objc', 'c', 'fortran', 'd', 'cuda'} # type: T.Set[str]

@ -11,6 +11,7 @@ from .. import coredata
from .. import dependencies from .. import dependencies
from .. import mesonlib from .. import mesonlib
from .. import mlog from .. import mlog
from ..compilers import SUFFIX_TO_LANG
from ..compilers.compilers import CompileCheckMode from ..compilers.compilers import CompileCheckMode
from ..interpreterbase import (ObjectHolder, noPosargs, noKwargs, from ..interpreterbase import (ObjectHolder, noPosargs, noKwargs,
FeatureNew, disablerIfNotFound, FeatureNew, disablerIfNotFound,
@ -454,13 +455,27 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_kwargs('compiler.links', *_COMPILES_KWS) @typed_kwargs('compiler.links', *_COMPILES_KWS)
def links_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool: def links_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool:
code = args[0] code = args[0]
compiler = None
if isinstance(code, mesonlib.File): if isinstance(code, mesonlib.File):
code = mesonlib.File.from_absolute_file( code = mesonlib.File.from_absolute_file(
code.rel_to_builddir(self.environment.source_dir)) code.rel_to_builddir(self.environment.source_dir))
suffix = code.suffix
if suffix not in self.compiler.file_suffixes:
for_machine = self.compiler.for_machine
clist = self.interpreter.coredata.compilers[for_machine]
if suffix not in SUFFIX_TO_LANG:
# just pass it to the compiler driver
mlog.warning(f'Unknown suffix for test file {code}')
elif SUFFIX_TO_LANG[suffix] not in clist:
mlog.warning(f'Passed {SUFFIX_TO_LANG[suffix]} source to links method, not specified for {for_machine.get_lower_case_name()} machine.')
else:
compiler = clist[SUFFIX_TO_LANG[suffix]]
testname = kwargs['name'] testname = kwargs['name']
extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
deps, msg = self._determine_dependencies(kwargs['dependencies']) deps, msg = self._determine_dependencies(kwargs['dependencies'])
result, cached = self.compiler.links(code, self.environment, result, cached = self.compiler.links(code, self.environment,
compiler=compiler,
extra_args=extra_args, extra_args=extra_args,
dependencies=deps) dependencies=deps)
cached_msg = mlog.blue('(cached)') if cached else '' cached_msg = mlog.blue('(cached)') if cached else ''

@ -421,6 +421,10 @@ class File(HoldableObject):
absdir = builddir absdir = builddir
return os.path.join(absdir, self.relative_name()) return os.path.join(absdir, self.relative_name())
@property
def suffix(self) -> str:
return os.path.splitext(self.fname)[1][1:].lower()
def endswith(self, ending: str) -> bool: def endswith(self, ending: str) -> bool:
return self.fname.endswith(ending) return self.fname.endswith(ending)

Loading…
Cancel
Save