From fd2c3b4c77ac1977d254301876525f8e631a940a Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Sat, 18 Aug 2018 14:44:55 +0300 Subject: [PATCH] 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(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index ace069338..6b2b130ac 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 9acb93c16..47c222d56 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 3366b6b61..7d682ec0f 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)