diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2018-08-27 22:30:23 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-27 22:30:23 +0300 |
commit | 1ffc8de5e8cc79dbaa54fd1ac02b6b4c5edac7a1 (patch) | |
tree | 916eb6a1c988386d9848115709dd9c6b199a5a5a /mesonbuild | |
parent | 731906504efb57aa9ae86685501f1d3a0aa22121 (diff) | |
parent | fd2c3b4c77ac1977d254301876525f8e631a940a (diff) | |
download | meson-1ffc8de5e8cc79dbaa54fd1ac02b6b4c5edac7a1.zip meson-1ffc8de5e8cc79dbaa54fd1ac02b6b4c5edac7a1.tar.gz meson-1ffc8de5e8cc79dbaa54fd1ac02b6b4c5edac7a1.tar.bz2 |
Merge pull request #3981 from GoaLitiuM/d-win-fixes
Fix D support on Windows
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 2 | ||||
-rw-r--r-- | mesonbuild/build.py | 2 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 21 | ||||
-rw-r--r-- | mesonbuild/compilers/d.py | 126 | ||||
-rw-r--r-- | mesonbuild/environment.py | 27 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 2 | ||||
-rw-r--r-- | mesonbuild/linkers.py | 49 |
7 files changed, 202 insertions, 27 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 83bff8a..acbeed3 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2374,7 +2374,7 @@ rule FORTRAN_DEP_HACK%s # options passed on the command-line, in default_options, etc. # These have the lowest priority. if not isinstance(target, build.StaticLibrary): - commands += compilers.get_base_link_args(self.environment.coredata.base_options, + commands += compilers.get_base_link_args(self.get_base_options_for_target(target), linker, isinstance(target, build.SharedModule)) # Add -nostdlib if needed; can't be overridden diff --git a/mesonbuild/build.py b/mesonbuild/build.py index caaadd8..b34ae2f 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1088,7 +1088,7 @@ You probably should put it in link_with instead.''') ''' linker, _ = self.get_clink_dynamic_linker_and_stdlibs() # Mixing many languages with MSVC is not supported yet so ignore stdlibs. - if linker and linker.get_id() == 'msvc': + if linker and linker.get_id() in ['msvc', 'llvm', 'dmd']: return True return False diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 95f937d..352c49e 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -196,22 +196,22 @@ rust_buildtype_args = {'plain': [], d_gdc_buildtype_args = {'plain': [], 'debug': [], - 'debugoptimized': ['-O'], - 'release': ['-O3', '-frelease'], + 'debugoptimized': ['-finline-functions'], + 'release': ['-frelease', '-finline-functions'], 'minsize': [], } d_ldc_buildtype_args = {'plain': [], 'debug': [], - 'debugoptimized': ['-O'], - 'release': ['-O3', '-release'], + 'debugoptimized': ['-enable-inlining', '-Hkeep-all-bodies'], + 'release': ['-release', '-enable-inlining', '-Hkeep-all-bodies'], 'minsize': [], } d_dmd_buildtype_args = {'plain': [], 'debug': [], - 'debugoptimized': ['-O'], - 'release': ['-O', '-release'], + 'debugoptimized': ['-inline'], + 'release': ['-release', '-inline'], 'minsize': [], } @@ -459,6 +459,15 @@ def get_base_link_args(options, linker, is_shared_module): elif as_needed: # -Wl,-dead_strip_dylibs is incompatible with bitcode args.append(linker.get_asneeded_args()) + try: + crt_val = options['b_vscrt'].value + buildtype = options['buildtype'].value + try: + args += linker.get_crt_link_args(crt_val, buildtype) + except AttributeError: + pass + except KeyError: + pass return args class CrossNoRunException(MesonException): diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index c8cc6b0..a03af3e 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -62,20 +62,27 @@ dmd_optimization_args = {'0': [], } class DCompiler(Compiler): - def __init__(self, exelist, version, is_cross, **kwargs): + mscrt_args = { + 'none': ['-mscrtlib='], + 'md': ['-mscrtlib=msvcrt'], + 'mdd': ['-mscrtlib=msvcrtd'], + 'mt': ['-mscrtlib=libcmt'], + 'mtd': ['-mscrtlib=libcmtd'], + } + + def __init__(self, exelist, version, is_cross, is_64, **kwargs): self.language = 'd' super().__init__(exelist, version, **kwargs) self.id = 'unknown' self.is_cross = is_cross + self.is_64 = is_64 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) + [source_name], cwd=work_dir) + 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()) @@ -104,6 +111,8 @@ class DCompiler(Compiler): return 'deps' def get_pic_args(self): + if is_windows(): + return [] return ['-fPIC'] def get_std_shared_lib_link_args(self): @@ -166,12 +175,20 @@ class DCompiler(Compiler): 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): + if is_windows(): + return [] + # This method is to be used by LDC and DMD. # GDC can deal with the verbatim flags. if not rpath_paths and not install_rpath: @@ -224,6 +241,15 @@ class DCompiler(Compiler): 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.is_64: + return ['-m64'] + return ['-m32'] + return [] + @classmethod def translate_args_to_nongnu(cls, args): dcargs = [] @@ -237,6 +263,10 @@ class DCompiler(Compiler): if arg.startswith('-Wl,'): linkargs = arg[arg.index(',') + 1:].split(',') for la in linkargs: + if la.startswith('--out-implib='): + # Import library name for MSVC targets + dcargs.append('-L/IMPLIB:' + la[13:].strip()) + continue dcargs.append('-L' + la.strip()) continue elif arg.startswith('-install_name'): @@ -264,6 +294,22 @@ class DCompiler(Compiler): # a linker search path. dcargs.append('-L' + arg) continue + elif arg.startswith('-mscrtlib='): + mscrtlib = arg[10:].lower() + + if cls is LLVMDCompiler: + # Default crt libraries for LDC2 must be excluded for other + # selected crt options. + if mscrtlib != 'libcmt': + dcargs.append('-L/NODEFAULTLIB:libcmt') + dcargs.append('-L/NODEFAULTLIB:libvcruntime') + + # Fixes missing definitions for printf-functions in VS2017 + if mscrtlib.startswith('msvcrt'): + dcargs.append('-L/DEFAULTLIB:legacy_stdio_definitions.lib') + + dcargs.append(arg) + continue dcargs.append(arg) return dcargs @@ -271,15 +317,44 @@ class DCompiler(Compiler): def get_debug_args(self, is_debug): return clike_debug_args[is_debug] + def get_crt_args(self, crt_val, buildtype): + if not is_windows(): + return [] + + if crt_val in self.mscrt_args: + return self.mscrt_args[crt_val] + assert(crt_val == 'from_buildtype') + + # Match what build type flags used to do. + if buildtype == 'plain': + return [] + elif buildtype == 'debug': + return self.mscrt_args['mdd'] + elif buildtype == 'debugoptimized': + return self.mscrt_args['md'] + elif buildtype == 'release': + return self.mscrt_args['md'] + elif buildtype == 'minsize': + return self.mscrt_args['md'] + else: + assert(buildtype == 'custom') + raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') + + def get_crt_compile_args(self, crt_val, buildtype): + return [] + + def get_crt_link_args(self, crt_val, buildtype): + return [] + class GnuDCompiler(DCompiler): - def __init__(self, exelist, version, is_cross, **kwargs): - DCompiler.__init__(self, exelist, version, is_cross, **kwargs) + def __init__(self, exelist, version, is_cross, is_64, **kwargs): + DCompiler.__init__(self, exelist, version, is_cross, is_64, **kwargs) self.id = 'gcc' default_warn_args = ['-Wall', '-Wdeprecated'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} - self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic'] + self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic', 'b_vscrt'] self._has_color_support = version_compare(self.version, '>=4.9') # dependencies were implemented before, but broken - support was fixed in GCC 7.1+ @@ -324,10 +399,10 @@ class GnuDCompiler(DCompiler): return gnu_optimization_args[optimization_level] class LLVMDCompiler(DCompiler): - def __init__(self, exelist, version, is_cross, **kwargs): - DCompiler.__init__(self, exelist, version, is_cross, **kwargs) + def __init__(self, exelist, version, is_cross, is_64, **kwargs): + DCompiler.__init__(self, exelist, version, is_cross, is_64, **kwargs) self.id = 'llvm' - self.base_options = ['b_coverage', 'b_colorout'] + self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt'] def get_colorout_args(self, colortype): if colortype == 'always': @@ -361,6 +436,8 @@ class LLVMDCompiler(DCompiler): return ['-cov'] def get_buildtype_args(self, buildtype): + if buildtype != 'plain': + return self.get_target_arch_args() + d_ldc_buildtype_args[buildtype] return d_ldc_buildtype_args[buildtype] def get_pic_args(self): @@ -372,6 +449,9 @@ class LLVMDCompiler(DCompiler): # -L is for the compiler, telling it to pass the second -L to the linker. return ['-L-L' + dirname] + def get_crt_link_args(self, crt_val, buildtype): + return self.get_crt_args(crt_val, buildtype) + @classmethod def unix_args_to_native(cls, args): return cls.translate_args_to_nongnu(args) @@ -381,10 +461,11 @@ class LLVMDCompiler(DCompiler): class DmdDCompiler(DCompiler): - def __init__(self, exelist, version, is_cross, **kwargs): - DCompiler.__init__(self, exelist, version, is_cross, **kwargs) + def __init__(self, exelist, version, is_cross, is_64, **kwargs): + DCompiler.__init__(self, exelist, version, is_cross, is_64, **kwargs) self.id = 'dmd' - self.base_options = ['b_coverage', 'b_colorout'] + self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt'] + self.is_msvc = 'VCINSTALLDIR' in os.environ def get_colorout_args(self, colortype): if colortype == 'always': @@ -421,11 +502,28 @@ class DmdDCompiler(DCompiler): return ['-L-L' + dirname] def get_buildtype_args(self, buildtype): + if buildtype != 'plain': + return self.get_target_arch_args() + d_dmd_buildtype_args[buildtype] return d_dmd_buildtype_args[buildtype] def get_std_shared_lib_link_args(self): return ['-shared', '-defaultlib=libphobos2.so'] + def get_target_arch_args(self): + # DMD32 and DMD64 on 64-bit Windows defaults to 32-bit (OMF). + # Force the target to 64-bit in order to stay consistent + # across the different platforms. + if is_windows(): + if self.is_64: + return ['-m64'] + elif self.is_msvc: + return ['-m32mscoff'] + return ['-m32'] + return [] + + def get_crt_compile_args(self, crt_val, buildtype): + return self.get_crt_args(crt_val, buildtype) + @classmethod def unix_args_to_native(cls, args): return cls.translate_args_to_nongnu(args) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index a5586dd..38f66e9 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -15,7 +15,7 @@ import configparser, os, platform, re, shlex, shutil, subprocess from . import coredata -from .linkers import ArLinker, ArmarLinker, VisualStudioLinker +from .linkers import ArLinker, ArmarLinker, VisualStudioLinker, LDCLinker from . import mesonlib from .mesonlib import EnvironmentException, Popen_safe from . import mlog @@ -341,6 +341,7 @@ class Environment: self.vs_static_linker = ['lib'] self.gcc_static_linker = ['gcc-ar'] self.clang_static_linker = ['llvm-ar'] + self.ldc2_static_linker = ['ldc2'] # Various prefixes and suffixes for import libraries, shared libraries, # static libraries, and executables. @@ -839,12 +840,23 @@ This is probably wrong, it should always point to the native compiler.''' % evar raise EnvironmentException('Could not execute D compiler "%s"' % ' '.join(exelist)) version = search_version(out) full_version = out.split('\n', 1)[0] + + # Detect which MSVC build environment is currently active. + is_64 = False + c_compiler = {} + if mesonlib.is_windows() and 'VCINSTALLDIR' in os.environ: + # MSVC compiler is required for correct platform detection. + c_compiler = {'c': self.detect_c_compiler(want_cross)} + + if detect_cpu_family(c_compiler) == 'x86_64': + is_64 = True + if 'LLVM D compiler' in out: - return compilers.LLVMDCompiler(exelist, version, is_cross, full_version=full_version) + return compilers.LLVMDCompiler(exelist, version, is_cross, is_64, full_version=full_version) elif 'gdc' in out: - return compilers.GnuDCompiler(exelist, version, is_cross, full_version=full_version) + return compilers.GnuDCompiler(exelist, version, is_cross, is_64, full_version=full_version) elif 'The D Language Foundation' in out or 'Digital Mars' in out: - return compilers.DmdDCompiler(exelist, version, is_cross, full_version=full_version) + return compilers.DmdDCompiler(exelist, version, is_cross, is_64, full_version=full_version) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') def detect_swift_compiler(self): @@ -876,6 +888,11 @@ This is probably wrong, it should always point to the native compiler.''' % evar elif isinstance(compiler, compilers.ClangCompiler): # Use llvm-ar if available; needed for LTO linkers = [self.clang_static_linker, self.default_static_linker] + elif isinstance(compiler, compilers.DCompiler): + if mesonlib.is_windows(): + linkers = [self.vs_static_linker, self.ldc2_static_linker] + else: + linkers = [self.default_static_linker, self.ldc2_static_linker] else: linkers = [self.default_static_linker] popen_exceptions = {} @@ -893,6 +910,8 @@ This is probably wrong, it should always point to the native compiler.''' % evar return VisualStudioLinker(linker) if p.returncode == 0 and ('armar' in linker or 'armar.exe' in linker): return ArmarLinker(linker) + if 'LDC - the LLVM D compiler' in out: + return LDCLinker(linker) if p.returncode == 0: return ArLinker(linker) if p.returncode == 1 and err.startswith('usage'): # OSX diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 358dd8f..e001232 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -3998,7 +3998,7 @@ Try setting b_lundef to false instead.''') # BW compatibility. This was permitted so we must support it # for a few releases so people can transition to "correct" # path declarations. - if i.startswith(self.environment.get_source_dir()): + if os.path.normpath(i).startswith(self.environment.get_source_dir()): mlog.warning('''Building a path to the source dir is not supported. Use a relative path instead. This will become a hard error in the future.''') i = os.path.relpath(i, os.path.join(self.environment.get_source_dir(), self.subdir)) diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index 6e40ab4..93106b3 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -137,3 +137,52 @@ class ArmarLinker(ArLinker): def can_linker_accept_rsp(self): # armar cann't accept arguments using the @rsp syntax return False + +class LDCLinker(StaticLinker): + + def __init__(self, exelist): + self.exelist = exelist + self.id = 'ldc2' + + def can_linker_accept_rsp(self): + return mesonlib.is_windows() + + def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): + return [] + + def get_exelist(self): + return self.exelist[:] + + def get_std_link_args(self): + return ['-lib'] + + def get_output_args(self, target): + return ['-of=' + target] + + def get_buildtype_linker_args(self, buildtype): + return [] + + def get_linker_always_args(self): + return [] + + def get_coverage_link_args(self): + return [] + + def get_always_args(self): + return [] + + def thread_link_flags(self, env): + return [] + + def openmp_flags(self): + return [] + + def get_option_link_args(self, options): + return [] + + @classmethod + def unix_args_to_native(cls, args): + return args[:] + + def get_link_debugfile_args(self, targetfile): + return [] |