aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2018-08-27 22:30:23 +0300
committerGitHub <noreply@github.com>2018-08-27 22:30:23 +0300
commit1ffc8de5e8cc79dbaa54fd1ac02b6b4c5edac7a1 (patch)
tree916eb6a1c988386d9848115709dd9c6b199a5a5a /mesonbuild
parent731906504efb57aa9ae86685501f1d3a0aa22121 (diff)
parentfd2c3b4c77ac1977d254301876525f8e631a940a (diff)
downloadmeson-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.py2
-rw-r--r--mesonbuild/build.py2
-rw-r--r--mesonbuild/compilers/compilers.py21
-rw-r--r--mesonbuild/compilers/d.py126
-rw-r--r--mesonbuild/environment.py27
-rw-r--r--mesonbuild/interpreter.py2
-rw-r--r--mesonbuild/linkers.py49
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 []