aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2017-04-22 14:26:25 +0300
committerGitHub <noreply@github.com>2017-04-22 14:26:25 +0300
commite107017b3bc73d8f04d43d47f2ccb7eecc817aaa (patch)
treebfb41827fd039731d7b1a1dcd1f4478e9825f45c /mesonbuild
parent47579d3acba484d9c801fc9a2e751ffa3194eee5 (diff)
parent61ed2702bf83210d08b4eec9870d081fdedea0fe (diff)
downloadmeson-e107017b3bc73d8f04d43d47f2ccb7eecc817aaa.zip
meson-e107017b3bc73d8f04d43d47f2ccb7eecc817aaa.tar.gz
meson-e107017b3bc73d8f04d43d47f2ccb7eecc817aaa.tar.bz2
Merge pull request #1649 from centricular/static-lto
Fix LTO + static libraries on GCC and Clang
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/backend/ninjabackend.py6
-rw-r--r--mesonbuild/environment.py63
2 files changed, 43 insertions, 26 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 3bf840d..db136c7 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1304,7 +1304,11 @@ int dummy;
if static_linker is None:
return
rule = 'rule STATIC%s_LINKER\n' % crstr
- if mesonlib.is_windows():
+ # We don't use @file.rsp on Windows with ArLinker because llvm-ar and
+ # gcc-ar blindly pass the --plugin argument to `ar` and you cannot pass
+ # options as arguments while using the @file.rsp syntax.
+ # See: https://github.com/mesonbuild/meson/issues/1646
+ if mesonlib.is_windows() and not isinstance(static_linker, compilers.ArLinker):
command_template = ''' command = {executable} @$out.rsp
rspfile = $out.rsp
rspfile_content = $LINK_ARGS {output_args} $in
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 93a41e8..cb28897 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -262,8 +262,10 @@ class Environment:
self.default_objc = ['cc']
self.default_objcpp = ['c++']
self.default_fortran = ['gfortran', 'g95', 'f95', 'f90', 'f77']
- self.default_static_linker = 'ar'
- self.vs_static_linker = 'lib'
+ self.default_static_linker = ['ar']
+ self.vs_static_linker = ['lib']
+ self.gcc_static_linker = ['gcc-ar']
+ self.clang_static_linker = ['llvm-ar']
# Various prefixes and suffixes for import libraries, shared libraries,
# static libraries, and executables.
@@ -433,8 +435,8 @@ class Environment:
exe_wrap = None
return compilers, ccache, is_cross, exe_wrap
- def _handle_compiler_exceptions(self, exceptions, compilers):
- errmsg = 'Unknown compiler(s): ' + str(compilers)
+ def _handle_exceptions(self, exceptions, binaries, bintype='compiler'):
+ errmsg = 'Unknown {}(s): {}'.format(bintype, binaries)
if exceptions:
errmsg += '\nThe follow exceptions were encountered:'
for (c, e) in exceptions.items():
@@ -484,7 +486,7 @@ class Environment:
inteltype = ICC_STANDARD
cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler
return cls(ccache + compiler, version, inteltype, is_cross, exe_wrap)
- self._handle_compiler_exceptions(popen_exceptions, compilers)
+ self._handle_exceptions(popen_exceptions, compilers)
def detect_c_compiler(self, want_cross):
return self._detect_c_or_cpp_compiler('c', 'CC', want_cross)
@@ -537,7 +539,7 @@ class Environment:
if 'NAG Fortran' in err:
return NAGFortranCompiler(compiler, version, is_cross, exe_wrap)
- self._handle_compiler_exceptions(popen_exceptions, compilers)
+ self._handle_exceptions(popen_exceptions, compilers)
def get_scratch_dir(self):
return self.scratch_dir
@@ -570,7 +572,7 @@ class Environment:
return ClangObjCCompiler(ccache + compiler, version, CLANG_OSX, is_cross, exe_wrap)
if out.startswith('clang'):
return ClangObjCCompiler(ccache + compiler, version, CLANG_STANDARD, is_cross, exe_wrap)
- self._handle_compiler_exceptions(popen_exceptions, compilers)
+ self._handle_exceptions(popen_exceptions, compilers)
def detect_objcpp_compiler(self, want_cross):
popen_exceptions = {}
@@ -596,7 +598,7 @@ class Environment:
return ClangObjCPPCompiler(ccache + compiler, version, CLANG_OSX, is_cross, exe_wrap)
if out.startswith('clang'):
return ClangObjCPPCompiler(ccache + compiler, version, CLANG_STANDARD, is_cross, exe_wrap)
- self._handle_compiler_exceptions(popen_exceptions, compilers)
+ self._handle_exceptions(popen_exceptions, compilers)
def detect_java_compiler(self):
exelist = ['javac']
@@ -693,28 +695,39 @@ class Environment:
linker = self.cross_info.config['binaries']['ar']
if isinstance(linker, str):
linker = [linker]
+ linkers = [linker]
else:
evar = 'AR'
if evar in os.environ:
- linker = shlex.split(os.environ[evar])
+ linkers = [shlex.split(os.environ[evar])]
elif isinstance(compiler, VisualStudioCCompiler):
- linker = [self.vs_static_linker]
+ linkers = [self.vs_static_linker]
+ elif isinstance(compiler, GnuCompiler):
+ # Use gcc-ar if available; needed for LTO
+ linkers = [self.gcc_static_linker, self.default_static_linker]
+ elif isinstance(compiler, ClangCompiler):
+ # Use llvm-ar if available; needed for LTO
+ linkers = [self.clang_static_linker, self.default_static_linker]
else:
- linker = [self.default_static_linker]
- if 'lib' in linker or 'lib.exe' in linker:
- arg = '/?'
- else:
- arg = '--version'
- try:
- p, out, err = Popen_safe(linker + [arg])
- except OSError:
- raise EnvironmentException('Could not execute static linker "%s".' % ' '.join(linker))
- if '/OUT:' in out or '/OUT:' in err:
- return VisualStudioLinker(linker)
- if p.returncode == 0:
- return ArLinker(linker)
- if p.returncode == 1 and err.startswith('usage'): # OSX
- return ArLinker(linker)
+ linkers = [self.default_static_linker]
+ popen_exceptions = {}
+ for linker in linkers:
+ if 'lib' in linker or 'lib.exe' in linker:
+ arg = '/?'
+ else:
+ arg = '--version'
+ try:
+ p, out, err = Popen_safe(linker + [arg])
+ except OSError as e:
+ popen_exceptions[' '.join(linker + [arg])] = e
+ continue
+ if '/OUT:' in out or '/OUT:' in err:
+ return VisualStudioLinker(linker)
+ if p.returncode == 0:
+ return ArLinker(linker)
+ if p.returncode == 1 and err.startswith('usage'): # OSX
+ return ArLinker(linker)
+ self._handle_exceptions(popen_exceptions, linkers, 'linker')
raise EnvironmentException('Unknown static linker "%s"' % ' '.join(linker))
def detect_ccache(self):