From 79f05b189a95e61cb6954765bc54cfcf05f1f3b1 Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Sat, 18 Aug 2018 12:51:26 +0300 Subject: Follow target platform defined in MSVC environment for Windows D compilation --- mesonbuild/compilers/d.py | 49 ++++++++++++++++++++++++++++++++++++----------- mesonbuild/environment.py | 17 +++++++++++++--- 2 files changed, 52 insertions(+), 14 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index e67683b..0067e61 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -62,20 +62,19 @@ dmd_optimization_args = {'0': [], } class DCompiler(Compiler): - def __init__(self, exelist, version, is_cross, **kwargs): + 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()) @@ -166,6 +165,8 @@ 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): @@ -224,6 +225,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 = [] @@ -272,8 +282,8 @@ class DCompiler(Compiler): return clike_debug_args[is_debug] 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, @@ -324,8 +334,8 @@ 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'] @@ -361,6 +371,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): @@ -381,10 +393,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.is_msvc = 'VCINSTALLDIR' in os.environ def get_colorout_args(self, colortype): if colortype == 'always': @@ -421,11 +434,25 @@ 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 [] + @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 c64fe59..346f5f4 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -833,12 +833,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): -- cgit v1.1 From 82b38b60718b7edfb7f3ef2860287e6ac8c74aab Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Sat, 18 Aug 2018 12:55:21 +0300 Subject: Fallback to LDC as static linker when not in MSVC build environment --- mesonbuild/environment.py | 10 +++++++++- mesonbuild/linkers.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'mesonbuild') diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 346f5f4..9777540 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. @@ -881,6 +882,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 = {} @@ -898,6 +904,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/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 [] -- cgit v1.1 From 7ab938d9aff64bfa9936daebbbb6b06d1b054ff1 Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Sat, 18 Aug 2018 14:08:47 +0300 Subject: Ignore unix related compiler arguments on Windows --- mesonbuild/compilers/d.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'mesonbuild') diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 0067e61..eafdc2d 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -103,6 +103,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): @@ -173,6 +175,9 @@ class DCompiler(Compiler): return [] 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: -- cgit v1.1 From 4a1d64cb6cb8c75cf98b6d5bc36c9634abc26f19 Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Sat, 18 Aug 2018 14:10:58 +0300 Subject: Fix import libraries and static library naming --- mesonbuild/build.py | 2 +- mesonbuild/compilers/d.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'mesonbuild') diff --git a/mesonbuild/build.py b/mesonbuild/build.py index c1cb8a8..96c64b8 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1079,7 +1079,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/d.py b/mesonbuild/compilers/d.py index eafdc2d..3366b6b 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -174,6 +174,9 @@ class DCompiler(Compiler): 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 [] @@ -252,6 +255,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'): -- cgit v1.1 From 9d5448ab45a7e553fe6063a2f0350451b3b55149 Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Sat, 18 Aug 2018 14:12:53 +0300 Subject: Normalize string constructs of d_import_dirs paths Fixes skipped deprecation warnings of badly constructed d_import_dirs on Windows. --- mesonbuild/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mesonbuild') diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 707cf9e..c0f3745 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -3929,7 +3929,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)) -- cgit v1.1 From b208cbda8163513787f669743f2c8877a330aaf1 Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Sat, 18 Aug 2018 14:30:53 +0300 Subject: Remove optimization related arguments from buildtype args, inline release builds Dub enables inlining by default for release builds, so meson should do it as well. --- mesonbuild/compilers/compilers.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index b8ae399..9acb93c 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': [], } -- cgit v1.1 From fd2c3b4c77ac1977d254301876525f8e631a940a Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Sat, 18 Aug 2018 14:44:55 +0300 Subject: Handle proper linking of MSVC runtime libraries DMD expects mscrtlib arguments while compiling, whereas LDC2 expects these while linking. --- mesonbuild/backend/ninjabackend.py | 2 +- mesonbuild/compilers/compilers.py | 9 ++++++ mesonbuild/compilers/d.py | 65 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 4 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index ace0693..6b2b130 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/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 9acb93c..47c222d 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -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 3366b6b..7d682ec 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -62,6 +62,14 @@ dmd_optimization_args = {'0': [], } class DCompiler(Compiler): + 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) @@ -286,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 @@ -293,6 +317,35 @@ 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, is_64, **kwargs): DCompiler.__init__(self, exelist, version, is_cross, is_64, **kwargs) @@ -301,7 +354,7 @@ class GnuDCompiler(DCompiler): 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+ @@ -349,7 +402,7 @@ class LLVMDCompiler(DCompiler): 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': @@ -396,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) @@ -408,7 +464,7 @@ class DmdDCompiler(DCompiler): 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): @@ -465,6 +521,9 @@ class DmdDCompiler(DCompiler): 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) -- cgit v1.1