compilers: Dispatch to dynamic linker class

Most of the cuda code is from Olexa Bilaniuk.
Most of the PGI code is from Michael Hirsc
pull/5681/head
Dylan Baker 6 years ago
parent 2bd85c614a
commit 06dcbd50ee
  1. 13
      mesonbuild/backend/ninjabackend.py
  2. 10
      mesonbuild/build.py
  3. 3
      mesonbuild/compilers/__init__.py
  4. 24
      mesonbuild/compilers/c.py
  5. 264
      mesonbuild/compilers/compilers.py
  6. 18
      mesonbuild/compilers/cpp.py
  7. 16
      mesonbuild/compilers/cs.py
  8. 58
      mesonbuild/compilers/cuda.py
  9. 131
      mesonbuild/compilers/d.py
  10. 8
      mesonbuild/compilers/fortran.py
  11. 18
      mesonbuild/compilers/java.py
  12. 60
      mesonbuild/compilers/mixins/arm.py
  13. 43
      mesonbuild/compilers/mixins/ccrx.py
  14. 72
      mesonbuild/compilers/mixins/clike.py
  15. 123
      mesonbuild/compilers/mixins/gnu.py
  16. 3
      mesonbuild/compilers/mixins/intel.py
  17. 26
      mesonbuild/compilers/mixins/pgi.py
  18. 69
      mesonbuild/compilers/mixins/visualstudio.py
  19. 11
      mesonbuild/compilers/rust.py
  20. 12
      mesonbuild/compilers/swift.py
  21. 5
      mesonbuild/linkers.py

