dub: enhance dependency handling

fixes #4032: meson now checks properly for the compiler used to compile dub dependencies

fixes #3568: applied the following patch https://paste.debian.net/1039317/

meson now adds flags for native dependencies required by dub modules

meson now checks for the D version implemented by the compiler used to build dub dependencies (execpt gdc which doesn't support this)
pull/4084/head
FFY00 7 years ago
parent b86f2fd17f
commit 124cedde38
No known key found for this signature in database
GPG Key ID: F893C674816AA95D
  1. 9
      mesonbuild/compilers/d.py
  2. 125
      mesonbuild/dependencies/base.py

@ -95,6 +95,9 @@ class DCompiler(Compiler):
def name_string(self):
return ' '.join(self.exelist)
def get_exelist(self):
return self.exelist
def get_linker_exelist(self):
return self.exelist[:]
@ -294,6 +297,11 @@ class DCompiler(Compiler):
# a linker search path.
dcargs.append('-L' + arg)
continue
elif arg.startswith('/') or arg.startswith('./'):
# absolute (or relative) paths passed to the linker may be static libraries
# or other objects that we need to link.
dcargs.append('-L' + arg)
continue
elif arg.startswith('-mscrtlib='):
mscrtlib = arg[10:].lower()
@ -309,6 +317,7 @@ class DCompiler(Compiler):
dcargs.append('-L/DEFAULTLIB:legacy_stdio_definitions.lib')
dcargs.append(arg)
continue
dcargs.append(arg)

@ -24,6 +24,7 @@ import json
import shlex
import shutil
import textwrap
import platform
from enum import Enum
from pathlib import PurePath
@ -849,12 +850,13 @@ class DubDependency(ExternalDependency):
super().__init__('dub', environment, 'd', kwargs)
self.name = name
self.compiler = super().get_compiler()
self.module_path = None
if 'required' in kwargs:
self.required = kwargs.get('required')
if DubDependency.class_dubbin is None:
self.dubbin = self.check_dub()
self.dubbin = self._check_dub()
DubDependency.class_dubbin = self.dubbin
else:
self.dubbin = DubDependency.class_dubbin
@ -875,20 +877,33 @@ class DubDependency(ExternalDependency):
self.is_found = False
return
j = json.loads(res)
comp = self.compiler.get_id().replace('llvm', 'ldc').replace('gcc', 'gdc')
packages = []
j = json.loads(res)
for package in j['packages']:
packages.append(package['name'])
if package['name'] == name:
if j['compiler'] != comp:
msg = ['Dependency', mlog.bold(name), 'found but it was compiled with']
msg += [mlog.bold(j['compiler']), 'and we are using', mlog.bold(comp)]
mlog.error(*msg)
self.is_found = True
not_lib = True
if 'targetType' in package:
if package['targetType'] == 'library':
not_lib = False
if not_lib:
mlog.error(mlog.bold(name), 'found but it isn\'t a library')
self.is_found = False
return
self.module_path = self._find_right_lib_path(package['path'], comp, j, True, package['targetFileName'])
if not os.path.exists(self.module_path):
mlog.error(mlog.bold(name), 'found but it wasn\'t compiled with', mlog.bold(comp))
self.is_found = False
return
self.version = package['version']
self.pkg = package
break
if self.pkg['targetFileName'].endswith('.a'):
self.static = True
@ -899,39 +914,93 @@ class DubDependency(ExternalDependency):
for path in self.pkg['importPaths']:
self.compile_args.append('-I' + os.path.join(self.pkg['path'], path))
self.link_args = []
self.link_args = self.raw_link_args = []
for flag in self.pkg['lflags']:
self.link_args.append(flag)
search_paths = []
search_paths.append(os.path.join(self.pkg['path'], self.pkg['targetPath']))
found, res = self.__search_paths(search_paths, self.pkg['targetFileName'])
for file in res:
self.link_args.append(file)
self.is_found = found
self.link_args.append(os.path.join(self.module_path, self.pkg['targetFileName']))
# Handle dependencies
libs = []
def add_lib_args(field_name, target):
if field_name in target['buildSettings']:
if os.name is 'nt':
for lib in target['buildSettings'][field_name]:
if lib not in target['buildSettings'][field_name]:
libs.append(lib)
# TODO: Use CCompiler.find_library to find the path of the .lib files
else: # posix and everything else
for lib in target['buildSettings'][field_name]:
if lib not in libs:
libs.append(lib)
pkgdep = PkgConfigDependency(lib, environment, {'required': 'true', 'silent': 'true'})
for arg in pkgdep.get_compile_args():
self.compile_args.append(arg)
for arg in pkgdep.get_link_args():
self.link_args.append(arg)
for arg in pkgdep.get_link_args(raw=True):
self.raw_link_args.append(arg)
for target in j['targets']:
if target['rootPackage'] in packages:
add_lib_args('libs', target)
add_lib_args('libs-{}'.format(platform.machine()), target)
for file in target['buildSettings']['linkerFiles']:
self.link_args.append(self._find_right_lib_path(file, comp, j))
def get_compiler(self):
return self.compiler
def __search_paths(self, search_paths, target_file):
found = False
res = []
if target_file == '':
return True, res
for path in search_paths:
if os.path.isdir(path):
for file in os.listdir(path):
if file == target_file:
res.append(os.path.join(path, file))
found = True
return found, res
def _find_right_lib_path(self, default_path, comp, j, folder_only=False, file_name=''):
path = ''
module_build_path = lib_file_name = ''
if folder_only:
module_build_path = default_path
lib_file_name = file_name
else:
module_build_path = os.path.dirname(default_path)
lib_file_name = os.path.basename(default_path)
# Get D version implemented in the compiler
# gdc doesn't support this
ret, res = self._call_dubbin(['--version'])
if ret != 0:
mlog.error('Failed to run {!r}', mlog.bold(comp))
self.is_found = False
return
d_ver = re.search('v[0-9].[0-9][0-9][0-9].[0-9]', res) # Ex.: v2.081.2
if d_ver is not None:
d_ver = d_ver.group().rsplit('.', 1)[0].replace('v', '').replace('.', '') # Fix structure. Ex.: 2081
else:
d_ver = '' # gdc
# Ex.: library-debug-linux.posix-x86_64-ldc_2081-EF934983A3319F8F8FF2F0E107A363BA
build_name = 'library-{}-{}.{}-{}-{}_{}'.format(j['buildType'], j['platform'][0], j['platform'][1], platform.machine(), comp, d_ver)
for entry in os.listdir(os.path.join(module_build_path, '.dub', 'build')):
if entry.startswith(build_name):
for file in os.listdir(os.path.join(module_build_path, '.dub', 'build', entry)):
if file == lib_file_name:
if folder_only:
path = os.path.join(module_build_path, '.dub', 'build', entry)
else:
path = os.path.join(module_build_path, '.dub', 'build', entry, lib_file_name)
break
return path
def _call_dubbin(self, args, env=None):
p, out = Popen_safe(self.dubbin.get_command() + args, env=env)[0:2]
return p.returncode, out.strip()
def check_dub(self):
def _call_copmbin(self, args, env=None):
p, out = Popen_safe(self.compiler.get_exelist() + args, env=env)[0:2]
return p.returncode, out.strip()
def _check_dub(self):
dubbin = ExternalProgram('dub', silent=True)
if dubbin.found():
try:

Loading…
Cancel
Save