From 90e43dbdfe06d062939803ec4ee261315096aee7 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 25 Jul 2019 08:37:30 -0700 Subject: re-architect the D compiler abstractions We support 3 D compilers, DMD, LDC, and GDC. DMD is the reference compiler, and LDC attempts to largely mirror it's command line usage. GDC does not, it instead acts like GCC (which makes sense). The current abstraction puts DMD behavior in the base D compiler and then overrides then in the GnuDCompiler class. This is messy, but it becomes more problematic when splitting the linker and compiler abstractions apart. I've opted to instead split the DCompiler class into two separate classes. The DCompiler implements core D functinoality, and DmdLikeCompilerMixin, which implements the DMD and LDC command line arguments. I've then mxed that into the DmdDCompiler and LLVMDCompiler classes, and mixed the GnuCompiler into the GnuDCompiler class to get Gnu command line behavior. --- mesonbuild/compilers/d.py | 412 ++++++++++++++++++++++------------------------ 1 file changed, 197 insertions(+), 215 deletions(-) (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 1a37c63..27ca6fc 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -27,7 +27,7 @@ from .compilers import ( Compiler, CompilerArgs, ) -from .mixins.gnu import get_gcc_soname_args, gnu_color_args, gnu_optimization_args +from .mixins.gnu import get_gcc_soname_args, GnuCompiler d_feature_args = {'gcc': {'unittest': '-funittest', 'debug': '-fdebug', @@ -62,44 +62,11 @@ dmd_optimization_args = {'0': [], 's': ['-O'], } -class DCompiler(Compiler): - mscrt_args = { - 'none': ['-mscrtlib='], - 'md': ['-mscrtlib=msvcrt'], - 'mdd': ['-mscrtlib=msvcrtd'], - 'mt': ['-mscrtlib=libcmt'], - 'mtd': ['-mscrtlib=libcmtd'], - } - def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs): - self.language = 'd' - super().__init__(exelist, version, for_machine, **kwargs) - self.id = 'unknown' - self.arch = arch - - def sanity_check(self, work_dir, environment): - source_name = os.path.join(work_dir, 'sanity.d') - output_name = os.path.join(work_dir, 'dtest') - with open(source_name, 'w') as ofile: - ofile.write('''void main() { }''') - pc = subprocess.Popen(self.exelist + self.get_output_args(output_name) + self.get_target_arch_args() + [source_name], cwd=work_dir) - pc.wait() - if pc.returncode != 0: - raise EnvironmentException('D compiler %s can not compile programs.' % self.name_string()) - if subprocess.call(output_name) != 0: - raise EnvironmentException('Executables created by D compiler %s are not runnable.' % self.name_string()) - - def needs_static_linker(self): - return True - - def name_string(self): - return ' '.join(self.exelist) - - def get_exelist(self): - return self.exelist +class DmdLikeCompilerMixin: def get_linker_exelist(self): - return self.exelist[:] + return self.get_exelist() def get_output_args(self, target): return ['-of=' + target] @@ -147,20 +114,6 @@ class DCompiler(Compiler): def get_compile_only_args(self): return ['-c'] - 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 [] - return ['-fPIC'] - - def get_std_shared_lib_link_args(self): - return ['-shared'] - def get_soname_args(self, *args): # FIXME: Make this work for cross-compiling if is_windows(): @@ -173,96 +126,6 @@ class DCompiler(Compiler): return get_gcc_soname_args(CompilerType.GCC_STANDARD, *args) - 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)) - - 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] @@ -285,54 +148,6 @@ class DCompiler(Compiler): paths = paths + ':' + padding return ['-Wl,-rpath,{}'.format(paths)] - def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): - if callable(extra_args): - extra_args = extra_args(mode) - if extra_args is None: - extra_args = [] - elif isinstance(extra_args, str): - extra_args = [extra_args] - if dependencies is None: - dependencies = [] - elif not isinstance(dependencies, list): - dependencies = [dependencies] - # Collect compiler arguments - args = CompilerArgs(self) - for d in dependencies: - # Add compile flags needed by dependencies - args += d.get_compile_args() - if mode == 'link': - # Add link flags needed to find dependencies - args += d.get_link_args() - - if mode == 'compile': - # Add DFLAGS from the env - args += env.coredata.get_external_args(self.for_machine, self.language) - elif mode == 'link': - # Add LDFLAGS from the env - args += env.coredata.get_external_link_args(self.for_machine, self.language) - # extra_args must override all other arguments, so we add them last - args += extra_args - return args - - def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile'): - args = self._get_compiler_check_args(env, extra_args, dependencies, mode) - - with self.cached_compile(code, env.coredata, extra_args=args, mode=mode) as p: - return p.returncode == 0, p.cached - - def has_multi_arguments(self, args, env): - return self.compiles('int i;\n', env, extra_args=args) - - def get_target_arch_args(self): - # LDC2 on Windows targets to current OS architecture, but - # it should follow the target specified by the MSVC toolchain. - if is_windows(): - if self.arch == 'x86_64': - return ['-m64'] - return ['-m32'] - return [] - @classmethod def translate_args_to_nongnu(cls, args): dcargs = [] @@ -480,6 +295,189 @@ class DCompiler(Compiler): assert(buildtype == 'custom') raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') + +class DCompiler(Compiler): + mscrt_args = { + 'none': ['-mscrtlib='], + 'md': ['-mscrtlib=msvcrt'], + 'mdd': ['-mscrtlib=msvcrtd'], + 'mt': ['-mscrtlib=libcmt'], + 'mtd': ['-mscrtlib=libcmtd'], + } + + def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs): + self.language = 'd' + super().__init__(exelist, version, for_machine, **kwargs) + self.id = 'unknown' + self.arch = arch + + def sanity_check(self, work_dir, environment): + source_name = os.path.join(work_dir, 'sanity.d') + output_name = os.path.join(work_dir, 'dtest') + with open(source_name, 'w') as ofile: + ofile.write('''void main() { }''') + pc = subprocess.Popen(self.exelist + self.get_output_args(output_name) + self.get_target_arch_args() + [source_name], cwd=work_dir) + pc.wait() + if pc.returncode != 0: + raise EnvironmentException('D compiler %s can not compile programs.' % self.name_string()) + if subprocess.call(output_name) != 0: + raise EnvironmentException('Executables created by D compiler %s are not runnable.' % self.name_string()) + + def needs_static_linker(self): + return True + + 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 [] + 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: + 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)) + + 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 _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): + if callable(extra_args): + extra_args = extra_args(mode) + if extra_args is None: + extra_args = [] + elif isinstance(extra_args, str): + extra_args = [extra_args] + if dependencies is None: + dependencies = [] + elif not isinstance(dependencies, list): + dependencies = [dependencies] + # Collect compiler arguments + args = CompilerArgs(self) + for d in dependencies: + # Add compile flags needed by dependencies + args += d.get_compile_args() + if mode == 'link': + # Add link flags needed to find dependencies + args += d.get_link_args() + + if mode == 'compile': + # Add DFLAGS from the env + args += env.coredata.get_external_args(self.for_machine, self.language) + elif mode == 'link': + # Add LDFLAGS from the env + args += env.coredata.get_external_link_args(self.for_machine, self.language) + # extra_args must override all other arguments, so we add them last + args += extra_args + return args + + def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile'): + args = self._get_compiler_check_args(env, extra_args, dependencies, mode) + + with self.cached_compile(code, env.coredata, extra_args=args, mode=mode) as p: + return p.returncode == 0, p.cached + + def has_multi_arguments(self, args, env): + return self.compiles('int i;\n', env, extra_args=args) + + def get_target_arch_args(self): + # LDC2 on Windows targets to current OS architecture, but + # it should follow the target specified by the MSVC toolchain. + if is_windows(): + if self.arch == 'x86_64': + return ['-m64'] + return ['-m32'] + return [] + def get_crt_compile_args(self, crt_val, buildtype): return [] @@ -489,7 +487,11 @@ class DCompiler(Compiler): def thread_link_flags(self, env): return ['-pthread'] -class GnuDCompiler(DCompiler): + def name_string(self): + return ' '.join(self.exelist) + + +class GnuDCompiler(DCompiler, GnuCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs): DCompiler.__init__(self, exelist, version, for_machine, arch, **kwargs) self.id = 'gcc' @@ -507,32 +509,17 @@ class GnuDCompiler(DCompiler): def get_colorout_args(self, colortype): if self._has_color_support: - return gnu_color_args[colortype][:] + super().get_colorout_args(colortype) return [] def get_dependency_gen_args(self, outtarget, outfile): - if not self._has_deps_support: - return [] - return ['-MD', '-MQ', outtarget, '-MF', outfile] - - def get_output_args(self, target): - return ['-o', target] - - def get_linker_output_args(self, target): - return ['-o', target] - - def get_include_args(self, path, is_system): - return ['-I' + path] + if self._has_deps_support: + return super().get_dependency_gen_args(outtarget, outfile) + return [] def get_warn_args(self, level): return self.warn_args[level] - def get_werror_args(self): - return ['-Werror'] - - def get_linker_search_args(self, dirname): - return ['-L' + dirname] - def get_coverage_args(self): return [] @@ -546,13 +533,8 @@ class GnuDCompiler(DCompiler): return parameter_list - 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_optimization_args(self, optimization_level): - return gnu_optimization_args[optimization_level] -class LLVMDCompiler(DCompiler): +class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs): DCompiler.__init__(self, exelist, version, for_machine, arch, **kwargs) self.id = 'llvm' @@ -590,7 +572,7 @@ class LLVMDCompiler(DCompiler): return ldc_optimization_args[optimization_level] -class DmdDCompiler(DCompiler): +class DmdDCompiler(DmdLikeCompilerMixin, DCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs): DCompiler.__init__(self, exelist, version, for_machine, arch, **kwargs) self.id = 'dmd' -- cgit v1.1 From f5f7a7bbb327dce7e82c830087f6fa6ef78a3a6e Mon Sep 17 00:00:00 2001 From: "Michael Hirsch, Ph.D" Date: Thu, 1 Aug 2019 01:20:07 -0400 Subject: compilers/mixins/pgi: simplify pic logic --- mesonbuild/compilers/mixins/pgi.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py index 0613e79..ff2e9bf 100644 --- a/mesonbuild/compilers/mixins/pgi.py +++ b/mesonbuild/compilers/mixins/pgi.py @@ -74,9 +74,9 @@ class PGICompiler(): def get_pic_args(self) -> typing.List[str]: # PGI -fPIC is Linux only. - if self.compiler_type.is_osx_compiler or self.compiler_type.is_windows_compiler: - return [] - return ['-fPIC'] + if self.compiler_type.is_linux_compiler(): + return ['-fPIC'] + return [] def openmp_flags(self) -> typing.List[str]: return ['-mp'] -- cgit v1.1 From 499c44dc77c2d4a2c649830555cd9257d285bba6 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 23 Jul 2019 15:50:45 -0700 Subject: compilers/cuda: don't use re for replacement Even with the check (for extra safety) string.replace is more than twice as fast. --- mesonbuild/compilers/cuda.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 152c8ba..ffd60f3 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -12,13 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -import re, os.path +import os.path from .. import mlog from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args, cuda_debug_args, CompilerType) -from .mixins.gnu import get_gcc_soname_args class CudaCompiler(Compiler): def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None): @@ -165,7 +164,7 @@ class CudaCompiler(Compiler): Converts GNU-style arguments -Wl,-arg,-arg to NVCC-style arguments -Xlinker=-arg,-arg """ - return [re.sub('^-Wl,', '-Xlinker=', arg) for arg in args] + 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] -- cgit v1.1 From e7db288e19ad262a48403524c6319a6b0266e06f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 17 Jul 2019 10:05:03 -0700 Subject: compilers/objc[pp]: Pass extra keyword arguments to Compiler constructor --- mesonbuild/compilers/objc.py | 12 ++++++------ mesonbuild/compilers/objcpp.py | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py index b9ce0b1..7a778d7 100644 --- a/mesonbuild/compilers/objc.py +++ b/mesonbuild/compilers/objc.py @@ -23,9 +23,9 @@ from .mixins.gnu import GnuCompiler from .mixins.clang import ClangCompiler class ObjCCompiler(CLikeCompiler, Compiler): - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap: typing.Optional[str]): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap: typing.Optional[str], **kwargs): self.language = 'objc' - Compiler.__init__(self, exelist, version, for_machine) + Compiler.__init__(self, exelist, version, for_machine, **kwargs) CLikeCompiler.__init__(self, is_cross, exe_wrap) def get_display_language(self): @@ -57,8 +57,8 @@ class ObjCCompiler(CLikeCompiler, Compiler): class GnuObjCCompiler(GnuCompiler, ObjCCompiler): - def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None): - ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None, **kwargs): + ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) GnuCompiler.__init__(self, compiler_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -68,8 +68,8 @@ class GnuObjCCompiler(GnuCompiler, ObjCCompiler): class ClangObjCCompiler(ClangCompiler, ObjCCompiler): - def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None): - ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): + ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) ClangCompiler.__init__(self, compiler_type) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py index a090bed..70a86c5 100644 --- a/mesonbuild/compilers/objcpp.py +++ b/mesonbuild/compilers/objcpp.py @@ -23,9 +23,9 @@ from .mixins.gnu import GnuCompiler from .mixins.clang import ClangCompiler class ObjCPPCompiler(CLikeCompiler, Compiler): - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap: typing.Optional[str]): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap: typing.Optional[str], **kwargs): self.language = 'objcpp' - Compiler.__init__(self, exelist, version, for_machine) + Compiler.__init__(self, exelist, version, for_machine, **kwargs) CLikeCompiler.__init__(self, is_cross, exe_wrap) def get_display_language(self): @@ -58,8 +58,8 @@ class ObjCPPCompiler(CLikeCompiler, Compiler): class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler): - def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None): - ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None, **kwargs): + ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) GnuCompiler.__init__(self, compiler_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'0': [], @@ -69,8 +69,8 @@ class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler): class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler): - def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None): - ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): + ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) ClangCompiler.__init__(self, compiler_type) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'0': [], -- cgit v1.1 From b5c76a6c02c235d971069965b1f75765c09bdf5f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 7 Aug 2019 11:42:48 -0700 Subject: compilers/fortran: fix ifort (linux, mac) dependency generation Ifort can generate dependency information (.d files), it just does it differently than GNU compilers do. This also fixes a bug caused by adding the dependency generation commands to the GNULike class later in this series. --- mesonbuild/compilers/fortran.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index c10e2ca..3eb8f2e 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -11,9 +11,11 @@ # 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 pathlib import Path from typing import List import subprocess, os -from pathlib import Path +import typing from .compilers import ( CompilerType, @@ -256,6 +258,10 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler): def language_stdlib_only_link_flags(self): return ['-lifcore', '-limf'] + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]: + return ['-gen-dep=' + outtarget, '-gen-depformat=make'] + + class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler): file_suffixes = ['f90', 'f', 'for', 'ftn', 'fpp'] -- cgit v1.1 From 1f66e6708bdaa1c1eaa761f8aa6286d001a73bdf Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 17 Jul 2019 10:42:06 -0700 Subject: compilers/swift: Pass extra args to the Compiler constructor --- mesonbuild/compilers/swift.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py index 0038264..b979d2d 100644 --- a/mesonbuild/compilers/swift.py +++ b/mesonbuild/compilers/swift.py @@ -27,9 +27,9 @@ swift_optimization_args = {'0': [], } class SwiftCompiler(Compiler): - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, **kwargs): self.language = 'swift' - super().__init__(exelist, version, for_machine) + super().__init__(exelist, version, for_machine, **kwargs) self.version = version self.id = 'llvm' self.is_cross = is_cross -- cgit v1.1 From 61255eca1668d283114a45a166ddc0b2d13e56f9 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 23 Jul 2019 15:42:14 -0700 Subject: compilers/cuda: pass through extra kwargs --- mesonbuild/compilers/cuda.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index ffd60f3..a121264 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -20,10 +20,10 @@ from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args, cuda_debug_args, CompilerType) class CudaCompiler(Compiler): - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): if not hasattr(self, 'language'): self.language = 'cuda' - super().__init__(exelist, version, for_machine) + super().__init__(exelist, version, for_machine, **kwargs) self.is_cross = is_cross self.exe_wrapper = exe_wrapper self.id = 'nvcc' -- cgit v1.1 From 16e04a9bde9135dc4e28c69fbc063a659f338bab Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 23 Jul 2019 16:09:12 -0700 Subject: compilers/fortran: Make ifort (windows) proxy extra args to Compiler --- mesonbuild/compilers/fortran.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 3eb8f2e..48c324f 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -276,8 +276,8 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler): 'custom': [], } - def __init__(self, exelist, for_machine: MachineChoice, version, is_cross, target: str, exe_wrapper=None): - FortranCompiler.__init__(self, exelist, for_machine, version, is_cross, exe_wrapper) + def __init__(self, exelist, for_machine: MachineChoice, version, is_cross, target: str, exe_wrapper=None, **kwargs): + FortranCompiler.__init__(self, exelist, for_machine, version, is_cross, exe_wrapper, **kwargs) IntelVisualStudioLikeCompiler.__init__(self, target) default_warn_args = ['/warn:general', '/warn:truncated_source'] -- cgit v1.1 From 18b1bf9292fc27910a52c6512b33a40e4b80b927 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 22 Jul 2019 15:20:56 -0700 Subject: compilers: Make MSVClike compilers proxy extra keyword arguments --- mesonbuild/compilers/c.py | 12 ++++++------ mesonbuild/compilers/cpp.py | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index f50b77c..589857e 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -293,14 +293,14 @@ class VisualStudioLikeCCompilerMixin: class VisualStudioCCompiler(VisualStudioLikeCompiler, VisualStudioLikeCCompilerMixin, CCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target: str): - CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target: str, **kwargs): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap, **kwargs) VisualStudioLikeCompiler.__init__(self, target) self.id = 'msvc' class ClangClCCompiler(VisualStudioLikeCompiler, VisualStudioLikeCCompilerMixin, CCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target): - CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target, **kwargs): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap, **kwargs) VisualStudioLikeCompiler.__init__(self, target) self.id = 'clang-cl' @@ -311,8 +311,8 @@ class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerM __have_warned = False - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target): - CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target, **kwargs): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap, **kwargs) IntelVisualStudioLikeCompiler.__init__(self, target) def get_options(self): diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 5808b2e..f942114 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -473,8 +473,8 @@ class CPP11AsCPP14Mixin: class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, VisualStudioLikeCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap, target): - CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap, target, **kwargs): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap, **kwargs) VisualStudioLikeCompiler.__init__(self, target) self.base_options = ['b_pch', 'b_vscrt'] # FIXME add lto, pgo and the like self.id = 'msvc' @@ -506,8 +506,8 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi return args class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, VisualStudioLikeCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target): - CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target, **kwargs): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap, **kwargs) VisualStudioLikeCompiler.__init__(self, target) self.id = 'clang-cl' @@ -518,8 +518,8 @@ class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, Vi class IntelClCPPCompiler(VisualStudioLikeCPPCompilerMixin, IntelVisualStudioLikeCompiler, CPPCompiler): - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target): - CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target, **kwargs): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap, **kwargs) IntelVisualStudioLikeCompiler.__init__(self, target) def get_options(self): -- cgit v1.1 From b0f4ee2f949bdf795b2126bc59e952efbc0653b0 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 24 Jul 2019 10:46:44 -0700 Subject: compilers/rust: Proxy extra kwargs to Compiler.__init__ --- mesonbuild/compilers/rust.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 332cee6..c482e77 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -27,9 +27,9 @@ rust_optimization_args = {'0': [], } class RustCompiler(Compiler): - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): self.language = 'rust' - super().__init__(exelist, version, for_machine) + super().__init__(exelist, version, for_machine, **kwargs) self.exe_wrapper = exe_wrapper self.id = 'rustc' self.is_cross = is_cross -- cgit v1.1 From 38d588bc6e314d50b54313ffa9454416a00f05b5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 18 Jul 2019 10:21:56 -0700 Subject: compilers/mixins: Add a module for mixins for compilers that are linkers This is currently meant to solve problems for D's DMD compiler, however it may be useful in other cases. --- mesonbuild/compilers/mixins/islinker.py | 124 ++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 mesonbuild/compilers/mixins/islinker.py (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/mixins/islinker.py b/mesonbuild/compilers/mixins/islinker.py new file mode 100644 index 0000000..4c1a476 --- /dev/null +++ b/mesonbuild/compilers/mixins/islinker.py @@ -0,0 +1,124 @@ +# Copyright 2019 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. + +"""Mixins for compilers that *are* linkers. + +While many compilers (such as gcc and clang) are used by meson to dispatch +linker commands and other (like MSVC) are not, a few (such as DMD) actually +are both the linker and compiler in one binary. This module provides mixin +classes for those cases. +""" + +import os +import shlex +import typing + +from ... import mesonlib + +if typing.TYPE_CHECKING: + from ...coredata import OptionDictType + from ...environment import Environment + + +class LinkerEnvVarsMixin: + + """Mixin reading LDFLAGS from the environment.""" + + def get_linker_args_from_envvars(self) -> typing.List[str]: + flags = os.environ.get('LDFLAGS') + if not flags: + return [] + return shlex.split(flags) + + +class BasicLinkerIsCompilerMixin: + + """Provides a baseline of methods that a linker would implement. + + In every case this provides a "no" or "empty" answer. If a compiler + implements any of these it needs a different mixin or to override that + functionality itself. + """ + + def sanitizer_link_args(self, value: str) -> typing.List[str]: + return [] + + def get_lto_link_args(self) -> typing.List[str]: + return [] + + def can_linker_accept_rsp(self) -> bool: + return mesonlib.is_windows() + + def get_linker_exelist(self) -> typing.List[str]: + return self.exelist.copy() + + def get_linker_output_args(self, output: str) -> typing.List[str]: + return [] + + def get_linker_always_args(self) -> typing.List[str]: + return [] + + def get_linker_lib_prefix(self) -> str: + return '' + + def get_option_link_args(self, options: 'OptionDictType') -> typing.List[str]: + return [] + + def has_multi_link_args(self, args: typing.List[str], env: 'Environment') -> typing.Tuple[bool, bool]: + return False, False + + def get_link_debugfile_args(self, targetfile: str) -> typing.List[str]: + return [] + + def get_std_shared_lib_link_args(self) -> typing.List[str]: + return [] + + def get_std_shared_module_args(self, options: 'OptionDictType') -> typing.List[str]: + return self.get_std_shared_lib_link_args() + + def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]: + raise mesonlib.EnvironmentException( + 'Linker {} does not support link_whole'.format(self.id)) + + def get_allow_undefined_args(self) -> typing.List[str]: + raise mesonlib.EnvironmentException( + 'Linker {} does not support allow undefined'.format(self.id)) + + def get_pie_link_args(self) -> typing.List[str]: + m = 'Linker {} does not support position-independent executable' + raise mesonlib.EnvironmentException(m.format(self.id)) + + def get_undefined_link_args(self) -> typing.List[str]: + return [] + + def get_coverage_link_args(self) -> typing.List[str]: + m = "Linker {} doesn't implement coverage data generation.".format(self.id) + raise mesonlib.EnvironmentException(m) + + def no_undefined_link_args(self) -> typing.List[str]: + return [] + + def bitcode_args(self) -> typing.List[str]: + raise mesonlib.MesonException("This linker doesn't support bitcode bundles") + + def get_soname_args(self, for_machine: 'mesonlib.MachineChoice', + prefix: str, shlib_name: str, suffix: str, soversion: str, + darwin_versions: typing.Tuple[str, str], + is_shared_module: bool) -> typing.List[str]: + raise mesonlib.MesonException("This linker doesn't support soname 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 [] -- cgit v1.1 From 06dcbd50eea47b3182081527ea1c0ada01d4d847 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 9 Aug 2019 13:46:35 -0700 Subject: compilers: Dispatch to dynamic linker class Most of the cuda code is from Olexa Bilaniuk. Most of the PGI code is from Michael Hirsc --- mesonbuild/compilers/__init__.py | 3 +- mesonbuild/compilers/c.py | 24 +-- mesonbuild/compilers/compilers.py | 264 +++++++++++----------------- mesonbuild/compilers/cpp.py | 18 +- mesonbuild/compilers/cs.py | 16 +- mesonbuild/compilers/cuda.py | 58 +++--- mesonbuild/compilers/d.py | 131 +++++++++++--- mesonbuild/compilers/fortran.py | 8 +- mesonbuild/compilers/java.py | 18 +- mesonbuild/compilers/mixins/arm.py | 60 ------- mesonbuild/compilers/mixins/ccrx.py | 43 ----- mesonbuild/compilers/mixins/clike.py | 72 ++------ mesonbuild/compilers/mixins/gnu.py | 123 ++----------- mesonbuild/compilers/mixins/intel.py | 3 - mesonbuild/compilers/mixins/pgi.py | 26 +-- mesonbuild/compilers/mixins/visualstudio.py | 69 +------- mesonbuild/compilers/rust.py | 11 +- mesonbuild/compilers/swift.py | 12 -- 18 files changed, 273 insertions(+), 686 deletions(-) (limited to 'mesonbuild/compilers') diff --git a/mesonbuild/compilers/__init__.py b/mesonbuild/compilers/__init__.py index 5cd56b8..c81fe75 100644 --- a/mesonbuild/compilers/__init__.py +++ b/mesonbuild/compilers/__init__.py @@ -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 diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 589857e..1ec9146 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -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'] diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 5249068..f16e447 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -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 diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index f942114..f93db3e 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -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 [] diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py index 8069ab1..7c884c9 100644 --- a/mesonbuild/compilers/cs.py +++ b/mesonbuild/compilers/cs.py @@ -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', diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index a121264..b6bafe7 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -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 [] diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 27ca6fc..18e3bf9 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -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' diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 48c324f..30ec6fe 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -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 [] diff --git a/mesonbuild/compilers/java.py b/mesonbuild/compilers/java.py index ea1fa0f..fb1a190 100644 --- a/mesonbuild/compilers/java.py +++ b/mesonbuild/compilers/java.py @@ -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 [] diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py index 02654ce..fca3d66 100644 --- a/mesonbuild/compilers/mixins/arm.py +++ b/mesonbuild/compilers/mixins/arm.py @@ -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': diff --git a/mesonbuild/compilers/mixins/ccrx.py b/mesonbuild/compilers/mixins/ccrx.py index 0e435e3..d154111 100644 --- a/mesonbuild/compilers/mixins/ccrx.py +++ b/mesonbuild/compilers/mixins/ccrx.py @@ -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] diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 37d2424..3af1768 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -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') diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 9756604..757dc65 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -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): diff --git a/mesonbuild/compilers/mixins/intel.py b/mesonbuild/compilers/mixins/intel.py index 7fadb50..d7e1b21 100644 --- a/mesonbuild/compilers/mixins/intel.py +++ b/mesonbuild/compilers/mixins/intel.py @@ -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'] diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py index ff2e9bf..c13c7bc 100644 --- a/mesonbuild/compilers/mixins/pgi.py +++ b/mesonbuild/compilers/mixins/pgi.py @@ -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 [] diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index edb104d..5fe8599 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -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'] diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index c482e77..cecbe64 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -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 [] diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py index b979d2d..6c639fd 100644 --- a/mesonbuild/compilers/swift.py +++ b/mesonbuild/compilers/swift.py @@ -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] -- cgit v1.1