Split compiler detection from Environment

This moves all the compiler detection logic into the new
compilers.detect module. This dramatically reduces the size
and complexity of Environment.
pull/8933/head
Daniel Mensinger 4 years ago
parent 0f237b8d1d
commit 3f889606c7
  1. 3
      mesonbuild/ast/introspection.py
  2. 4
      mesonbuild/backend/backends.py
  3. 4
      mesonbuild/build.py
  4. 33
      mesonbuild/compilers/__init__.py
  5. 1209
      mesonbuild/compilers/detect.py
  6. 5
      mesonbuild/compilers/mixins/intel.py
  7. 4
      mesonbuild/dependencies/dev.py
  8. 1368
      mesonbuild/environment.py
  9. 2
      mesonbuild/interpreter/interpreter.py
  10. 11
      mesonbuild/linkers/__init__.py
  11. 216
      mesonbuild/linkers/detect.py
  12. 44
      mesonbuild/mesonlib/universal.py
  13. 9
      run_project_tests.py
  14. 156
      run_unittests.py

@ -23,6 +23,7 @@ from ..mesonlib import MachineChoice, OptionKey
from ..interpreterbase import InvalidArguments, TYPE_nvar
from ..build import BuildTarget, Executable, Jar, SharedLibrary, SharedModule, StaticLibrary
from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, StringNode
from ..compilers import detect_compiler_for
import typing as T
import os
import argparse
@ -162,7 +163,7 @@ class IntrospectionInterpreter(AstInterpreter):
for lang in sorted(langs, key=compilers.sort_clink):
lang = lang.lower()
if lang not in self.coredata.compilers[for_machine]:
self.environment.detect_compiler_for(lang, for_machine)
detect_compiler_for(self.environment, lang, for_machine)
def func_dependency(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None:
args = self.flatten_args(args)

@ -29,7 +29,7 @@ from .. import dependencies
from .. import programs
from .. import mesonlib
from .. import mlog
from ..compilers import LANGUAGES_USING_LDFLAGS
from ..compilers import LANGUAGES_USING_LDFLAGS, detect
from ..mesonlib import (
File, MachineChoice, MesonException, OptionType, OrderedSet, OptionOverrideProxy,
classify_unity_sources, OptionKey, join_args
@ -1315,7 +1315,7 @@ class Backend:
mlog.warning('Cross file does not specify strip binary, result will not be stripped.')
else:
# TODO go through all candidates, like others
strip_bin = [self.environment.default_strip[0]]
strip_bin = [detect.defaults['strip'][0]]
d = InstallData(self.environment.get_source_dir(),
self.environment.get_build_dir(),
self.environment.get_prefix(),

@ -37,7 +37,7 @@ from .mesonlib import (
)
from .compilers import (
Compiler, is_object, clink_langs, sort_clink, lang_suffixes,
is_known_suffix
is_known_suffix, detect_static_linker
)
from .linkers import StaticLinker
from .interpreterbase import FeatureNew
@ -275,7 +275,7 @@ class Build:
def ensure_static_linker(self, compiler):
if self.static_linker[compiler.for_machine] is None and compiler.needs_static_linker():
self.static_linker[compiler.for_machine] = self.environment.detect_static_linker(compiler)
self.static_linker[compiler.for_machine] = detect_static_linker(self.environment, compiler)
def get_project(self):
return self.projects['']

@ -35,6 +35,22 @@ __all__ = [
'lang_suffixes',
'sort_clink',
'compiler_from_language',
'detect_compiler_for',
'detect_static_linker',
'detect_c_compiler',
'detect_cpp_compiler',
'detect_cuda_compiler',
'detect_fortran_compiler',
'detect_objc_compiler',
'detect_objcpp_compiler',
'detect_java_compiler',
'detect_cs_compiler',
'detect_vala_compiler',
'detect_rust_compiler',
'detect_d_compiler',
'detect_swift_compiler',
'AppleClangCCompiler',
'AppleClangCPPCompiler',
'AppleClangObjCCompiler',
@ -133,6 +149,23 @@ from .compilers import (
LANGUAGES_USING_LDFLAGS,
sort_clink,
)
from .detect import (
compiler_from_language,
detect_compiler_for,
detect_static_linker,
detect_c_compiler,
detect_cpp_compiler,
detect_cuda_compiler,
detect_objc_compiler,
detect_objcpp_compiler,
detect_fortran_compiler,
detect_java_compiler,
detect_cs_compiler,
detect_vala_compiler,
detect_rust_compiler,
detect_d_compiler,
detect_swift_compiler,
)
from .c import (
CCompiler,
AppleClangCCompiler,

File diff suppressed because it is too large Load Diff

@ -168,14 +168,11 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
return args
def get_toolset_version(self) -> T.Optional[str]:
# Avoid circular dependencies....
from ...environment import search_version
# ICL provides a cl.exe that returns the version of MSVC it tries to
# emulate, so we'll get the version from that and pass it to the same
# function the real MSVC uses to calculate the toolset version.
_, _, err = mesonlib.Popen_safe(['cl.exe'])
v1, v2, *_ = search_version(err).split('.')
v1, v2, *_ = mesonlib.search_version(err).split('.')
version = int(v1 + v2)
return self._calculate_toolset_version(version)

@ -23,7 +23,7 @@ import shutil
import typing as T
from .. import mesonlib, mlog
from ..compilers import AppleClangCCompiler, AppleClangCPPCompiler
from ..compilers import AppleClangCCompiler, AppleClangCPPCompiler, detect_compiler_for
from ..environment import get_llvm_tool_names
from ..mesonlib import version_compare, stringlistify, extract_as_list, MachineChoice
from .base import DependencyException, DependencyMethods, strip_system_libdirs, SystemDependency
@ -520,7 +520,7 @@ class JDKSystemDependency(SystemDependency):
m = self.env.machines[self.for_machine]
if 'java' not in environment.coredata.compilers[self.for_machine]:
environment.detect_compiler_for('java', self.for_machine)
detect_compiler_for(environment, 'java', self.for_machine)
self.javac = environment.coredata.compilers[self.for_machine]['java']
self.version = self.javac.version

File diff suppressed because it is too large Load Diff

@ -1328,7 +1328,7 @@ external dependencies (including libraries) must go to "dependencies".''')
comp = clist[lang]
else:
try:
comp = self.environment.detect_compiler_for(lang, for_machine)
comp = compilers.detect_compiler_for(self.environment, lang, for_machine)
if comp is None:
raise InvalidArguments('Tried to use unknown language "%s".' % lang)
if self.should_skip_sanity_check(for_machine):

@ -12,6 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from .detect import (
defaults,
guess_win_linker,
guess_nix_linker,
)
from .linkers import (
RSPFileSyntax,
@ -64,6 +69,12 @@ from .linkers import (
)
__all__ = [
# detect.py
'defaults',
'guess_win_linker',
'guess_nix_linker',
# linkers.py
'RSPFileSyntax',
'StaticLinker',

@ -0,0 +1,216 @@
# Copyright 2012-2021 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from ..mesonlib import (
EnvironmentException, MachineChoice, OptionKey,
Popen_safe, search_version
)
from .linkers import (
DynamicLinker,
AppleDynamicLinker,
GnuDynamicLinker,
GnuGoldDynamicLinker,
GnuBFDDynamicLinker,
LLVMDynamicLinker,
QualcommLLVMDynamicLinker,
MSVCDynamicLinker,
ClangClDynamicLinker,
SolarisDynamicLinker,
AIXDynamicLinker,
OptlinkDynamicLinker,
)
import re
import shlex
import typing as T
if T.TYPE_CHECKING:
from ..environment import Environment
from ..compilers import Compiler
defaults: T.Dict[str, T.List[str]] = {}
defaults['static_linker'] = ['ar', 'gar']
defaults['vs_static_linker'] = ['lib']
defaults['clang_cl_static_linker'] = ['llvm-lib']
defaults['cuda_static_linker'] = ['nvlink']
defaults['gcc_static_linker'] = ['gcc-ar']
defaults['clang_static_linker'] = ['llvm-ar']
def __failed_to_detect_linker(compiler: T.List[str], args: T.List[str], stdout: str, stderr: str) -> 'T.NoReturn':
msg = 'Unable to detect linker for compiler "{} {}"\nstdout: {}\nstderr: {}'.format(
' '.join(compiler), ' '.join(args), stdout, stderr)
raise EnvironmentException(msg)
def guess_win_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Type['Compiler'],
for_machine: MachineChoice, *,
use_linker_prefix: bool = True, invoked_directly: bool = True,
extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker':
env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env)
# Explicitly pass logo here so that we can get the version of link.exe
if not use_linker_prefix or comp_class.LINKER_PREFIX is None:
check_args = ['/logo', '--version']
elif isinstance(comp_class.LINKER_PREFIX, str):
check_args = [comp_class.LINKER_PREFIX + '/logo', comp_class.LINKER_PREFIX + '--version']
elif isinstance(comp_class.LINKER_PREFIX, list):
check_args = comp_class.LINKER_PREFIX + ['/logo'] + comp_class.LINKER_PREFIX + ['--version']
check_args += env.coredata.options[OptionKey('args', lang=comp_class.language, machine=for_machine)].value
override = [] # type: T.List[str]
value = env.lookup_binary_entry(for_machine, comp_class.language + '_ld')
if value is not None:
override = comp_class.use_linker_args(value[0])
check_args += override
if extra_args is not None:
check_args.extend(extra_args)
p, o, _ = Popen_safe(compiler + check_args)
if o.startswith('LLD'):
if '(compatible with GNU linkers)' in o:
return LLVMDynamicLinker(
compiler, for_machine, comp_class.LINKER_PREFIX,
override, version=search_version(o))
elif not invoked_directly:
return ClangClDynamicLinker(
for_machine, override, exelist=compiler, prefix=comp_class.LINKER_PREFIX,
version=search_version(o), direct=False, machine=None)
if value is not None and invoked_directly:
compiler = value
# We've already hanedled the non-direct case above
p, o, e = Popen_safe(compiler + check_args)
if o.startswith('LLD'):
return ClangClDynamicLinker(
for_machine, [],
prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
exelist=compiler, version=search_version(o), direct=invoked_directly)
elif 'OPTLINK' in o:
# Opltink's stdout *may* beging with a \r character.
return OptlinkDynamicLinker(compiler, for_machine, version=search_version(o))
elif o.startswith('Microsoft') or e.startswith('Microsoft'):
out = o or e
match = re.search(r'.*(X86|X64|ARM|ARM64).*', out)
if match:
target = str(match.group(1))
else:
target = 'x86'
return MSVCDynamicLinker(
for_machine, [], machine=target, exelist=compiler,
prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
version=search_version(out), direct=invoked_directly)
elif 'GNU coreutils' in o:
raise EnvironmentException(
"Found GNU link.exe instead of MSVC link.exe. This link.exe "
"is not a linker. You may need to reorder entries to your "
"%PATH% variable to resolve this.")
__failed_to_detect_linker(compiler, check_args, o, e)
def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Type['Compiler'],
for_machine: MachineChoice, *,
extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker':
"""Helper for guessing what linker to use on Unix-Like OSes.
:compiler: Invocation to use to get linker
:comp_class: The Compiler Type (uninstantiated)
:for_machine: which machine this linker targets
:extra_args: Any additional arguments required (such as a source file)
"""
env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env)
extra_args = extra_args or []
extra_args += env.coredata.options[OptionKey('args', lang=comp_class.language, machine=for_machine)].value
if isinstance(comp_class.LINKER_PREFIX, str):
check_args = [comp_class.LINKER_PREFIX + '--version'] + extra_args
else:
check_args = comp_class.LINKER_PREFIX + ['--version'] + extra_args
override = [] # type: T.List[str]
value = env.lookup_binary_entry(for_machine, comp_class.language + '_ld')
if value is not None:
override = comp_class.use_linker_args(value[0])
check_args += override
_, o, e = Popen_safe(compiler + check_args)
v = search_version(o + e)
linker: DynamicLinker
if o.startswith('LLD'):
linker = LLVMDynamicLinker(
compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
elif 'Snapdragon' in e and 'LLVM' in e:
linker = QualcommLLVMDynamicLinker(
compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
elif e.startswith('lld-link: '):
# The LLD MinGW frontend didn't respond to --version before version 9.0.0,
# and produced an error message about failing to link (when no object
# files were specified), instead of printing the version number.
# Let's try to extract the linker invocation command to grab the version.
_, o, e = Popen_safe(compiler + check_args + ['-v'])
try:
linker_cmd = re.match(r'.*\n(.*?)\nlld-link: ', e, re.DOTALL).group(1)
linker_cmd = shlex.split(linker_cmd)[0]
except (AttributeError, IndexError, ValueError):
pass
else:
_, o, e = Popen_safe([linker_cmd, '--version'])
v = search_version(o)
linker = LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
# first is for apple clang, second is for real gcc, the third is icc
elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e or 'ld: unknown option:' in e:
if isinstance(comp_class.LINKER_PREFIX, str):
_, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args)
else:
_, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-v'] + extra_args)
for line in e.split('\n'):
if 'PROJECT:ld' in line:
v = line.split('-')[1]
break
else:
v = 'unknown version'
linker = AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
elif 'GNU' in o or 'GNU' in e:
cls: T.Type[GnuDynamicLinker]
if 'gold' in o or 'gold' in e:
cls = GnuGoldDynamicLinker
else:
cls = GnuBFDDynamicLinker
linker = cls(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
elif 'Solaris' in e or 'Solaris' in o:
for line in (o+e).split('\n'):
if 'ld: Software Generation Utilities' in line:
v = line.split(':')[2].lstrip()
break
else:
v = 'unknown version'
linker = SolarisDynamicLinker(
compiler, for_machine, comp_class.LINKER_PREFIX, override,
version=v)
elif 'ld: 0706-012 The -- flag is not recognized' in e:
if isinstance(comp_class.LINKER_PREFIX, str):
_, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-V'] + extra_args)
else:
_, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-V'] + extra_args)
linker = AIXDynamicLinker(
compiler, for_machine, comp_class.LINKER_PREFIX, override,
version=search_version(e))
else:
__failed_to_detect_linker(compiler, check_args, o, e)
return linker

@ -135,6 +135,7 @@ __all__ = [
'version_compare',
'version_compare_condition_with_min',
'version_compare_many',
'search_version',
'windows_proof_rm',
'windows_proof_rmtree',
]
@ -883,6 +884,49 @@ def version_compare_condition_with_min(condition: str, minimum: str) -> bool:
return T.cast(bool, cmpop(Version(minimum), Version(condition)))
def search_version(text: str) -> str:
# Usually of the type 4.1.4 but compiler output may contain
# stuff like this:
# (Sourcery CodeBench Lite 2014.05-29) 4.8.3 20140320 (prerelease)
# Limiting major version number to two digits seems to work
# thus far. When we get to GCC 100, this will break, but
# if we are still relevant when that happens, it can be
# considered an achievement in itself.
#
# This regex is reaching magic levels. If it ever needs
# to be updated, do not complexify but convert to something
# saner instead.
# We'll demystify it a bit with a verbose definition.
version_regex = re.compile(r"""
(?<! # Zero-width negative lookbehind assertion
(
\d # One digit
| \. # Or one period
) # One occurrence
)
# Following pattern must not follow a digit or period
(
\d{1,2} # One or two digits
(
\.\d+ # Period and one or more digits
)+ # One or more occurrences
(
-[a-zA-Z0-9]+ # Hyphen and one or more alphanumeric
)? # Zero or one occurrence
) # One occurrence
""", re.VERBOSE)
match = version_regex.search(text)
if match:
return match.group(0)
# try a simpler regex that has like "blah 2020.01.100 foo" or "blah 2020.01 foo"
version_regex = re.compile(r"(\d{1,4}\.\d{1,4}\.?\d{0,4})")
match = version_regex.search(text)
if match:
return match.group(0)
return 'unknown version'
def default_libdir() -> str:
if is_debianlike():

@ -42,6 +42,7 @@ from mesonbuild import compilers
from mesonbuild import mesonlib
from mesonbuild import mlog
from mesonbuild import mtest
from mesonbuild.compilers import compiler_from_language, detect_objc_compiler, detect_objcpp_compiler
from mesonbuild.build import ConfigurationData
from mesonbuild.mesonlib import MachineChoice, Popen_safe, TemporaryDirectoryWinProof
from mesonbuild.mlog import blue, bold, cyan, green, red, yellow, normal_green
@ -884,7 +885,7 @@ def have_objc_compiler(use_tmp: bool) -> bool:
with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmp else '.') as build_dir:
env = environment.Environment(None, build_dir, get_fake_options('/'))
try:
objc_comp = env.detect_objc_compiler(MachineChoice.HOST)
objc_comp = detect_objc_compiler(env, MachineChoice.HOST)
except mesonlib.MesonException:
return False
if not objc_comp:
@ -900,7 +901,7 @@ def have_objcpp_compiler(use_tmp: bool) -> bool:
with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmp else '.') as build_dir:
env = environment.Environment(None, build_dir, get_fake_options('/'))
try:
objcpp_comp = env.detect_objcpp_compiler(MachineChoice.HOST)
objcpp_comp = detect_objcpp_compiler(env, MachineChoice.HOST)
except mesonlib.MesonException:
return False
if not objcpp_comp:
@ -1392,7 +1393,7 @@ def detect_system_compiler(options: 'CompilerArgumentType') -> None:
for lang in sorted(compilers.all_languages):
try:
comp = env.compiler_from_language(lang, MachineChoice.HOST)
comp = compiler_from_language(env, lang, MachineChoice.HOST)
# note compiler id for later use with test.json matrix
compiler_id_map[lang] = comp.get_id()
except mesonlib.MesonException:
@ -1412,7 +1413,7 @@ def print_compilers(env: 'Environment', machine: MachineChoice) -> None:
print()
for lang in sorted(compilers.all_languages):
try:
comp = env.compiler_from_language(lang, machine)
comp = compiler_from_language(env, lang, machine)
details = '{:<10} {} {}'.format('[' + comp.get_id() + ']', ' '.join(comp.get_exelist()), comp.get_version_string())
except mesonlib.MesonException:
details = '[not found]'

@ -59,7 +59,13 @@ from mesonbuild.mesonlib import (
BuildDirLock, LibType, MachineChoice, PerMachine, Version, is_windows,
is_osx, is_cygwin, is_dragonflybsd, is_openbsd, is_haiku, is_sunos,
windows_proof_rmtree, windows_proof_rm, python_command,
version_compare, split_args, quote_arg, relpath, is_linux, git
version_compare, split_args, quote_arg, relpath, is_linux, git,
search_version
)
from mesonbuild.compilers import (
detect_static_linker, detect_c_compiler, detect_cpp_compiler,
detect_objc_compiler, detect_objcpp_compiler, detect_d_compiler,
detect_swift_compiler, compiler_from_language
)
from mesonbuild.environment import detect_ninja
from mesonbuild.mesonlib import MesonException, EnvironmentException, OptionKey
@ -140,7 +146,7 @@ def _git_init(project_dir):
# If a user has git configuration init.defaultBranch set we want to override that
with tempfile.TemporaryDirectory() as d:
out = git(['--version'], str(d))[1]
if version_compare(mesonbuild.environment.search_version(out), '>= 2.28'):
if version_compare(search_version(out), '>= 2.28'):
extra_cmd = ['--initial-branch', 'master']
else:
extra_cmd = []
@ -226,14 +232,12 @@ def skip_if_no_cmake(f):
return f(*args, **kwargs)
return wrapped
def skip_if_not_language(lang):
def skip_if_not_language(lang: str):
def wrapper(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
try:
env = get_fake_env()
f = getattr(env, f'detect_{lang}_compiler')
f(MachineChoice.HOST)
compiler_from_language(get_fake_env(), lang, MachineChoice.HOST)
except EnvironmentException:
raise unittest.SkipTest(f'No {lang} compiler found.')
return func(*args, **kwargs)
@ -269,7 +273,7 @@ def skip_if_not_base_option(feature):
@functools.wraps(f)
def wrapped(*args, **kwargs):
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
key = OptionKey(feature)
if key not in cc.base_options:
raise unittest.SkipTest(
@ -327,18 +331,17 @@ def no_pkgconfig():
class InternalTests(unittest.TestCase):
def test_version_number(self):
searchfunc = mesonbuild.environment.search_version
self.assertEqual(searchfunc('foobar 1.2.3'), '1.2.3')
self.assertEqual(searchfunc('1.2.3'), '1.2.3')
self.assertEqual(searchfunc('foobar 2016.10.28 1.2.3'), '1.2.3')
self.assertEqual(searchfunc('2016.10.28 1.2.3'), '1.2.3')
self.assertEqual(searchfunc('foobar 2016.10.128'), '2016.10.128')
self.assertEqual(searchfunc('2016.10.128'), '2016.10.128')
self.assertEqual(searchfunc('2016.10'), '2016.10')
self.assertEqual(searchfunc('2016.10 1.2.3'), '1.2.3')
self.assertEqual(searchfunc('oops v1.2.3'), '1.2.3')
self.assertEqual(searchfunc('2016.oops 1.2.3'), '1.2.3')
self.assertEqual(searchfunc('2016.x'), 'unknown version')
self.assertEqual(search_version('foobar 1.2.3'), '1.2.3')
self.assertEqual(search_version('1.2.3'), '1.2.3')
self.assertEqual(search_version('foobar 2016.10.28 1.2.3'), '1.2.3')
self.assertEqual(search_version('2016.10.28 1.2.3'), '1.2.3')
self.assertEqual(search_version('foobar 2016.10.128'), '2016.10.128')
self.assertEqual(search_version('2016.10.128'), '2016.10.128')
self.assertEqual(search_version('2016.10'), '2016.10')
self.assertEqual(search_version('2016.10 1.2.3'), '1.2.3')
self.assertEqual(search_version('oops v1.2.3'), '1.2.3')
self.assertEqual(search_version('2016.oops 1.2.3'), '1.2.3')
self.assertEqual(search_version('2016.x'), 'unknown version')
def test_mode_symbolic_to_bits(self):
modefunc = mesonbuild.mesonlib.FileMode.perms_s_to_bits
@ -837,7 +840,7 @@ class InternalTests(unittest.TestCase):
'{}.dll.a', '{}.lib', '{}.dll'),
'static': msvc_static}}
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if is_osx():
self._test_all_naming(cc, env, patterns, 'darwin')
elif is_cygwin():
@ -881,7 +884,7 @@ class InternalTests(unittest.TestCase):
with tempfile.TemporaryDirectory() as tmpdir:
pkgbin = ExternalProgram('pkg-config', command=['pkg-config'], silent=True)
env = get_fake_env()
compiler = env.detect_c_compiler(MachineChoice.HOST)
compiler = detect_c_compiler(env, MachineChoice.HOST)
env.coredata.compilers.host = {'c': compiler}
env.coredata.options[OptionKey('link_args', lang='c')] = FakeCompilerOptions()
p1 = Path(tmpdir) / '1'
@ -1063,7 +1066,7 @@ class InternalTests(unittest.TestCase):
Ensure that the toolset version returns the correct value for this MSVC
'''
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_argument_syntax() != 'msvc':
raise unittest.SkipTest('Test only applies to MSVC-like compilers')
toolset_ver = cc.get_toolset_version()
@ -1752,8 +1755,8 @@ class DataTests(unittest.TestCase):
self.assertIsNotNone(md)
env = get_fake_env()
# FIXME: Support other compilers
cc = env.detect_c_compiler(MachineChoice.HOST)
cpp = env.detect_cpp_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
cpp = detect_cpp_compiler(env, MachineChoice.HOST)
for comp in (cc, cpp):
for opt in comp.get_options():
self.assertIn(str(opt), md)
@ -2556,7 +2559,7 @@ class AllPlatformTests(BasePlatformTests):
def test_clike_get_library_dirs(self):
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
for d in cc.get_library_dirs(env):
self.assertTrue(os.path.exists(d))
self.assertTrue(os.path.isdir(d))
@ -2572,8 +2575,8 @@ class AllPlatformTests(BasePlatformTests):
'''
testdir = os.path.join(self.common_test_dir, '3 static')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
static_linker = env.detect_static_linker(cc)
cc = detect_c_compiler(env, MachineChoice.HOST)
static_linker = detect_static_linker(env, cc)
if is_windows():
raise unittest.SkipTest('https://github.com/mesonbuild/meson/issues/1526')
if not isinstance(static_linker, mesonbuild.linkers.ArLinker):
@ -3041,9 +3044,9 @@ class AllPlatformTests(BasePlatformTests):
for lang, evar in langs:
# Detect with evar and do sanity checks on that
if evar in os.environ:
ecc = getattr(env, f'detect_{lang}_compiler')(MachineChoice.HOST)
ecc = compiler_from_language(env, lang, MachineChoice.HOST)
self.assertTrue(ecc.version)
elinker = env.detect_static_linker(ecc)
elinker = detect_static_linker(env, ecc)
# 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
@ -3069,9 +3072,9 @@ class AllPlatformTests(BasePlatformTests):
# Check that we actually used the evalue correctly as the compiler
self.assertEqual(ecc.get_exelist(), split_args(evalue))
# Do auto-detection of compiler based on platform, PATH, etc.
cc = getattr(env, f'detect_{lang}_compiler')(MachineChoice.HOST)
cc = compiler_from_language(env, lang, MachineChoice.HOST)
self.assertTrue(cc.version)
linker = env.detect_static_linker(cc)
linker = detect_static_linker(env, cc)
# Check compiler type
if isinstance(cc, gnu):
self.assertIsInstance(linker, ar)
@ -3129,8 +3132,8 @@ class AllPlatformTests(BasePlatformTests):
# Need a new env to re-run environment loading
env = get_fake_env(testdir, self.builddir, self.prefix)
wcc = getattr(env, f'detect_{lang}_compiler')(MachineChoice.HOST)
wlinker = env.detect_static_linker(wcc)
wcc = compiler_from_language(env, lang, MachineChoice.HOST)
wlinker = detect_static_linker(env, wcc)
# Pop it so we don't use it for the next detection
evalue = os.environ.pop('AR')
# Must be the same type since it's a wrapper around the same exelist
@ -3148,7 +3151,7 @@ class AllPlatformTests(BasePlatformTests):
testdir = os.path.join(self.common_test_dir, '133 c cpp and asm')
# Skip if building with MSVC
env = get_fake_env(testdir, self.builddir, self.prefix)
if env.detect_c_compiler(MachineChoice.HOST).get_id() == 'msvc':
if detect_c_compiler(env, MachineChoice.HOST).get_id() == 'msvc':
raise unittest.SkipTest('MSVC can\'t compile assembly')
self.init(testdir)
commands = {'c-asm': {}, 'cpp-asm': {}, 'cpp-c-asm': {}, 'c-cpp-asm': {}}
@ -3309,7 +3312,7 @@ class AllPlatformTests(BasePlatformTests):
testdir = os.path.join(self.common_test_dir, '5 linkstatic')
env = get_fake_env(testdir, self.builddir, self.prefix)
if env.detect_c_compiler(MachineChoice.HOST).get_id() == 'clang' and is_windows():
if detect_c_compiler(env, MachineChoice.HOST).get_id() == 'clang' and is_windows():
raise unittest.SkipTest('LTO not (yet) supported by windows clang')
self.init(testdir, extra_args='-Db_lto=true')
@ -3321,7 +3324,7 @@ class AllPlatformTests(BasePlatformTests):
testdir = os.path.join(self.common_test_dir, '6 linkshared')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
extra_args: T.List[str] = []
if cc.get_id() == 'clang':
if is_windows():
@ -3347,7 +3350,7 @@ class AllPlatformTests(BasePlatformTests):
testdir = os.path.join(self.common_test_dir, '6 linkshared')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_id() != 'clang':
raise unittest.SkipTest('Only clang currently supports thinLTO')
if cc.linker.id not in {'ld.lld', 'ld.gold', 'ld64', 'lld-link'}:
@ -3615,8 +3618,8 @@ class AllPlatformTests(BasePlatformTests):
def detect_prebuild_env(self):
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
stlinker = env.detect_static_linker(cc)
cc = detect_c_compiler(env, MachineChoice.HOST)
stlinker = detect_static_linker(env, cc)
if mesonbuild.mesonlib.is_windows():
object_suffix = 'obj'
shared_suffix = 'dll'
@ -4060,7 +4063,7 @@ class AllPlatformTests(BasePlatformTests):
env = get_fake_env()
for l in ['cpp', 'cs', 'd', 'java', 'cuda', 'fortran', 'objc', 'objcpp', 'rust']:
try:
comp = env.detect_compiler_for(l, MachineChoice.HOST)
comp = mesonbuild.compilers.detect_compiler_for(env, l, MachineChoice.HOST)
with tempfile.TemporaryDirectory() as d:
comp.sanity_check(d, env)
langs.append(l)
@ -4170,7 +4173,7 @@ class AllPlatformTests(BasePlatformTests):
extra_args = None
libdir_flags = ['-L']
env = get_fake_env(testdirlib, self.builddir, self.prefix)
if env.detect_c_compiler(MachineChoice.HOST).get_id() in {'msvc', 'clang-cl', 'intel-cl'}:
if detect_c_compiler(env, MachineChoice.HOST).get_id() in {'msvc', 'clang-cl', 'intel-cl'}:
# msvc-like compiler, also test it with msvc-specific flags
libdir_flags += ['/LIBPATH:', '-LIBPATH:']
else:
@ -5562,7 +5565,7 @@ class AllPlatformTests(BasePlatformTests):
raise unittest.SkipTest('gcovr not found, or too old')
testdir = os.path.join(self.common_test_dir, '1 trivial')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_id() == 'clang':
if not mesonbuild.environment.detect_llvm_cov():
raise unittest.SkipTest('llvm-cov not found')
@ -5582,7 +5585,7 @@ class AllPlatformTests(BasePlatformTests):
raise unittest.SkipTest('gcovr not found, or too old')
testdir = os.path.join(self.common_test_dir, '105 generatorcustom')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_id() == 'clang':
if not mesonbuild.environment.detect_llvm_cov():
raise unittest.SkipTest('llvm-cov not found')
@ -5602,7 +5605,7 @@ class AllPlatformTests(BasePlatformTests):
raise unittest.SkipTest('gcovr not found, or too old')
testdir = os.path.join(self.common_test_dir, '1 trivial')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_id() == 'clang':
if not mesonbuild.environment.detect_llvm_cov():
raise unittest.SkipTest('llvm-cov not found')
@ -5622,7 +5625,7 @@ class AllPlatformTests(BasePlatformTests):
raise unittest.SkipTest('gcovr not found, or too old')
testdir = os.path.join(self.common_test_dir, '1 trivial')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_id() == 'clang':
if not mesonbuild.environment.detect_llvm_cov():
raise unittest.SkipTest('llvm-cov not found')
@ -5642,7 +5645,7 @@ class AllPlatformTests(BasePlatformTests):
raise unittest.SkipTest('gcovr not found, or too old')
testdir = os.path.join(self.common_test_dir, '1 trivial')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_id() == 'clang':
if not mesonbuild.environment.detect_llvm_cov():
raise unittest.SkipTest('llvm-cov not found')
@ -5842,7 +5845,7 @@ class AllPlatformTests(BasePlatformTests):
'bar/barfile'
]
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_argument_syntax() == 'msvc':
main_expected.append('bin/foo.pdb')
bar_expected.append('bin/bar.pdb')
@ -5936,18 +5939,18 @@ class AllPlatformTests(BasePlatformTests):
env = get_fake_env()
# Get the compiler so we know which compiler class to mock.
cc = env.detect_compiler_for('c', MachineChoice.HOST)
cc = mesonbuild.compilers.detect_compiler_for(env, 'c', MachineChoice.HOST)
cc_type = type(cc)
# Test a compiler that acts as a linker
with mock.patch.object(cc_type, 'INVOKES_LINKER', True):
cc = env.detect_compiler_for('c', MachineChoice.HOST)
cc = mesonbuild.compilers.detect_compiler_for(env, 'c', MachineChoice.HOST)
link_args = env.coredata.get_external_link_args(cc.for_machine, cc.language)
self.assertEqual(sorted(link_args), sorted(['-DCFLAG', '-flto']))
# And one that doesn't
with mock.patch.object(cc_type, 'INVOKES_LINKER', False):
cc = env.detect_compiler_for('c', MachineChoice.HOST)
cc = mesonbuild.compilers.detect_compiler_for(env, 'c', MachineChoice.HOST)
link_args = env.coredata.get_external_link_args(cc.for_machine, cc.language)
self.assertEqual(sorted(link_args), sorted(['-flto']))
@ -6141,8 +6144,8 @@ class FailureTests(BasePlatformTests):
'''
env = get_fake_env()
try:
env.detect_objc_compiler(MachineChoice.HOST)
env.detect_objcpp_compiler(MachineChoice.HOST)
detect_objc_compiler(env, MachineChoice.HOST)
detect_objcpp_compiler(env, MachineChoice.HOST)
except EnvironmentException:
code = "add_languages('objc')\nadd_languages('objcpp')"
self.assertMesonRaises(code, "Unknown compiler")
@ -6362,7 +6365,7 @@ class WindowsTests(BasePlatformTests):
'''
testdir = os.path.join(self.platform_test_dir, '1 basic')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_argument_syntax() != 'msvc':
raise unittest.SkipTest('Not using MSVC')
# To force people to update this test, and also test
@ -6375,7 +6378,7 @@ class WindowsTests(BasePlatformTests):
# resource compiler depfile generation is not yet implemented for msvc
env = get_fake_env(testdir, self.builddir, self.prefix)
depfile_works = env.detect_c_compiler(MachineChoice.HOST).get_id() not in {'msvc', 'clang-cl', 'intel-cl'}
depfile_works = detect_c_compiler(env, MachineChoice.HOST).get_id() not in {'msvc', 'clang-cl', 'intel-cl'}
self.init(testdir)
self.build()
@ -6406,7 +6409,7 @@ class WindowsTests(BasePlatformTests):
testdir = os.path.join(self.unit_test_dir, '45 vscpp17')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_argument_syntax() != 'msvc':
raise unittest.SkipTest('Test only applies to MSVC-like compilers')
@ -6424,7 +6427,7 @@ class WindowsTests(BasePlatformTests):
testdir = os.path.join(self.platform_test_dir, '1 basic')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_argument_syntax() != 'msvc':
raise unittest.SkipTest('Test only applies to MSVC-like compilers')
@ -6448,28 +6451,28 @@ class WindowsTests(BasePlatformTests):
with mock.patch.dict(os.environ, {envvar: name}):
env = get_fake_env()
try:
comp = getattr(env, f'detect_{lang}_compiler')(MachineChoice.HOST)
comp = compiler_from_language(env, lang, MachineChoice.HOST)
except EnvironmentException:
raise unittest.SkipTest(f'Could not find a compiler for {lang}')
self.assertEqual(comp.linker.id, expected)
def test_link_environment_variable_lld_link(self):
env = get_fake_env()
comp = getattr(env, 'detect_c_compiler')(MachineChoice.HOST)
comp = detect_c_compiler(env, MachineChoice.HOST)
if isinstance(comp, mesonbuild.compilers.GnuLikeCompiler):
raise unittest.SkipTest('GCC cannot be used with link compatible linkers.')
self._check_ld('lld-link', 'c', 'lld-link')
def test_link_environment_variable_link(self):
env = get_fake_env()
comp = getattr(env, 'detect_c_compiler')(MachineChoice.HOST)
comp = detect_c_compiler(env, MachineChoice.HOST)
if isinstance(comp, mesonbuild.compilers.GnuLikeCompiler):
raise unittest.SkipTest('GCC cannot be used with link compatible linkers.')
self._check_ld('link', 'c', 'link')
def test_link_environment_variable_optlink(self):
env = get_fake_env()
comp = getattr(env, 'detect_c_compiler')(MachineChoice.HOST)
comp = detect_c_compiler(env, MachineChoice.HOST)
if isinstance(comp, mesonbuild.compilers.GnuLikeCompiler):
raise unittest.SkipTest('GCC cannot be used with link compatible linkers.')
self._check_ld('optlink', 'c', 'optlink')
@ -6481,7 +6484,7 @@ class WindowsTests(BasePlatformTests):
@skip_if_not_language('d')
def test_link_environment_variable_d(self):
env = get_fake_env()
comp = getattr(env, 'detect_d_compiler')(MachineChoice.HOST)
comp = detect_d_compiler(env, MachineChoice.HOST)
if comp.id == 'dmd':
raise unittest.SkipTest('meson cannot reliably make DMD use a different linker.')
self._check_ld('lld-link', 'd', 'lld-link')
@ -6498,7 +6501,7 @@ class WindowsTests(BasePlatformTests):
self.build()
# Test that binaries have a non-zero checksum
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
cc_id = cc.get_id()
ld_id = cc.get_linker_id()
dll = glob(os.path.join(self.builddir, '*mycpplib.dll'))[0]
@ -6520,7 +6523,7 @@ class WindowsTests(BasePlatformTests):
'''
# Verify that the `b_vscrt` option is available
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if OptionKey('b_vscrt') not in cc.base_options:
raise unittest.SkipTest('Compiler does not support setting the VS CRT')
# Verify that qmake is for Qt5
@ -6546,7 +6549,7 @@ class WindowsTests(BasePlatformTests):
'''
# Verify that the `b_vscrt` option is available
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if OptionKey('b_vscrt') not in cc.base_options:
raise unittest.SkipTest('Compiler does not support setting the VS CRT')
@ -6614,7 +6617,7 @@ class DarwinTests(BasePlatformTests):
'''
testdir = os.path.join(self.platform_test_dir, '7 bitcode')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.id != 'clang':
raise unittest.SkipTest('Not using Clang on OSX')
# Try with bitcode enabled
@ -6794,7 +6797,7 @@ class LinuxlikeTests(BasePlatformTests):
self.assertEqual(libhello_nolib.get_pkgconfig_variable('escaped_var', {}), r'hello\ world')
self.assertEqual(libhello_nolib.get_pkgconfig_variable('unescaped_var', {}), 'hello world')
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_id() in {'gcc', 'clang'}:
for name in {'ct', 'ct0'}:
ct_dep = PkgConfigDependency(name, env, kwargs)
@ -7069,7 +7072,7 @@ class LinuxlikeTests(BasePlatformTests):
'''
testdir = os.path.join(self.common_test_dir, '36 has function')
env = get_fake_env(testdir, self.builddir, self.prefix)
cpp = env.detect_cpp_compiler(MachineChoice.HOST)
cpp = detect_cpp_compiler(env, MachineChoice.HOST)
Oflag = '-O3'
OflagCPP = Oflag
if cpp.get_id() in ('clang', 'gcc'):
@ -7161,7 +7164,7 @@ class LinuxlikeTests(BasePlatformTests):
'''
testdir = os.path.join(self.common_test_dir, '1 trivial')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
self._test_stds_impl(testdir, cc)
def test_compiler_cpp_stds(self):
@ -7171,7 +7174,7 @@ class LinuxlikeTests(BasePlatformTests):
'''
testdir = os.path.join(self.common_test_dir, '2 cpp')
env = get_fake_env(testdir, self.builddir, self.prefix)
cpp = env.detect_cpp_compiler(MachineChoice.HOST)
cpp = detect_cpp_compiler(env, MachineChoice.HOST)
self._test_stds_impl(testdir, cpp)
def test_unity_subproj(self):
@ -8011,7 +8014,7 @@ class LinuxlikeTests(BasePlatformTests):
if is_cygwin() or is_osx():
raise unittest.SkipTest('Not applicable on Cygwin or OSX.')
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
cc = detect_c_compiler(env, MachineChoice.HOST)
linker = cc.linker
if not linker.export_dynamic_args(env):
raise unittest.SkipTest('Not applicable for linkers without --export-dynamic')
@ -8124,7 +8127,7 @@ class LinuxlikeTests(BasePlatformTests):
for envvar in envvars:
with mock.patch.dict(os.environ, {envvar: name}):
env = get_fake_env()
comp = getattr(env, f'detect_{lang}_compiler')(MachineChoice.HOST)
comp = compiler_from_language(env, lang, MachineChoice.HOST)
if isinstance(comp, (mesonbuild.compilers.AppleClangCCompiler,
mesonbuild.compilers.AppleClangCPPCompiler,
mesonbuild.compilers.AppleClangObjCCompiler,
@ -8910,8 +8913,7 @@ class NativeFileTests(BasePlatformTests):
with more than one implementation, such as C, C++, ObjC, ObjC++, and D.
"""
env = get_fake_env()
getter = getattr(env, f'detect_{lang}_compiler')
getter = functools.partial(getter, for_machine)
getter = lambda: compiler_from_language(env, lang, for_machine)
cc = getter()
binary, newid = cb(cc)
env.binaries[for_machine].binaries[lang] = binary
@ -9115,10 +9117,8 @@ class NativeFileTests(BasePlatformTests):
"""
wrapper = self.helper_create_binary_wrapper(binary, version=version_str)
env = get_fake_env()
getter = getattr(env, f'detect_{lang}_compiler')
getter = functools.partial(getter, MachineChoice.HOST)
env.binaries.host.binaries[lang] = [wrapper]
compiler = getter()
compiler = compiler_from_language(env, lang, MachineChoice.HOST)
self.assertEqual(compiler.version, version)
@skip_if_not_language('vala')
@ -9145,7 +9145,7 @@ class NativeFileTests(BasePlatformTests):
extra_args={'Xlinker': 'macosx_version. PROJECT:ld - 1.2.3'})
env = get_fake_env()
env.binaries.host.binaries['swift'] = [wrapper]
compiler = env.detect_swift_compiler(MachineChoice.HOST)
compiler = detect_swift_compiler(env, MachineChoice.HOST)
self.assertEqual(compiler.version, '1.2345')
def test_native_file_dirs(self):
@ -10023,7 +10023,7 @@ class SubprojectsCommandTests(BasePlatformTests):
# If a user has git configuration init.defaultBranch set we want to override that
with tempfile.TemporaryDirectory() as d:
out = git(['--version'], str(d))[1]
if version_compare(mesonbuild.environment.search_version(out), '>= 2.28'):
if version_compare(search_version(out), '>= 2.28'):
extra_cmd = ['--initial-branch', 'master']
else:
extra_cmd = []

Loading…
Cancel
Save