Merge pull request #2444 from dcbaker/llvm

LLVM: Fix dynamic vs statically linking.
pull/2595/head
Jussi Pakkanen 7 years ago committed by GitHub
commit 416a6fc235
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      docs/markdown/snippets/llvm-static-linking.md
  2. 92
      mesonbuild/dependencies/dev.py
  3. 36
      test cases/frameworks/15 llvm/meson.build

@ -0,0 +1,8 @@
# LLVM dependency supports both dynamic and static linking
The LLVM dependency has been improved to consistently use dynamic linking.
Previously recent version (>= 3.9) would link dynamically while older versions
would link statically.
Now LLVM also accepts the `static` keyword to enable statically linking to LLVM
modules instead of dynamically linking.

@ -16,6 +16,7 @@
# development purposes, such as testing, debugging, etc..
import os
import re
import shlex
import shutil
@ -136,8 +137,10 @@ class LLVMDependency(ExternalDependency):
# It's necessary for LLVM <= 3.8 to use the C++ linker. For 3.9 and 4.0
# the C linker works fine if only using the C API.
super().__init__('llvm-config', environment, 'cpp', kwargs)
self.modules = []
self.provided_modules = []
self.required_modules = set()
self.llvmconfig = None
self.static = kwargs.get('static', False)
self.__best_found = None
# FIXME: Support multiple version requirements ala PkgConfigDependency
req_version = kwargs.get('version', None)
@ -169,31 +172,90 @@ class LLVMDependency(ExternalDependency):
# for users who want the patch version.
self.version = out.strip().rstrip('svn')
p, out = Popen_safe(
[self.llvmconfig, '--libs', '--ldflags'])[:2]
p, out = Popen_safe([self.llvmconfig, '--components'])[:2]
if p.returncode != 0:
raise DependencyException('Could not generate libs for LLVM.')
self.link_args = strip_system_libdirs(environment, shlex.split(out))
raise DependencyException('Could not generate modules for LLVM.')
self.provided_modules = shlex.split(out)
modules = stringlistify(extract_as_list(kwargs, 'modules'))
self.check_components(modules)
opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules'))
self.check_components(opt_modules, required=False)
p, out = Popen_safe([self.llvmconfig, '--cppflags'])[:2]
if p.returncode != 0:
raise DependencyException('Could not generate includedir for LLVM.')
cargs = mesonlib.OrderedSet(shlex.split(out))
self.compile_args = list(cargs.difference(self.__cpp_blacklist))
p, out = Popen_safe([self.llvmconfig, '--components'])[:2]
if version_compare(self.version, '>= 3.9'):
self._set_new_link_args()
else:
self._set_old_link_args()
self.link_args = strip_system_libdirs(environment, self.link_args)
def _set_new_link_args(self):
"""How to set linker args for LLVM versions >= 3.9"""
link_args = ['--link-static', '--system-libs'] if self.static else ['--link-shared']
p, out = Popen_safe(
[self.llvmconfig, '--libs', '--ldflags'] + link_args + list(self.required_modules))[:2]
if p.returncode != 0:
raise DependencyException('Could not generate modules for LLVM.')
self.modules = shlex.split(out)
raise DependencyException('Could not generate libs for LLVM.')
self.link_args = shlex.split(out)
modules = stringlistify(extract_as_list(kwargs, 'modules'))
def _set_old_link_args(self):
"""Setting linker args for older versions of llvm.
Old versions of LLVM bring an extra level of insanity with them.
llvm-config will provide the correct arguments for static linking, but
not for shared-linnking, we have to figure those out ourselves, because
of course we do.
"""
if self.static:
p, out = Popen_safe(
[self.llvmconfig, '--libs', '--ldflags', '--system-libs'] + list(self.required_modules))[:2]
if p.returncode != 0:
raise DependencyException('Could not generate libs for LLVM.')
self.link_args = shlex.split(out)
else:
# llvm-config will provide arguments for static linking, so we get
# to figure out for ourselves what to link with. We'll do that by
# checking in the directory provided by --libdir for a library
# called libLLVM-<ver>.(so|dylib|dll)
p, out = Popen_safe([self.llvmconfig, '--libdir'])[:2]
if p.returncode != 0:
raise DependencyException('Could not generate libs for LLVM.')
libdir = out.strip()
expected_name = 'libLLVM-{}'.format(self.version)
re_name = re.compile(r'{}.(so|dll|dylib)'.format(expected_name))
for file_ in os.listdir(libdir):
if re_name.match(file_):
self.link_args = ['-L{}'.format(libdir),
'-l{}'.format(os.path.splitext(file_.lstrip('lib'))[0])]
break
else:
raise DependencyException(
'Could not find a dynamically linkable library for LLVM.')
def check_components(self, modules, required=True):
"""Check for llvm components (modules in meson terms).
The required option is whether the module is required, not whether LLVM
is required.
"""
for mod in sorted(set(modules)):
if mod not in self.modules:
mlog.log('LLVM module', mod, 'found:', mlog.red('NO'))
self.is_found = False
if self.required:
raise DependencyException(
'Could not find required LLVM Component: {}'.format(mod))
if mod not in self.provided_modules:
mlog.log('LLVM module', mod, 'found:', mlog.red('NO'),
'(optional)' if not required else '')
if required:
self.is_found = False
if self.required:
raise DependencyException(
'Could not find required LLVM Component: {}'.format(mod))
else:
self.required_modules.add(mod)
mlog.log('LLVM module', mod, 'found:', mlog.green('YES'))
def check_llvmconfig(self, version_req):

@ -1,21 +1,31 @@
project('llvmtest', ['c', 'cpp'], default_options : ['c_std=c99'])
llvm_dep = dependency(
'llvm',
modules : ['bitwriter', 'asmprinter', 'executionengine', 'target',
'mcjit', 'nativecodegen'],
required : true,
)
d = dependency('llvm', modules : 'not-found', required : false)
assert(d.found() == false, 'not-found llvm module found')
d = dependency('llvm', version : '<0.1', required : false)
assert(d.found() == false, 'ancient llvm module found')
executable('sum', 'sum.c', dependencies : [
llvm_dep,
dependency('zlib'),
meson.get_compiler('c').find_library('dl', required : false),
dependency('tinfo'),
])
d = dependency('llvm', optional_modules : 'not-found', required : false)
assert(d.found() == true, 'optional module stopped llvm from being found.')
foreach static : [true, false]
llvm_dep = dependency(
'llvm',
modules : ['bitwriter', 'asmprinter', 'executionengine', 'target',
'mcjit', 'nativecodegen'],
required : true,
static : static,
)
name = static ? 'static' : 'dynamic'
executable(
'sum-@0@'.format(name),
'sum.c',
dependencies : [
llvm_dep,
dependency('zlib'),
dependency('glib-2.0'),
meson.get_compiler('c').find_library('dl', required : false),
]
)
endforeach

Loading…
Cancel
Save