@ -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 :