@ -1327,7 +1327,8 @@ int dummy;
self.get_target_dir(target))
else:
target_slashname_workaround_dir = self.get_target_dir(target)
rpath_args = rustc.build_rpath_args(self.environment.get_build_dir(),
rpath_args = rustc.build_rpath_args(self.environment,
self.environment.get_build_dir(),
target_slashname_workaround_dir,
self.determine_rpath_dirs(target),
target.build_rpath,
@ -2324,9 +2325,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
# All shared libraries are PIC
commands += linker.get_pic_args()
# Add -Wl,-soname arguments on Linux, -install_name on OS X
commands += linker.get_soname_args(target.prefix, target.name, target.suffix,
target.soversion, target.darwin_versions,
isinstance(target, build.SharedModule))
commands += linker.get_soname_args(
self.environment, target.prefix, target.name, target.suffix,
target.soversion, target.darwin_versions,
isinstance(target, build.SharedModule))
# This is only visited when building for Windows using either GCC or Visual Studio
if target.vs_module_defs and hasattr(linker, 'gen_vs_module_defs_args'):
commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src))
@ -2537,7 +2539,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
self.get_target_dir(target))
else:
target_slashname_workaround_dir = self.get_target_dir(target)
commands += linker.build_rpath_args(self.environment.get_build_dir(),
commands += linker.build_rpath_args(self.environment,
self.environment.get_build_dir(),
target_slashname_workaround_dir,
self.determine_rpath_dirs(target),
target.build_rpath,

@ -28,7 +28,7 @@ from .mesonlib import (
extract_as_list, typeslistify, stringlistify, classify_unity_sources,
get_filenames_templates_dict, substitute_values, has_path_sep,
)
from .compilers import Compiler, is_object, clink_langs, sort_clink, lang_suffixes, get_macos_dylib_install_name
from .compilers import Compiler, is_object, clink_langs, sort_clink, lang_suffixes
from .linkers import StaticLinker
from .interpreterbase import FeatureNew
@ -96,8 +96,12 @@ known_stlib_kwargs = known_build_target_kwargs | {'pic'}
known_jar_kwargs = known_exe_kwargs | {'main_class'}
@lru_cache(maxsize=None)
def get_target_macos_dylib_install_name(ld):
return get_macos_dylib_install_name(ld.prefix, ld.name, ld.suffix, ld.soversion)
def get_target_macos_dylib_install_name(ld) -> str:
name = ['@rpath/', ld.prefix, ld.name]
if ld.soversion is not None:
name.append('.' + ld.soversion)
name.append('.dylib')
return ''.join(name)
class InvalidArguments(MesonException):
pass

@ -23,7 +23,6 @@ __all__ = [
'clink_langs',
'c_suffixes',
'cpp_suffixes',
'get_macos_dylib_install_name',
'get_base_compile_args',
'get_base_link_args',
'is_assembly',
@ -185,6 +184,6 @@ from .rust import RustCompiler
from .swift import SwiftCompiler
from .vala import ValaCompiler
from .mixins.visualstudio import VisualStudioLikeCompiler
from .mixins.gnu import GnuCompiler, get_macos_dylib_install_name
from .mixins.gnu import GnuCompiler
from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler
from .mixins.clang import ClangCompiler

@ -27,6 +27,7 @@ from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler
from .mixins.clang import ClangCompiler
from .mixins.elbrus import ElbrusCompiler
from .mixins.pgi import PGICompiler
from .mixins.islinker import BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin
from .compilers import (
gnu_winlibs,
msvc_winlibs,
@ -112,14 +113,8 @@ class ClangCCompiler(ClangCompiler, CCompiler):
def get_option_link_args(self, options):
return []
def get_linker_always_args(self):
basic = super().get_linker_always_args()
if self.compiler_type.is_osx_compiler:
return basic + ['-Wl,-headerpad_max_install_names']
return basic
class EmscriptenCCompiler(ClangCCompiler):
class EmscriptenCCompiler(LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin, ClangCCompiler):
def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
if not is_cross:
raise MesonException('Emscripten compiler can only be used for cross compilation.')
@ -129,18 +124,6 @@ class EmscriptenCCompiler(ClangCCompiler):
def get_option_link_args(self, options):
return []
def get_linker_always_args(self):
return []
def get_asneeded_args(self):
return []
def get_lundef_args(self):
return []
def build_rpath_args(self, *args, **kwargs):
return []
def get_soname_args(self, *args, **kwargs):
raise MesonException('Emscripten does not support shared libraries.')
@ -388,9 +371,6 @@ class CcrxCCompiler(CcrxCompiler, CCompiler):
def get_output_args(self, target):
return ['-output=obj=%s' % target]
def get_linker_output_args(self, outputname):
return ['-output=%s' % outputname]
def get_werror_args(self):
return ['-change_message=error']

@ -13,9 +13,10 @@
# limitations under the License.
import contextlib, enum, os.path, re, tempfile, shlex
from typing import Optional, Tuple, List
import typing
from typing import List, Optional, Tuple
from ..linkers import StaticLinker
from ..linkers import StaticLinker, GnuLikeDynamicLinkerMixin
from .. import coredata
from .. import mlog
from .. import mesonlib
@ -27,6 +28,11 @@ from ..envconfig import (
Properties,
)
if typing.TYPE_CHECKING:
from ..coredata import OptionDictType
from ..environment import Environment
from ..linkers import DynamicLinker # noqa: F401
"""This file contains the data files of all compilers Meson knows
about. To support a new compiler, add its information below.
Also add corresponding autodetection code in environment.py."""
@ -335,18 +341,26 @@ def get_base_link_args(options, linker, is_shared_module):
args += linker.get_coverage_link_args()
except KeyError:
pass
# These do not need a try...except
if not is_shared_module and option_enabled(linker.base_options, options, 'b_lundef'):
args.append('-Wl,--no-undefined')
as_needed = option_enabled(linker.base_options, options, 'b_asneeded')
bitcode = option_enabled(linker.base_options, options, 'b_bitcode')
# Shared modules cannot be built with bitcode_bundle because
# -bitcode_bundle is incompatible with -undefined and -bundle
if bitcode and not is_shared_module:
args.append('-Wl,-bitcode_bundle')
args.extend(linker.bitcode_args())
elif as_needed:
# -Wl,-dead_strip_dylibs is incompatible with bitcode
args.extend(linker.get_asneeded_args())
# Apple's ld (the only one that supports bitcode) does not like any
# -undefined arguments at all, so don't pass these when using bitcode
if not bitcode:
if (not is_shared_module and
option_enabled(linker.base_options, options, 'b_lundef')):
args.extend(linker.no_undefined_link_args())
else:
args.extend(linker.get_allow_undefined_link_args())
try:
crt_val = options['b_vscrt'].value
buildtype = options['buildtype'].value
@ -358,30 +372,6 @@ def get_base_link_args(options, linker, is_shared_module):
pass
return args
def prepare_rpaths(raw_rpaths, build_dir, from_dir):
internal_format_rpaths = [evaluate_rpath(p, build_dir, from_dir) for p in raw_rpaths]
ordered_rpaths = order_rpaths(internal_format_rpaths)
return ordered_rpaths
def order_rpaths(rpath_list):
# We want rpaths that point inside our build dir to always override
# those pointing to other places in the file system. This is so built
# binaries prefer our libraries to the ones that may lie somewhere
# in the file system, such as /lib/x86_64-linux-gnu.
#
# The correct thing to do here would be C++'s std::stable_partition.
# Python standard library does not have it, so replicate it with
# sort, which is guaranteed to be stable.
return sorted(rpath_list, key=os.path.isabs)
def evaluate_rpath(p, build_dir, from_dir):
if p == from_dir:
return '' # relpath errors out in this case
elif os.path.isabs(p):
return p # These can be outside of build dir.
else:
return os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir))
class CrossNoRunException(MesonException):
pass
@ -529,7 +519,7 @@ class CompilerArgs(list):
return True
return False
def to_native(self, copy=False):
def to_native(self, copy: bool = False) -> typing.List[str]:
# Check if we need to add --start/end-group for circular dependencies
# between static libraries, and for recursively searching for symbols
# needed by static libraries that are provided by object files or
@ -538,8 +528,12 @@ class CompilerArgs(list):
new = self.copy()
else:
new = self
if get_compiler_uses_gnuld(self.compiler):
global soregex
# This covers all ld.bfd, ld.gold, ld.gold, and xild on Linux, which
# all act like (or are) gnu ld
# TODO: this could probably be added to the DynamicLinker instead
if (hasattr(self.compiler, 'linker') and
self.compiler.linker is not None and
isinstance(self.compiler.linker, GnuLikeDynamicLinkerMixin)):
group_start = -1
group_end = -1
for i, each in enumerate(new):
@ -656,7 +650,8 @@ class Compiler:
# manually searched.
internal_libs = ()
def __init__(self, exelist, version, for_machine: MachineChoice, **kwargs):
def __init__(self, exelist, version, for_machine: MachineChoice,
linker: typing.Optional['DynamicLinker'] = None, **kwargs):
if isinstance(exelist, str):
self.exelist = [exelist]
elif isinstance(exelist, list):
@ -676,6 +671,7 @@ class Compiler:
self.full_version = None
self.for_machine = for_machine
self.base_options = []
self.linker = linker
def __repr__(self):
repr_str = "<{0}: v{1} `{2}`>"
@ -729,6 +725,12 @@ class Compiler:
def get_exelist(self):
return self.exelist[:]
def get_linker_exelist(self) -> typing.List[str]:
return self.linker.get_exelist()
def get_linker_output_args(self, outputname: str) -> typing.List[str]:
return self.linker.get_output_args(outputname)
def get_builtin_define(self, *args, **kwargs):
raise EnvironmentException('%s does not support get_builtin_define.' % self.id)
@ -738,17 +740,17 @@ class Compiler:
def get_always_args(self):
return []
def can_linker_accept_rsp(self):
def can_linker_accept_rsp(self) -> bool:
"""
Determines whether the linker can accept arguments using the @rsp syntax.
"""
return mesonlib.is_windows()
return self.linker.get_accepts_rsp()
def get_linker_always_args(self):
return []
return self.linker.get_always_args()
def get_linker_lib_prefix(self):
return ''
return self.linker.get_lib_prefix()
def gen_import_library_args(self, implibname):
"""
@ -769,7 +771,10 @@ class Compiler:
"""
return self.get_language() in languages_using_ldflags
def get_args_from_envvars(self):
def get_linker_args_from_envvars(self) -> typing.List[str]:
return self.linker.get_args_from_envvars()
def get_args_from_envvars(self) -> typing.Tuple[typing.List[str], typing.List[str]]:
"""
Returns a tuple of (compile_flags, link_flags) for the specified language
from the inherited environment
@ -781,15 +786,13 @@ class Compiler:
mlog.debug('No {} in the environment, not changing global flags.'.format(var))
lang = self.get_language()
compiler_is_linker = False
if hasattr(self, 'get_linker_exelist'):
compiler_is_linker = (self.get_exelist() == self.get_linker_exelist())
compiler_is_linker = self.linker is not None and self.linker.invoked_by_compiler()
if lang not in cflags_mapping:
return [], []
compile_flags = []
link_flags = []
compile_flags = [] # type: typing.List[str]
link_flags = [] # type: typing.List[str]
env_compile_flags = os.environ.get(cflags_mapping[lang])
log_var(cflags_mapping[lang], env_compile_flags)
@ -798,12 +801,11 @@ class Compiler:
# Link flags (same for all languages)
if self.use_ldflags():
env_link_flags = os.environ.get('LDFLAGS')
env_link_flags = self.get_linker_args_from_envvars()
else:
env_link_flags = None
env_link_flags = []
log_var('LDFLAGS', env_link_flags)
if env_link_flags is not None:
link_flags += shlex.split(env_link_flags)
link_flags += env_link_flags
if compiler_is_linker:
# When the compiler is used as a wrapper around the linker (such as
# with GCC and Clang), the compile flags can be needed while linking
@ -861,8 +863,8 @@ class Compiler:
def get_option_compile_args(self, options):
return []
def get_option_link_args(self, options):
return []
def get_option_link_args(self, options: 'OptionDictType') -> typing.List[str]:
return self.linker.get_option_args(options)
def check_header(self, *args, **kwargs) -> Tuple[bool, bool]:
raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language())
@ -910,10 +912,8 @@ class Compiler:
'Language {} does not support has_multi_arguments.'.format(
self.get_display_language()))
def has_multi_link_arguments(self, args, env) -> Tuple[bool, bool]:
raise EnvironmentException(
'Language {} does not support has_multi_link_arguments.'.format(
self.get_display_language()))
def has_multi_link_arguments(self, args: typing.List[str], env: 'Environment') -> Tuple[bool, bool]:
return self.linker.has_multi_arguments(args, env)
def _get_compile_output(self, dirname, mode):
# In pre-processor mode, the output is sent to stdout and discarded
@ -1026,19 +1026,23 @@ class Compiler:
def get_compile_debugfile_args(self, rel_obj, **kwargs):
return []
def get_link_debugfile_args(self, rel_obj):
return []
def get_link_debugfile_args(self, targetfile: str) -> typing.List[str]:
return self.linker.get_debugfile_args(targetfile)
def get_std_shared_lib_link_args(self):
return []
def get_std_shared_lib_link_args(self) -> typing.List[str]:
return self.linker.get_std_shared_lib_args()
def get_std_shared_module_link_args(self, options: 'OptionDictType') -> typing.List[str]:
return self.linker.get_std_shared_module_args(options)
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]:
return self.linker.get_link_whole_for(args)
def get_std_shared_module_link_args(self, options):
return self.get_std_shared_lib_link_args()
def get_allow_undefined_link_args(self) -> typing.List[str]:
return self.linker.get_allow_undefined_args()
def get_link_whole_for(self, args):
if isinstance(args, list) and not args:
return []
raise EnvironmentException('Language %s does not support linking whole archives.' % self.get_display_language())
def no_undefined_link_args(self) -> typing.List[str]:
return self.linker.no_undefined_args()
# Compiler arguments needed to enable the given instruction set.
# May be [] meaning nothing needed or None meaning the given set
@ -1046,77 +1050,11 @@ class Compiler:
def get_instruction_set_args(self, instruction_set):
return None
def build_unix_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
if not rpath_paths and not install_rpath and not build_rpath:
return []
args = []
if get_compiler_is_osx_compiler(self):
# Ensure that there is enough space for install_name_tool in-place editing of large RPATHs
args.append('-Wl,-headerpad_max_install_names')
# @loader_path is the equivalent of $ORIGIN on macOS
# https://stackoverflow.com/q/26280738
origin_placeholder = '@loader_path'
else:
origin_placeholder = '$ORIGIN'
# The rpaths we write must be relative if they point to the build dir,
# because otherwise they have different length depending on the build
# directory. This breaks reproducible builds.
processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
# Need to deduplicate rpaths, as macOS's install_name_tool
# is *very* allergic to duplicate -delete_rpath arguments
# when calling depfixer on installation.
all_paths = OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
# Build_rpath is used as-is (it is usually absolute).
if build_rpath != '':
all_paths.add(build_rpath)
if mesonlib.is_dragonflybsd() or mesonlib.is_openbsd():
# This argument instructs the compiler to record the value of
# ORIGIN in the .dynamic section of the elf. On Linux this is done
# by default, but is not on dragonfly/openbsd for some reason. Without this
# $ORIGIN in the runtime path will be undefined and any binaries
# linked against local libraries will fail to resolve them.
args.append('-Wl,-z,origin')
if get_compiler_is_osx_compiler(self):
# macOS does not support colon-separated strings in LC_RPATH,
# hence we have to pass each path component individually
args += ['-Wl,-rpath,' + rp for rp in all_paths]
else:
# In order to avoid relinking for RPATH removal, the binary needs to contain just
# enough space in the ELF header to hold the final installation RPATH.
paths = ':'.join(all_paths)
if len(paths) < len(install_rpath):
padding = 'X' * (len(install_rpath) - len(paths))
if not paths:
paths = padding
else:
paths = paths + ':' + padding
args.append('-Wl,-rpath,' + paths)
if mesonlib.is_sunos():
return args
if get_compiler_is_linuxlike(self):
# Rpaths to use while linking must be absolute. These are not
# written to the binary. Needed only with GNU ld:
# https://sourceware.org/bugzilla/show_bug.cgi?id=16936
# Not needed on Windows or other platforms that don't use RPATH
# https://github.com/mesonbuild/meson/issues/1897
#
# In addition, this linker option tends to be quite long and some
# compilers have trouble dealing with it. That's why we will include
# one option per folder, like this:
#
# -Wl,-rpath-link,/path/to/folder1 -Wl,-rpath,/path/to/folder2 ...
#
# ...instead of just one single looooong option, like this:
#
# -Wl,-rpath-link,/path/to/folder1:/path/to/folder2:...
args += ['-Wl,-rpath-link,' + os.path.join(build_dir, p) for p in rpath_paths]
return args
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]:
return self.linker.build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
def thread_flags(self, env):
return []
@ -1125,10 +1063,6 @@ class Compiler:
raise EnvironmentException('Language %s does not support OpenMP flags.' % self.get_display_language())
def language_stdlib_only_link_flags(self):
# The linker flags needed to link the standard library of the current
# language in. This is needed in cases where you e.g. combine D and C++
# and both of which need to link their runtime library in or otherwise
# building fails with undefined symbols.
return []
def gnu_symbol_visibility_args(self, vistype):
@ -1149,9 +1083,8 @@ class Compiler:
m = 'Language {} does not support position-independent executable'
raise EnvironmentException(m.format(self.get_display_language()))
def get_pie_link_args(self):
m = 'Language {} does not support position-independent executable'
raise EnvironmentException(m.format(self.get_display_language()))
def get_pie_link_args(self) -> typing.List[str]:
return self.linker.get_pie_args()
def get_argument_syntax(self):
"""Returns the argument family type.
@ -1172,11 +1105,8 @@ class Compiler:
raise EnvironmentException(
'%s does not support get_profile_use_args ' % self.get_id())
def get_undefined_link_args(self):
'''
Get args for allowing undefined symbols when linking to a shared library
'''
return []
def get_undefined_link_args(self) -> typing.List[str]:
return self.linker.get_undefined_link_args()
def remove_linkerlike_args(self, args):
return [x for x in args if not x.startswith('-Wl')]
@ -1185,13 +1115,32 @@ class Compiler:
return []
def get_lto_link_args(self) -> List[str]:
return []
return self.linker.get_lto_args()
def sanitizer_compile_args(self, value: str) -> List[str]:
return []
def sanitizer_link_args(self, value: str) -> List[str]:
return []
return self.linker.sanitizer_args(value)
def get_asneeded_args(self) -> typing.List[str]:
return self.linker.get_asneeded_args()
def bitcode_args(self) -> typing.List[str]:
return self.linker.bitcode_args()
def get_linker_debug_crt_args(self) -> typing.List[str]:
return self.linker.get_debug_crt_args()
def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]:
return self.linker.get_buildtype_args(buildtype)
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]:
return self.linker.get_soname_args(
env, prefix, shlib_name, suffix, soversion,
darwin_versions, is_shared_module)
@enum.unique
@ -1235,23 +1184,6 @@ def get_compiler_is_linuxlike(compiler):
compiler_type = getattr(compiler, 'compiler_type', None)
return compiler_type and compiler_type.is_standard_compiler
def get_compiler_is_osx_compiler(compiler):
compiler_type = getattr(compiler, 'compiler_type', None)
return compiler_type and compiler_type.is_osx_compiler
def get_compiler_uses_gnuld(c):
# FIXME: Perhaps we should detect the linker in the environment?
# FIXME: Assumes that *BSD use GNU ld, but they might start using lld soon
compiler_type = getattr(c, 'compiler_type', None)
return compiler_type in {
CompilerType.GCC_STANDARD,
CompilerType.GCC_MINGW,
CompilerType.GCC_CYGWIN,
CompilerType.CLANG_STANDARD,
CompilerType.CLANG_MINGW,
CompilerType.ICC_STANDARD,
}
def get_largefile_args(compiler):
'''
Enable transparent large-file-support for 32-bit UNIX systems

@ -36,6 +36,7 @@ from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler
from .mixins.clang import ClangCompiler
from .mixins.elbrus import ElbrusCompiler
from .mixins.pgi import PGICompiler
from .mixins.islinker import BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin
def non_msvc_eh_options(eh, args):
@ -183,7 +184,7 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
return ['-lstdc++']
class EmscriptenCPPCompiler(ClangCPPCompiler):
class EmscriptenCPPCompiler(LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin, ClangCPPCompiler):
def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
if not is_cross:
raise MesonException('Emscripten compiler can only be used for cross compilation.')
@ -200,18 +201,6 @@ class EmscriptenCPPCompiler(ClangCPPCompiler):
def get_option_link_args(self, options):
return []
def get_linker_always_args(self):
return []
def get_asneeded_args(self):
return []
def get_lundef_args(self):
return []
def build_rpath_args(self, *args, **kwargs):
return []
def get_soname_args(self, *args, **kwargs):
raise MesonException('Emscripten does not support shared libraries.')
@ -574,9 +563,6 @@ class CcrxCPPCompiler(CcrxCompiler, CPPCompiler):
def get_output_args(self, target):
return ['-output=obj=%s' % target]
def get_linker_output_args(self, outputname):
return ['-output=%s' % outputname]
def get_option_link_args(self, options):
return []

@ -18,6 +18,7 @@ from ..mesonlib import EnvironmentException
from ..mesonlib import is_windows
from .compilers import Compiler, MachineChoice, mono_buildtype_args
from .mixins.islinker import BasicLinkerIsCompilerMixin
cs_optimization_args = {'0': [],
'g': [],
@ -27,7 +28,7 @@ cs_optimization_args = {'0': [],
's': ['-optimize+'],
}
class CsCompiler(Compiler):
class CsCompiler(BasicLinkerIsCompilerMixin, Compiler):
def __init__(self, exelist, version, for_machine: MachineChoice, comp_id, runner=None):
self.language = 'cs'
super().__init__(exelist, version, for_machine)
@ -50,18 +51,12 @@ class CsCompiler(Compiler):
def get_link_args(self, fname):
return ['-r:' + fname]
def get_soname_args(self, *args):
return []
def get_werror_args(self):
return ['-warnaserror']
def split_shlib_to_parts(self, fname):
return None, fname
def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
return []
def get_dependency_gen_args(self, outtarget, outfile):
return []
@ -71,15 +66,9 @@ class CsCompiler(Compiler):
def get_compile_only_args(self):
return []
def get_linker_output_args(self, outputname):
return []
def get_coverage_args(self):
return []
def get_coverage_link_args(self):
return []
def get_std_exe_link_args(self):
return []
@ -142,6 +131,7 @@ class CsCompiler(Compiler):
def get_optimization_args(self, optimization_level):
return cs_optimization_args[optimization_level]
class MonoCompiler(CsCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice):
super().__init__(exelist, version, for_machine, 'mono',

@ -13,12 +13,17 @@
# limitations under the License.
import os.path
import typing
from .. import mlog
from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe
from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args,
cuda_debug_args, CompilerType)
if typing.TYPE_CHECKING:
from ..environment import Environment # noqa: F401
class CudaCompiler(Compiler):
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
if not hasattr(self, 'language'):
@ -47,7 +52,7 @@ class CudaCompiler(Compiler):
return []
def thread_link_flags(self, environment):
return ['-Xcompiler=-pthread']
return self._cook_link_args(super().thread_link_flags())
def sanity_check(self, work_dir, environment):
mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist))
@ -142,9 +147,6 @@ class CudaCompiler(Compiler):
else:
mlog.debug('cudaGetDeviceCount() returned ' + stde)
def get_compiler_check_args(self):
return super().get_compiler_check_args() + []
def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None):
result, cached = super().has_header_symbol(hname, symbol, prefix, env, extra_args, dependencies)
if result:
@ -159,22 +161,24 @@ class CudaCompiler(Compiler):
return self.compiles(t.format(**fargs), env, extra_args, dependencies)
@staticmethod
def _cook_link_args(args):
def _cook_link_args(args: typing.List[str]) -> typing.List[str]:
"""
Converts GNU-style arguments -Wl,-arg,-arg
to NVCC-style arguments -Xlinker=-arg,-arg
"""
return [arg.replace('-Wl', '-Xlinker=', 1) if arg.startswith('-Wl') else arg for arg in args]
def get_output_args(self, target):
return ['-o', target]
cooked = [] # type: typing.List[str]
for arg in args:
if arg.startswith('-Wl,'):
arg = arg.replace('-Wl,', '-Xlinker=', 1)
arg = arg.replace(' ', '\\')
cooked.append(arg)
return cooked
def name_string(self):
return ' '.join(self.exelist)
def get_soname_args(self, *args):
rawargs = get_gcc_soname_args(CompilerType.GCC_STANDARD, *args)
return self._cook_link_args(rawargs)
return self._cook_link_args(super().get_soname_args(*args))
def get_dependency_gen_args(self, outtarget, outfile):
return []
@ -194,12 +198,6 @@ class CudaCompiler(Compiler):
def get_werror_args(self):
return ['-Werror=cross-execution-space-call,deprecated-declarations,reorder']
def get_linker_exelist(self):
return self.exelist[:]
def get_linker_output_args(self, outputname):
return ['-o', outputname]
def get_warn_args(self, level):
return self.warn_args[level]
@ -211,27 +209,17 @@ class CudaCompiler(Compiler):
path = '.'
return ['-I' + path]
def get_std_shared_lib_link_args(self):
return ['-shared']
def depfile_for_object(self, objfile):
return objfile + '.' + self.get_depfile_suffix()
def get_depfile_suffix(self):
return 'd'
def get_buildtype_linker_args(self, buildtype):
return []
def get_std_exe_link_args(self):
return []
def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
rawargs = self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
return self._cook_link_args(rawargs)
def get_linker_search_args(self, dirname):
return ['-L' + dirname]
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]:
return self._cook_link_args(super().build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath))
def linker_to_compiler_args(self, args):
return args
@ -241,3 +229,9 @@ class CudaCompiler(Compiler):
def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
return []
def get_output_args(self, target: str) -> typing.List[str]:
return ['-o', target]
def get_std_exe_link_args(self) -> typing.List[str]:
return []

@ -13,6 +13,7 @@
# limitations under the License.
import os.path, subprocess
import typing
from ..mesonlib import (
EnvironmentException, MachineChoice, version_compare, is_windows, is_osx
@ -27,7 +28,8 @@ from .compilers import (
Compiler,
CompilerArgs,
)
from .mixins.gnu import get_gcc_soname_args, GnuCompiler
from .mixins.gnu import GnuCompiler
from .mixins.islinker import LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin
d_feature_args = {'gcc': {'unittest': '-funittest',
'debug': '-fdebug',
@ -65,9 +67,6 @@ dmd_optimization_args = {'0': [],
class DmdLikeCompilerMixin:
def get_linker_exelist(self):
return self.get_exelist()
def get_output_args(self, target):
return ['-of=' + target]
@ -100,11 +99,6 @@ class DmdLikeCompilerMixin:
# DMD and LDC does not currently return Makefile-compatible dependency info.
return []
def get_linker_search_args(self, dirname):
# -L is recognized as "add this to the search path" by the linker,
# while the compiler recognizes it as "pass to linker".
return ['-Wl,-L' + dirname]
def get_coverage_args(self):
return ['-cov']
@ -114,22 +108,111 @@ class DmdLikeCompilerMixin:
def get_compile_only_args(self):
return ['-c']
def get_soname_args(self, *args):
# FIXME: Make this work for cross-compiling
def depfile_for_object(self, objfile):
return objfile + '.' + self.get_depfile_suffix()
def get_depfile_suffix(self):
return 'deps'
def get_pic_args(self):
if is_windows():
return []
elif is_osx():
soname_args = get_gcc_soname_args(CompilerType.GCC_OSX, *args)
if soname_args:
return ['-Wl,' + ','.join(soname_args)]
return []
return ['-fPIC']
def get_feature_args(self, kwargs, build_to_src):
res = []
if 'unittest' in kwargs:
unittest = kwargs.pop('unittest')
unittest_arg = d_feature_args[self.id]['unittest']
if not unittest_arg:
raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string())
if unittest:
res.append(unittest_arg)
if 'debug' in kwargs:
debug_level = -1
debugs = kwargs.pop('debug')
if not isinstance(debugs, list):
debugs = [debugs]
debug_arg = d_feature_args[self.id]['debug']
if not debug_arg:
raise EnvironmentException('D compiler %s does not support conditional debug identifiers.' % self.name_string())
# Parse all debug identifiers and the largest debug level identifier
for d in debugs:
if isinstance(d, int):
if d > debug_level:
debug_level = d
elif isinstance(d, str) and d.isdigit():
if int(d) > debug_level:
debug_level = int(d)
else:
res.append('{0}={1}'.format(debug_arg, d))
return get_gcc_soname_args(CompilerType.GCC_STANDARD, *args)
if debug_level >= 0:
res.append('{0}={1}'.format(debug_arg, debug_level))
if 'versions' in kwargs:
version_level = -1
versions = kwargs.pop('versions')
if not isinstance(versions, list):
versions = [versions]
version_arg = d_feature_args[self.id]['version']
if not version_arg:
raise EnvironmentException('D compiler %s does not support conditional version identifiers.' % self.name_string())
# Parse all version identifiers and the largest version level identifier
for v in versions:
if isinstance(v, int):
if v > version_level:
version_level = v
elif isinstance(v, str) and v.isdigit():
if int(v) > version_level:
version_level = int(v)
else:
res.append('{0}={1}'.format(version_arg, v))
if version_level >= 0:
res.append('{0}={1}'.format(version_arg, version_level))
if 'import_dirs' in kwargs:
import_dirs = kwargs.pop('import_dirs')
if not isinstance(import_dirs, list):
import_dirs = [import_dirs]
import_dir_arg = d_feature_args[self.id]['import_dir']
if not import_dir_arg:
raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string())
for idir_obj in import_dirs:
basedir = idir_obj.get_curdir()
for idir in idir_obj.get_incdirs():
# Avoid superfluous '/.' at the end of paths when d is '.'
if idir not in ('', '.'):
expdir = os.path.join(basedir, idir)
else:
expdir = basedir
srctreedir = os.path.join(build_to_src, expdir)
res.append('{0}{1}'.format(import_dir_arg, srctreedir))
if kwargs:
raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys()))
return res
def get_buildtype_linker_args(self, buildtype):
if buildtype != 'plain':
return self.get_target_arch_args()
return []
def get_std_exe_link_args(self):
return []
def gen_import_library_args(self, implibname):
return ['-Wl,--out-implib=' + implibname]
def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
def build_rpath_args(self, env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
if is_windows():
return []
@ -295,6 +378,11 @@ class DmdLikeCompilerMixin:
assert(buildtype == 'custom')
raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".')
def get_soname_args(self, *args, **kwargs) -> typing.List[str]:
# LDC and DMD actually do use a linker, but they proxy all of that with
# their own arguments
return Compiler.get_soname_args(self, *args, **kwargs)
class DCompiler(Compiler):
mscrt_args = {
@ -337,9 +425,6 @@ class DCompiler(Compiler):
return []
return ['-fPIC']
def get_std_shared_lib_link_args(self):
return ['-shared']
def get_feature_args(self, kwargs, build_to_src):
res = []
if 'unittest' in kwargs:
@ -534,7 +619,7 @@ class GnuDCompiler(DCompiler, GnuCompiler):
return parameter_list
class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
class LLVMDCompiler(DmdLikeCompilerMixin, LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin, DCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs):
DCompiler.__init__(self, exelist, version, for_machine, arch, **kwargs)
self.id = 'llvm'
@ -572,7 +657,7 @@ class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
return ldc_optimization_args[optimization_level]
class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
class DmdDCompiler(DmdLikeCompilerMixin, LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin, DCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs):
DCompiler.__init__(self, exelist, version, for_machine, arch, **kwargs)
self.id = 'dmd'

@ -24,8 +24,7 @@ from .compilers import (
)
from .mixins.clike import CLikeCompiler
from .mixins.gnu import (
GnuCompiler, apple_buildtype_linker_args, gnulike_buildtype_args,
gnulike_buildtype_linker_args, gnu_optimization_args,
GnuCompiler, gnulike_buildtype_args, gnu_optimization_args,
)
from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler
from .mixins.clang import ClangCompiler
@ -101,11 +100,6 @@ class FortranCompiler(CLikeCompiler, Compiler):
def get_debug_args(self, is_debug):
return clike_debug_args[is_debug]
def get_buildtype_linker_args(self, buildtype):
if is_osx():
return apple_buildtype_linker_args[buildtype]
return gnulike_buildtype_linker_args[buildtype]
def get_dependency_gen_args(self, outtarget, outfile):
return []

@ -17,8 +17,9 @@ import os.path, shutil, subprocess
from ..mesonlib import EnvironmentException, MachineChoice
from .compilers import Compiler, java_buildtype_args
from .mixins.islinker import BasicLinkerIsCompilerMixin
class JavaCompiler(Compiler):
class JavaCompiler(BasicLinkerIsCompilerMixin, Compiler):
def __init__(self, exelist, version, for_machine: MachineChoice):
self.language = 'java'
super().__init__(exelist, version, for_machine)
@ -26,24 +27,15 @@ class JavaCompiler(Compiler):
self.is_cross = False
self.javarunner = 'java'
def get_soname_args(self, *args):
return []
def get_werror_args(self):
return ['-Werror']
def split_shlib_to_parts(self, fname):
return None, fname
def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
return []
def get_dependency_gen_args(self, outtarget, outfile):
return []
def get_linker_exelist(self):
return self.exelist[:]
def get_compile_only_args(self):
return []
@ -52,15 +44,9 @@ class JavaCompiler(Compiler):
subdir = './'
return ['-d', subdir, '-s', subdir]
def get_linker_output_args(self, outputname):
return []
def get_coverage_args(self):
return []
def get_coverage_link_args(self):
return []
def get_std_exe_link_args(self):
return []

@ -35,15 +35,6 @@ arm_buildtype_args = {
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
arm_buildtype_linker_args = {
'plain': [],
'debug': [],
'debugoptimized': [],
'release': [],
'minsize': [],
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
arm_optimization_args = {
'0': ['-O0'],
'g': ['-g'],
@ -87,8 +78,6 @@ class ArmCompiler:
# Assembly
self.can_compile_suffixes.add('s')
def can_linker_accept_rsp(self) -> bool:
return False
def get_pic_args(self) -> typing.List[str]:
# FIXME: Add /ropi, /rwpi, /fpic etc. qualifiers to --apcs
@ -97,9 +86,6 @@ class ArmCompiler:
def get_buildtype_args(self, buildtype: str) -> typing.List[str]:
return arm_buildtype_args[buildtype]
def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]:
return arm_buildtype_linker_args[buildtype]
# Override CCompiler.get_always_args
def get_always_args(self) -> typing.List[str]:
return []
@ -108,10 +94,6 @@ class ArmCompiler:
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]:
return []
# Override CCompiler.get_std_shared_lib_link_args
def get_std_shared_lib_link_args(self) -> typing.List[str]:
return []
def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]:
# FIXME: Add required arguments
# NOTE from armcc user guide:
@ -130,19 +112,9 @@ class ArmCompiler:
def thread_flags(self, env: 'Environment') -> typing.List[str]:
return []
def thread_link_flags(self, env: 'Environment') -> typing.List[str]:
return []
def get_linker_exelist(self) -> typing.List[str]:
args = ['armlink']
return args
def get_coverage_args(self) -> typing.List[str]:
return []
def get_coverage_link_args(self) -> typing.List[str]:
return []
def get_optimization_args(self, optimization_level: str) -> typing.List[str]:
return arm_optimization_args[optimization_level]
@ -191,9 +163,6 @@ class ArmclangCompiler:
# Assembly
self.can_compile_suffixes.update('s')
def can_linker_accept_rsp(self) -> bool:
return False
def get_pic_args(self) -> typing.List[str]:
# PIC support is not enabled by default for ARM,
# if users want to use it, they need to add the required arguments explicitly
@ -205,13 +174,6 @@ class ArmclangCompiler:
def get_buildtype_args(self, buildtype: str) -> typing.List[str]:
return armclang_buildtype_args[buildtype]
def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]:
return arm_buildtype_linker_args[buildtype]
# Override CCompiler.get_std_shared_lib_link_args
def get_std_shared_lib_link_args(self) -> typing.List[str]:
return []
def get_pch_suffix(self) -> str:
return 'gch'
@ -225,34 +187,12 @@ class ArmclangCompiler:
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]:
return []
# Override CCompiler.build_rpath_args
def build_rpath_args(self, build_dir: str, from_dir: str, rpath_paths: str,
build_rpath: str, install_rpath: str) -> typing.List[str]:
return []
def get_linker_exelist(self) -> typing.List[str]:
return [self.linker_exe]
def get_optimization_args(self, optimization_level: str) -> typing.List[str]:
return armclang_optimization_args[optimization_level]
def get_debug_args(self, is_debug: bool) -> typing.List[str]:
return clike_debug_args[is_debug]
def gen_export_dynamic_link_args(self, env: 'Environment') -> typing.List[str]:
"""
The args for export dynamic
"""
return ['--export_dynamic']
def gen_import_library_args(self, implibname: str) -> typing.List[str]:
"""
The args of the outputted import library
ArmLinker's symdefs output can be used as implib
"""
return ['--symdefs=' + implibname]
def compute_parameters_with_absolute_paths(self, parameter_list: typing.List[str], build_dir: str) -> typing.List[str]:
for idx, i in enumerate(parameter_list):
if i[:2] == '-I' or i[:2] == '-L':

@ -32,15 +32,6 @@ ccrx_buildtype_args = {
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
ccrx_buildtype_linker_args = {
'plain': [],
'debug': [],
'debugoptimized': [],
'release': [],
'minsize': [],
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
ccrx_optimization_args = {
'0': ['-optimize=0'],
'g': ['-optimize=0'],
@ -60,14 +51,6 @@ class CcrxCompiler:
def __init__(self, compiler_type: 'CompilerType'):
if not self.is_cross:
raise EnvironmentException('ccrx supports only cross-compilation.')
# Check whether 'rlink.exe' is available in path
self.linker_exe = 'rlink.exe'
args = '--version'
try:
p, stdo, stderr = Popen_safe(self.linker_exe, args)
except OSError as e:
err_msg = 'Unknown linker\nRunning "{0}" gave \n"{1}"'.format(' '.join([self.linker_exe] + [args]), e)
raise EnvironmentException(err_msg)
self.id = 'ccrx'
self.compiler_type = compiler_type
# Assembly
@ -78,9 +61,6 @@ class CcrxCompiler:
'2': default_warn_args + [],
'3': default_warn_args + []}
def can_linker_accept_rsp(self) -> bool:
return False
def get_pic_args(self) -> typing.List[str]:
# PIC support is not enabled by default for CCRX,
# if users want to use it, they need to add the required arguments explicitly
@ -89,13 +69,6 @@ class CcrxCompiler:
def get_buildtype_args(self, buildtype: str) -> typing.List[str]:
return ccrx_buildtype_args[buildtype]
def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]:
return ccrx_buildtype_linker_args[buildtype]
# Override CCompiler.get_std_shared_lib_link_args
def get_std_shared_lib_link_args(self) -> typing.List[str]:
return []
def get_pch_suffix(self) -> str:
return 'pch'
@ -106,28 +79,12 @@ class CcrxCompiler:
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]:
return []
# Override CCompiler.build_rpath_args
def build_rpath_args(self, build_dir: str, from_dir: str, rpath_paths: str, build_rpath: str, install_rpath: str) -> typing.List[str]:
return []
def thread_flags(self, env: 'Environment') -> typing.List[str]:
return []
def thread_link_flags(self, env: 'Environment') -> typing.List[str]:
return []
def get_linker_exelist(self) -> typing.List[str]:
return [self.linker_exe]
def get_linker_lib_prefix(self) -> str:
return '-lib='
def get_coverage_args(self) -> typing.List[str]:
return []
def get_coverage_link_args(self) -> typing.List[str]:
return []
def get_optimization_args(self, optimization_level: str) -> typing.List[str]:
return ccrx_optimization_args[optimization_level]

@ -61,9 +61,6 @@ class CLikeCompiler:
else:
self.exe_wrapper = exe_wrapper.get_command()
# Set to None until we actually need to check this
self.has_fatal_warnings_link_arg = None
def needs_static_linker(self):
return True # When compiling static libraries, so yes.
@ -73,13 +70,6 @@ class CLikeCompiler:
'''
return ['-pipe'] + compilers.get_largefile_args(self)
def get_linker_debug_crt_args(self):
"""
Arguments needed to select a debug crt for the linker
This is only needed for MSVC
"""
return []
def get_no_stdinc_args(self):
return ['-nostdinc']
@ -93,22 +83,9 @@ class CLikeCompiler:
# Almost every compiler uses this for disabling warnings
return ['-w']
def get_soname_args(self, *args):
return []
def split_shlib_to_parts(self, fname):
return None, fname
# The default behavior is this, override in MSVC
@functools.lru_cache(maxsize=None)
def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
if self.compiler_type.is_windows_compiler:
return []
return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
def get_dependency_gen_args(self, outtarget, outfile):
return ['-MD', '-MQ', outtarget, '-MF', outfile]
def depfile_for_object(self, objfile):
return objfile + '.' + self.get_depfile_suffix()
@ -118,9 +95,6 @@ class CLikeCompiler:
def get_exelist(self):
return self.exelist[:]
def get_linker_exelist(self):
return self.exelist[:]
def get_preprocess_only_args(self):
return ['-E', '-P']
@ -140,19 +114,17 @@ class CLikeCompiler:
def get_output_args(self, target):
return ['-o', target]
def get_linker_output_args(self, outputname):
return ['-o', outputname]
def get_coverage_args(self):
return ['--coverage']
def get_coverage_link_args(self):
return ['--coverage']
def get_coverage_link_args(self) -> typing.List[str]:
return self.linker.get_coverage_args()
def get_werror_args(self):
return ['-Werror']
def get_std_exe_link_args(self):
# TODO: is this a linker property?
return []
def get_include_args(self, path, is_system):
@ -162,9 +134,6 @@ class CLikeCompiler:
return ['-isystem', path]
return ['-I' + path]
def get_std_shared_lib_link_args(self):
return ['-shared']
def get_compiler_dirs(self, env: 'Environment', name: str) -> typing.List[str]:
'''
Get dirs from the compiler, either `libraries:` or `programs:`
@ -222,27 +191,16 @@ class CLikeCompiler:
return os.path.basename(header_name) + '.' + self.get_pch_suffix()
def get_linker_search_args(self, dirname: str) -> typing.List[str]:
return ['-L' + dirname]
return self.linker.get_search_args(dirname)
def get_default_include_dirs(self):
return []
def gen_export_dynamic_link_args(self, env) -> typing.List[str]:
m = env.machines[self.for_machine]
if m.is_windows() or m.is_cygwin():
return ['-Wl,--export-all-symbols']
elif env.machines[self.for_machine].is_darwin():
return []
else:
return ['-Wl,-export-dynamic']
def gen_export_dynamic_link_args(self, env: 'Environment') -> typing.List[str]:
return self.linker.export_dynamic_args(env)
def gen_import_library_args(self, implibname: str) -> typing.List[str]:
"""
The name of the outputted import library
This implementation is used only on Windows by compilers that use GNU ld
"""
return ['-Wl,--out-implib=' + implibname]
return self.linker.import_library_args(implibname)
def sanity_check_impl(self, work_dir, environment, sname, code):
mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist))
@ -1104,11 +1062,8 @@ class CLikeCompiler:
return []
return ['-pthread']
def thread_link_flags(self, env):
host_m = env.machines[self.for_machine]
if host_m.is_haiku() or host_m.is_darwin():
return []
return ['-pthread']
def thread_link_flags(self, env: 'Environment') -> typing.List[str]:
return self.linker.thread_flags(env)
def linker_to_compiler_args(self, args):
return args
@ -1139,14 +1094,7 @@ class CLikeCompiler:
# First time we check for link flags we need to first check if we have
# --fatal-warnings, otherwise some linker checks could give some
# false positive.
fatal_warnings_args = ['-Wl,--fatal-warnings']
if self.has_fatal_warnings_link_arg is None:
self.has_fatal_warnings_link_arg = False
self.has_fatal_warnings_link_arg = self.has_multi_link_arguments(fatal_warnings_args, env)[0]
if self.has_fatal_warnings_link_arg:
args = fatal_warnings_args + args
args = self.linker.fatal_warnings() + args
args = self.linker_to_compiler_args(args)
code = 'int main() { return 0; }'
return self.has_arguments(args, env, code, mode='link')

@ -46,24 +46,6 @@ gnulike_buildtype_args = {
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
apple_buildtype_linker_args = {
'plain': [],
'debug': [],
'debugoptimized': [],
'release': [],
'minsize': [],
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
gnulike_buildtype_linker_args = {
'plain': [],
'debug': [],
'debugoptimized': [],
'release': ['-Wl,-O1'],
'minsize': [],
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
gnu_optimization_args = {
'0': [],
'g': ['-Og'],
@ -102,35 +84,6 @@ gnu_color_args = {
} # type: typing.Dict[str, typing.List[str]]
def get_macos_dylib_install_name(prefix: str, shlib_name: str, suffix: str, soversion: str) -> str:
install_name = prefix + shlib_name
if soversion is not None:
install_name += '.' + soversion
install_name += '.dylib'
return '@rpath/' + install_name
def get_gcc_soname_args(compiler_type: 'CompilerType', prefix: str,
shlib_name: str, suffix: str, soversion: str, darwin_versions:
typing.Tuple[str, str], is_shared_module: bool) -> typing.List[str]:
if compiler_type.is_standard_compiler:
sostr = '' if soversion is None else '.' + soversion
return ['-Wl,-soname,%s%s.%s%s' % (prefix, shlib_name, suffix, sostr)]
elif compiler_type.is_windows_compiler:
# For PE/COFF the soname argument has no effect with GNU LD
return []
elif compiler_type.is_osx_compiler:
if is_shared_module:
return []
name = get_macos_dylib_install_name(prefix, shlib_name, suffix, soversion)
args = ['-install_name', name]
if darwin_versions:
args += ['-compatibility_version', darwin_versions[0], '-current_version', darwin_versions[1]]
return args
else:
raise RuntimeError('Not implemented yet.')
# TODO: The result from calling compiler should be cached. So that calling this
# function multiple times don't add latency.
def gnulike_default_include_dirs(compiler: typing.List[str], lang: str) -> typing.List[str]:
@ -179,25 +132,13 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
self.compiler_type = compiler_type
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
'b_ndebug', 'b_staticpic', 'b_pie']
if (not self.compiler_type.is_osx_compiler and
not self.compiler_type.is_windows_compiler and
not mesonlib.is_openbsd()):
if not (self.compiler_type.is_windows_compiler or mesonlib.is_openbsd()):
self.base_options.append('b_lundef')
if not self.compiler_type.is_windows_compiler:
self.base_options.append('b_asneeded')
# All GCC-like backends can do assembly
self.can_compile_suffixes.add('s')
def get_asneeded_args(self) -> typing.List[str]:
# GNU ld cannot be installed on macOS
# https://github.com/Homebrew/homebrew-core/issues/17794#issuecomment-328174395
# Hence, we don't need to differentiate between OS and ld
# for the sake of adding as-needed support
if self.compiler_type.is_osx_compiler:
return ['-Wl,-dead_strip_dylibs']
else:
return ['-Wl,--as-needed']
def get_pic_args(self) -> typing.List[str]:
if self.compiler_type.is_osx_compiler or self.compiler_type.is_windows_compiler:
return [] # On Window and OS X, pic is always on.
@ -206,9 +147,6 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
def get_pie_args(self) -> typing.List[str]:
return ['-fPIE']
def get_pie_link_args(self) -> typing.List[str]:
return ['-pie']
def get_buildtype_args(self, buildtype: str) -> typing.List[str]:
return gnulike_buildtype_args[buildtype]
@ -219,11 +157,6 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
def get_debug_args(self, is_debug: bool) -> typing.List[str]:
return clike_debug_args[is_debug]
def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]:
if self.compiler_type.is_osx_compiler:
return apple_buildtype_linker_args[buildtype]
return gnulike_buildtype_linker_args[buildtype]
@abc.abstractmethod
def get_pch_suffix(self) -> str:
raise NotImplementedError("get_pch_suffix not implemented")
@ -231,27 +164,6 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
def split_shlib_to_parts(self, fname: str) -> typing.Tuple[str, str]:
return os.path.dirname(fname), fname
# We're doing argument proxying here, I don't think there's anyway to
# accurately model this without copying the real signature
def get_soname_args(self, *args: typing.Any) -> typing.List[str]:
return get_gcc_soname_args(self.compiler_type, *args)
def get_std_shared_lib_link_args(self) -> typing.List[str]:
return ['-shared']
def get_std_shared_module_link_args(self, options: typing.Dict[str, 'UserOption[typing.Any]']) -> typing.List[str]:
if self.compiler_type.is_osx_compiler:
return ['-bundle', '-Wl,-undefined,dynamic_lookup']
return ['-shared']
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]:
if self.compiler_type.is_osx_compiler:
result = [] # type: typing.List[str]
for a in args:
result += ['-Wl,-force_load', a]
return result
return ['-Wl,--whole-archive'] + args + ['-Wl,--no-whole-archive']
def get_instruction_set_args(self, instruction_set: str) -> typing.Optional[typing.List[str]]:
return gnulike_instruction_set_args.get(instruction_set, None)
@ -284,19 +196,6 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
def get_profile_use_args(self) -> typing.List[str]:
return ['-fprofile-use', '-fprofile-correction']
def get_allow_undefined_link_args(self) -> typing.List[str]:
if self.compiler_type.is_osx_compiler:
# Apple ld
return ['-Wl,-undefined,dynamic_lookup']
elif self.compiler_type.is_windows_compiler:
# For PE/COFF this is impossible
return []
elif mesonlib.is_sunos():
return []
else:
# GNU ld and LLVM lld
return ['-Wl,--allow-shlib-undefined']
def get_gui_app_args(self, value: bool) -> typing.List[str]:
if self.compiler_type.is_windows_compiler:
return ['-mwindows' if value else '-mconsole']
@ -369,9 +268,6 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
def get_lto_compile_args(self) -> typing.List[str]:
return ['-flto']
def get_lto_link_args(self) -> typing.List[str]:
return ['-flto']
def sanitizer_compile_args(self, value: str) -> typing.List[str]:
if value == 'none':
return []
@ -380,10 +276,19 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
args.append('-fno-omit-frame-pointer')
return args
def sanitizer_link_args(self, value: str) -> typing.List[str]:
if value == 'none':
return []
return ['-fsanitize=' + value]
def get_output_args(self, target: str) -> typing.List[str]:
return ['-o', target]
def get_dependency_gen_args(self, outtarget, outfile):
return ['-MD', '-MQ', outtarget, '-MF', outfile]
def get_compile_only_args(self) -> typing.List[str]:
return ['-c']
def get_include_args(self, path: str, is_system: bool) -> typing.List[str]:
if is_system:
return ['-isystem' + path]
return ['-I' + path]
class GnuCompiler(GnuLikeCompiler):

@ -133,8 +133,5 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
version = int(v1 + v2)
return self._calculate_toolset_version(version)
def get_linker_exelist(self) -> typing.List[str]:
return ['xilink']
def openmp_flags(self) -> typing.List[str]:
return ['/Qopenmp']

@ -33,17 +33,7 @@ pgi_buildtype_args = {
} # type: typing.Dict[str, typing.List[str]]
pgi_buildtype_linker_args = {
'plain': [],
'debug': [],
'debugoptimized': [],
'release': [],
'minsize': [],
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
class PGICompiler():
class PGICompiler:
def __init__(self, compiler_type: 'CompilerType'):
self.base_options = ['b_pch']
self.id = 'pgi'
@ -64,14 +54,6 @@ class PGICompiler():
def gen_import_library_args(self, implibname: str) -> typing.List[str]:
return []
def get_std_shared_lib_link_args(self) -> typing.List[str]:
# PGI -shared is Linux only.
if self.compiler_type.is_windows_compiler:
return ['-Bdynamic', '-Mmakedll']
elif not self.compiler_type.is_osx_compiler:
return ['-shared']
return []
def get_pic_args(self) -> typing.List[str]:
# PGI -fPIC is Linux only.
if self.compiler_type.is_linux_compiler():
@ -84,9 +66,6 @@ class PGICompiler():
def get_buildtype_args(self, buildtype: str) -> typing.List[str]:
return pgi_buildtype_args[buildtype]
def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]:
return pgi_buildtype_linker_args[buildtype]
def get_optimization_args(self, optimization_level: str) -> typing.List[str]:
return clike_optimization_args[optimization_level]
@ -99,9 +78,6 @@ class PGICompiler():
parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
return parameter_list
def get_allow_undefined_link_args(self) -> typing.List[str]:
return []
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]:
return []

@ -61,17 +61,6 @@ msvc_buildtype_args = {
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
msvc_buildtype_linker_args = {
'plain': [],
'debug': [],
'debugoptimized': [],
# The otherwise implicit REF and ICF linker optimisations are disabled by
# /DEBUG. REF implies ICF.
'release': ['/OPT:REF'],
'minsize': ['/INCREMENTAL:NO', '/OPT:REF'],
'custom': [],
} # type: typing.Dict[str, typing.List[str]]
msvc_optimization_args = {
'0': [],
'g': ['/O0'],
@ -133,31 +122,18 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
self.machine = 'x86'
else:
self.machine = target
self.linker.machine = self.machine
# Override CCompiler.get_always_args
def get_always_args(self) -> typing.List[str]:
return self.always_args
def get_linker_debug_crt_args(self) -> typing.List[str]:
"""
Arguments needed to select a debug crt for the linker
Sometimes we need to manually select the CRT (C runtime) to use with
MSVC. One example is when trying to link with static libraries since
MSVC won't auto-select a CRT for us in that case and will error out
asking us to select one.
"""
return ['/MDd']
def get_buildtype_args(self, buildtype: str) -> typing.List[str]:
args = msvc_buildtype_args[buildtype]
if self.id == 'msvc' and mesonlib.version_compare(self.version, '<18.0'):
args = [arg for arg in args if arg != '/Gw']
return args
def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]:
return msvc_buildtype_linker_args[buildtype]
def get_pch_suffix(self) -> str:
return 'pch'
@ -197,23 +173,6 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]:
return []
def get_linker_exelist(self) -> typing.List[str]:
# FIXME, should have same path as compiler.
# FIXME, should be controllable via cross-file.
if self.id == 'clang-cl':
return ['lld-link']
else:
return ['link']
def get_linker_always_args(self) -> typing.List[str]:
return ['/nologo']
def get_linker_output_args(self, outputname: str) -> typing.List[str]:
return ['/MACHINE:' + self.machine, '/OUT:' + outputname]
def get_linker_search_args(self, dirname: str) -> typing.List[str]:
return ['/LIBPATH:' + dirname]
def linker_to_compiler_args(self, args: typing.List[str]) -> typing.List[str]:
return ['/link'] + args
@ -228,12 +187,6 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
def get_pic_args(self) -> typing.List[str]:
return [] # PIC is handled by the loader on Windows
def gen_export_dynamic_link_args(self, env: 'Environment') -> typing.List[str]:
return [] # Not applicable with MSVC
def get_std_shared_lib_link_args(self) -> typing.List[str]:
return ['/DLL']
def gen_vs_module_defs_args(self, defsfile: str) -> typing.List[str]:
if not isinstance(defsfile, str):
raise RuntimeError('Module definitions file should be str')
@ -249,9 +202,6 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
"The name of the outputted import library"
return ['/IMPLIB:' + implibname]
def build_rpath_args(self, build_dir: str, from_dir: str, rpath_paths: str, build_rpath: str, install_rpath: str) -> typing.List[str]:
return []
def openmp_flags(self) -> typing.List[str]:
return ['/openmp']
@ -259,9 +209,6 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
def thread_flags(self, env: 'Environment') -> typing.List[str]:
return []
def thread_link_flags(self, env: 'Environment') -> typing.List[str]:
return []
@classmethod
def unix_args_to_native(cls, args: typing.List[str]) -> typing.List[str]:
result = []
@ -331,16 +278,6 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
args = ['/FS'] + args
return args
def get_link_debugfile_args(self, targetfile: str) -> typing.List[str]:
pdbarr = targetfile.split('.')[:-1]
pdbarr += ['pdb']
return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)]
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]:
# Only since VS2015
args = mesonlib.listify(args)
return ['/WHOLEARCHIVE:' + x for x in args]
def get_instruction_set_args(self, instruction_set: str) -> typing.Optional[typing.List[str]]:
if self.is_64:
return vs64_instruction_set_args.get(instruction_set, None)
@ -418,7 +355,3 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
def get_argument_syntax(self) -> str:
return 'msvc'
def get_allow_undefined_link_args(self) -> typing.List[str]:
# link.exe
return ['/FORCE:UNRESOLVED']

@ -13,11 +13,14 @@
# limitations under the License.
import subprocess, os.path
import typing
from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe
from .compilers import Compiler, rust_buildtype_args, clike_debug_args
if typing.TYPE_CHECKING:
from ..environment import Environment # noqa: F401
rust_optimization_args = {'0': [],
'g': ['-C', '--opt-level=0'],
'1': ['-C', '--opt-level=1'],
@ -77,9 +80,6 @@ class RustCompiler(Compiler):
def get_buildtype_args(self, buildtype):
return rust_buildtype_args[buildtype]
def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
def get_sysroot(self):
cmd = self.exelist + ['--print', 'sysroot']
p, stdo, stde = Popen_safe(cmd)
@ -102,8 +102,5 @@ class RustCompiler(Compiler):
return parameter_list
def get_buildtype_linker_args(self, build_type):
return []
def get_std_exe_link_args(self):
return []

@ -34,9 +34,6 @@ class SwiftCompiler(Compiler):
self.id = 'llvm'
self.is_cross = is_cross
def get_linker_exelist(self):
return self.exelist[:]
def name_string(self):
return ' '.join(self.exelist)
@ -58,9 +55,6 @@ class SwiftCompiler(Compiler):
def get_output_args(self, target):
return ['-o', target]
def get_linker_output_args(self, target):
return ['-o', target]
def get_header_import_args(self, headername):
return ['-import-objc-header', headername]
@ -70,9 +64,6 @@ class SwiftCompiler(Compiler):
def get_buildtype_args(self, buildtype):
return swift_buildtype_args[buildtype]
def get_buildtype_linker_args(self, buildtype):
return []
def get_std_exe_link_args(self):
return ['-emit-executable']
@ -82,9 +73,6 @@ class SwiftCompiler(Compiler):
def get_mod_gen_args(self):
return ['-emit-module']
def build_rpath_args(self, *args):
return [] # FIXME
def get_include_args(self, dirname):
return ['-I' + dirname]

@ -54,8 +54,9 @@ class StaticLinker:
def get_coverage_link_args(self) -> typing.List[str]:
return []
def build_rpath_args(self, build_dir: str, from_dir: str, rpath_paths: str,
build_rpath: str, install_rpath: str) -> typing.List[str]:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]:
return []
def thread_link_flags(self, env: 'Environment') -> typing.List[str]:

Loading…
Cancel
Save