@ -752,7 +752,8 @@ class Environment:
def _guess_win_linker ( self , compiler : T . List [ str ] , comp_class : Compiler ,
def _guess_win_linker ( self , compiler : T . List [ str ] , comp_class : Compiler ,
for_machine : MachineChoice , * ,
for_machine : MachineChoice , * ,
use_linker_prefix : bool = True ) - > ' DynamicLinker ' :
use_linker_prefix : bool = True , invoked_directly : bool = True ,
extra_args : T . Optional [ T . List [ str ] ] = None ) - > ' DynamicLinker ' :
self . coredata . add_lang_args ( comp_class . language , comp_class , for_machine , self )
self . coredata . add_lang_args ( comp_class . language , comp_class , for_machine , self )
# Explicitly pass logo here so that we can get the version of link.exe
# Explicitly pass logo here so that we can get the version of link.exe
@ -771,25 +772,29 @@ class Environment:
override = comp_class . use_linker_args ( value [ 0 ] )
override = comp_class . use_linker_args ( value [ 0 ] )
check_args + = override
check_args + = override
if extra_args is not None :
check_args . extend ( extra_args )
p , o , _ = Popen_safe ( compiler + check_args )
p , o , _ = Popen_safe ( compiler + check_args )
if o . startswith ( ' LLD ' ) :
if o . startswith ( ' LLD ' ) :
if ' (compatible with GNU linkers) ' in o :
if ' (compatible with GNU linkers) ' in o :
return LLVMDynamicLinker (
return LLVMDynamicLinker (
compiler , for_machine , comp_class . LINKER_PREFIX ,
compiler , for_machine , comp_class . LINKER_PREFIX ,
override , version = search_version ( o ) )
override , version = search_version ( o ) , direct = invoked_directly )
if value is not None :
if value is not None and invoked_directly :
compiler = value
compiler = value
# We've already hanedled the non-direct case above
p , o , e = Popen_safe ( compiler + check_args )
p , o , e = Popen_safe ( compiler + check_args )
if o . startswith ( ' LLD ' ) :
if o . startswith ( ' LLD ' ) :
return ClangClDynamicLinker (
return ClangClDynamicLinker (
for_machine , [ ] ,
for_machine , [ ] ,
prefix = comp_class . LINKER_PREFIX if use_linker_prefix else [ ] ,
prefix = comp_class . LINKER_PREFIX if use_linker_prefix else [ ] ,
exelist = compiler , version = search_version ( o ) )
exelist = compiler , version = search_version ( o ) , direct = invoked_directly )
elif ' OPTLINK ' in o :
elif ' OPTLINK ' in o :
# Opltink's stdout *may* beging with a \r character.
# Opltink's stdout *may* beging with a \r character.
return OptlinkDynamicLinker ( for_machine , version = search_version ( o ) )
return OptlinkDynamicLinker ( compiler , for_machine , version = search_version ( o ) )
elif o . startswith ( ' Microsoft ' ) or e . startswith ( ' Microsoft ' ) :
elif o . startswith ( ' Microsoft ' ) or e . startswith ( ' Microsoft ' ) :
out = o or e
out = o or e
match = re . search ( r ' .*(X86|X64|ARM|ARM64).* ' , out )
match = re . search ( r ' .*(X86|X64|ARM|ARM64).* ' , out )
@ -801,7 +806,7 @@ class Environment:
return MSVCDynamicLinker (
return MSVCDynamicLinker (
for_machine , [ ] , machine = target , exelist = compiler ,
for_machine , [ ] , machine = target , exelist = compiler ,
prefix = comp_class . LINKER_PREFIX if use_linker_prefix else [ ] ,
prefix = comp_class . LINKER_PREFIX if use_linker_prefix else [ ] ,
version = search_version ( out ) )
version = search_version ( out ) , direct = invoked_directly )
elif ' GNU coreutils ' in o :
elif ' GNU coreutils ' in o :
raise EnvironmentException (
raise EnvironmentException (
" Found GNU link.exe instead of MSVC link.exe. This link.exe "
" Found GNU link.exe instead of MSVC link.exe. This link.exe "
@ -1496,28 +1501,31 @@ class Environment:
if ' LLVM D compiler ' in out :
if ' LLVM D compiler ' in out :
# LDC seems to require a file
# LDC seems to require a file
if info . is_windows ( ) or info . is_cygwin ( ) :
# We cannot use NamedTemproraryFile on windows, its documented
# Getting LDC on windows to give useful linker output when
# to not work for our uses. So, just use mkstemp and only have
# not doing real work is painfully hard. It ships with a
# one path for simplicity.
# version of lld-link, so unless we think the user wants
o , f = tempfile . mkstemp ( ' .d ' )
# link.exe, just assume that we're going to use lld-link
os . close ( o )
# with it.
linker = self . _guess_win_linker (
try :
[ ' link ' if is_msvc else ' lld-link ' ] ,
if info . is_windows ( ) or info . is_cygwin ( ) :
compilers . LLVMDCompiler , for_machine , use_linker_prefix = False )
objfile = os . path . basename ( f ) [ : - 1 ] + ' obj '
else :
linker = self . _guess_win_linker (
with tempfile . NamedTemporaryFile ( suffix = ' .d ' ) as f :
exelist ,
compilers . LLVMDCompiler , for_machine ,
use_linker_prefix = True , invoked_directly = False ,
extra_args = [ f ] )
else :
# LDC writes an object file to the current working directory.
# LDC writes an object file to the current working directory.
# Clean it up.
# Clean it up.
objectfile = os . path . basename ( f . name ) [ : - 1 ] + ' o '
objfile = os . path . basename ( f ) [ : - 1 ] + ' o '
linker = self . _guess_nix_linker (
linker = self . _guess_nix_linker (
exelist , compilers . LLVMDCompiler , for_machine ,
exelist , compilers . LLVMDCompiler , for_machine ,
extra_args = [ f . name ] )
extra_args = [ f ] )
try :
finally :
os . unlink ( objectfile )
mesonlib . windows_proof_rm ( f )
except Exception :
mesonlib . windows_proof_rm ( objfile )
# Thank you Windows file system semantics and virus scanners.
pass
return compilers . LLVMDCompiler (
return compilers . LLVMDCompiler (
exelist , version , for_machine , info , arch ,
exelist , version , for_machine , info , arch ,
full_version = full_version , linker = linker )
full_version = full_version , linker = linker )
@ -1528,20 +1536,30 @@ class Environment:
full_version = full_version , linker = linker )
full_version = full_version , linker = linker )
elif ' The D Language Foundation ' in out or ' Digital Mars ' in out :
elif ' The D Language Foundation ' in out or ' Digital Mars ' in out :
# DMD seems to require a file
# DMD seems to require a file
if info . is_windows ( ) or info . is_cygwin ( ) :
# We cannot use NamedTemproraryFile on windows, its documented
if is_msvc :
# to not work for our uses. So, just use mkstemp and only have
linker_cmd = [ ' link ' ]
# one path for simplicity.
elif arch == ' x86 ' :
o , f = tempfile . mkstemp ( ' .d ' )
linker_cmd = [ ' optlink ' ]
os . close ( o )
# DMD as different detection logic for x86 and x86_64
arch_arg = ' -m64 ' if arch == ' x86_64 ' else ' -m32 '
try :
if info . is_windows ( ) or info . is_cygwin ( ) :
objfile = os . path . basename ( f ) [ : - 1 ] + ' obj '
linker = self . _guess_win_linker (
exelist , compilers . DmdDCompiler , for_machine ,
invoked_directly = False , extra_args = [ f , arch_arg ] )
else :
else :
linker_cmd = [ ' lld-link ' ]
objfile = os . path . basename ( f ) [ : - 1 ] + ' o '
linker = self . _guess_win_linker ( linker_cmd , compilers . DmdDCompiler , for_machine ,
use_linker_prefix = False )
else :
with tempfile . NamedTemporaryFile ( suffix = ' .d ' ) as f :
linker = self . _guess_nix_linker (
linker = self . _guess_nix_linker (
exelist , compilers . DmdDCompiler , for_machine ,
exelist , compilers . DmdDCompiler , for_machine ,
extra_args = [ f . name ] )
extra_args = [ f , arch_arg ] )
finally :
mesonlib . windows_proof_rm ( f )
mesonlib . windows_proof_rm ( objfile )
return compilers . DmdDCompiler (
return compilers . DmdDCompiler (
exelist , version , for_machine , info , arch ,
exelist , version , for_machine , info , arch ,
full_version = full_version , linker = linker )
full_version = full_version , linker = linker )