Merge pull request #4084 from FFY00/pr-fix-dub-dependencies
dub: enhance dependency handling
This commit is contained in:
commit
9bcd498a2f
|
@ -13,9 +13,13 @@ RUN apt-get -y update && apt-get -y upgrade \
|
|||
&& apt-get -y install python-dev \
|
||||
&& apt-get -y install libomp-dev openssh-client \
|
||||
&& apt-get -y install -y clang libclang-dev llvm-dev flex \
|
||||
&& apt-get -y install gdc ldc \
|
||||
&& python3 -m pip install hotdoc codecov \
|
||||
&& dub fetch urld \
|
||||
&& dub build urld --compiler=gdc
|
||||
&& dub build urld --compiler=gdc \
|
||||
&& dub fetch dubtestproject \
|
||||
&& dub build dubtestproject:test1 --compiler=ldc2 \
|
||||
&& dub build dubtestproject:test2 --compiler=ldc2
|
||||
|
||||
# OpenSSH client is needed to run openmpi binaries.
|
||||
|
||||
|
|
|
@ -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[:]
|
||||
|
||||
|
@ -292,6 +295,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()
|
||||
|
||||
|
@ -307,6 +315,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.link_args.append(os.path.join(self.module_path, self.pkg['targetFileName']))
|
||||
|
||||
self.is_found = found
|
||||
# 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:
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
project('dub', 'd', meson_version: '0.48.0')
|
||||
|
||||
dependency('dubtestproject', method: 'dub') # Not library (none)
|
|
@ -0,0 +1,3 @@
|
|||
project('dub', 'd', meson_version: '0.48.0')
|
||||
|
||||
dependency('dubtestproject:test1', method: 'dub') # Not library (executable)
|
|
@ -0,0 +1,3 @@
|
|||
project('dub', 'd', meson_version: '0.48.0')
|
||||
|
||||
dependency('dubtestproject:test2', method: 'dub') # Compiler mismatch
|
Loading…
Reference in New Issue