@ -14,8 +14,10 @@
import contextlib , os . path , re , tempfile
import collections . abc
from collections import deque
import itertools
import typing as T
from functools import lru_cache
from . . linkers import (
GnuLikeDynamicLinkerMixin , LinkerEnvVarsMixin , SolarisDynamicLinker ,
@ -465,6 +467,47 @@ class CompilerArgs(collections.abc.MutableSequence):
iterable : T . Optional [ T . Iterable [ str ] ] = None ) :
self . compiler = compiler
self . __container = list ( iterable ) if iterable is not None else [ ] # type: T.List[str]
self . pre = deque ( )
self . post = deque ( )
# Flush the saved pre and post list into the __container list
#
# This correctly deduplicates the entries after _can_dedup definition
# Note: This function is designed to work without delete operations, as deletions are worsening the performance a lot.
def flush_pre_post ( self ) :
pre_flush = deque ( )
pre_flush_set = set ( )
post_flush = deque ( )
post_flush_set = set ( )
#The two lists are here walked from the front to the back, in order to not need removals for deduplication
for a in reversed ( self . pre ) :
dedup = self . _can_dedup ( a )
if a not in pre_flush_set :
pre_flush . appendleft ( a )
if dedup == 2 :
pre_flush_set . add ( a )
for a in reversed ( self . post ) :
dedup = self . _can_dedup ( a )
if a not in post_flush_set :
post_flush . appendleft ( a )
if dedup == 2 :
post_flush_set . add ( a )
#pre and post will overwrite every element that is in the container
#only copy over args that are in __container but not in the post flush or pre flush set
for a in self . __container :
if a not in post_flush_set and a not in pre_flush_set :
pre_flush . append ( a )
self . __container = list ( pre_flush ) + list ( post_flush )
self . pre . clear ( )
self . post . clear ( )
def __iter__ ( self ) :
self . flush_pre_post ( )
return iter ( self . __container ) ;
@T . overload # noqa: F811
def __getitem__ ( self , index : int ) - > str : # noqa: F811
@ -475,6 +518,7 @@ class CompilerArgs(collections.abc.MutableSequence):
pass
def __getitem__ ( self , index ) : # noqa: F811
self . flush_pre_post ( )
return self . __container [ index ]
@T . overload # noqa: F811
@ -486,21 +530,26 @@ class CompilerArgs(collections.abc.MutableSequence):
pass
def __setitem__ ( self , index , value ) - > None : # noqa: F811
self . flush_pre_post ( )
self . __container [ index ] = value
def __delitem__ ( self , index : T . Union [ int , slice ] ) - > None :
self . flush_pre_post ( )
del self . __container [ index ]
def __len__ ( self ) - > int :
return len ( self . __container )
return len ( self . __container ) + len ( self . pre ) + len ( self . post )
def insert ( self , index : int , value : str ) - > None :
self . flush_pre_post ( )
self . __container . insert ( index , value )
def copy ( self ) - > ' CompilerArgs ' :
self . flush_pre_post ( )
return CompilerArgs ( self . compiler , self . __container . copy ( ) )
@classmethod
@lru_cache ( maxsize = None )
def _can_dedup ( cls , arg ) :
'''
Returns whether the argument can be safely de - duped . This is dependent
@ -555,6 +604,7 @@ class CompilerArgs(collections.abc.MutableSequence):
return 0
@classmethod
@lru_cache ( maxsize = None )
def _should_prepend ( cls , arg ) :
if arg . startswith ( cls . prepend_prefixes ) :
return True
@ -568,6 +618,7 @@ class CompilerArgs(collections.abc.MutableSequence):
# between static libraries, and for recursively searching for symbols
# needed by static libraries that are provided by object files or
# shared libraries.
self . flush_pre_post ( )
if copy :
new = self . copy ( )
else :
@ -627,6 +678,7 @@ class CompilerArgs(collections.abc.MutableSequence):
for absolute paths to libraries , etc , which can always be de - duped
safely .
'''
self . flush_pre_post ( )
if os . path . isabs ( arg ) :
self . append ( arg )
else :
@ -638,6 +690,7 @@ class CompilerArgs(collections.abc.MutableSequence):
reordering or de - dup except for absolute paths where the order of
include search directories is not relevant
'''
self . flush_pre_post ( )
for elem in iterable :
self . append_direct ( elem )
@ -653,6 +706,7 @@ class CompilerArgs(collections.abc.MutableSequence):
self . extend_direct ( lflags )
def __add__ ( self , args : T . Iterable [ str ] ) - > ' CompilerArgs ' :
self . flush_pre_post ( )
new = self . copy ( )
new + = args
return new
@ -662,8 +716,7 @@ class CompilerArgs(collections.abc.MutableSequence):
Add two CompilerArgs while taking into account overriding of arguments
and while preserving the order of arguments as much as possible
'''
pre = [ ] # type: T.List[str]
post = [ ] # type: T.List[str]
tmp_pre = deque ( )
if not isinstance ( args , collections . abc . Iterable ) :
raise TypeError ( ' can only concatenate Iterable[str] (not " {} " ) to CompilerArgs ' . format ( args ) )
for arg in args :
@ -673,32 +726,24 @@ class CompilerArgs(collections.abc.MutableSequence):
dedup = self . _can_dedup ( arg )
if dedup == 1 :
# Argument already exists and adding a new instance is useless
if arg in self or arg in pre or arg in post :
if arg in self . __container or arg in self . pre or arg in self . post :
continue
if dedup == 2 :
# Remove all previous occurrences of the arg and add it anew
if arg in self :
self . remove ( arg )
if arg in pre :
pre . remove ( arg )
if arg in post :
post . remove ( arg )
if self . _should_prepend ( arg ) :
pre . append ( arg )
tmp_pre . appendleft ( arg )
else :
post . append ( arg )
# Insert at the beginning
self [ : 0 ] = pre
# Append to the end
self . __container + = post
self . post . append ( arg )
self . pre . extendleft ( tmp_pre )
#pre and post is going to be merged later before a iter call
return self
def __radd__ ( self , args : T . Iterable [ str ] ) :
self . flush_pre_post ( )
new = CompilerArgs ( self . compiler , args )
new + = self
return new
def __eq__ ( self , other : T . Any ) - > T . Union [ bool , type ( NotImplemented ) ] :
self . flush_pre_post ( )
# Only allow equality checks against other CompilerArgs and lists instances
if isinstance ( other , CompilerArgs ) :
return self . compiler == other . compiler and self . __container == other . __container
@ -713,6 +758,7 @@ class CompilerArgs(collections.abc.MutableSequence):
self . __iadd__ ( args )
def __repr__ ( self ) - > str :
self . flush_pre_post ( )
return ' CompilerArgs( {!r} , {!r} ) ' . format ( self . compiler , self . __container )
class Compiler :