@@ -108,31 +108,24 @@ class Mode(Enum):
108108 COMPILE_AND_LINK = auto ()
109109
110110
111+ class LinkFlag :
112+ """Used to represent a linker flag.
113+
114+ The flag value is stored along with a bool that distingingishes input
115+ files from non-files.
116+
117+ A list of these is return by separate_linker_flags.
118+ """
119+ def __init__ (self , value , is_file ):
120+ self .value = value
121+ self .is_file = is_file
122+
123+
111124class EmccState :
112125 def __init__ (self , args ):
113126 self .mode = Mode .COMPILE_AND_LINK
114127 # Using tuple here to prevent accidental mutation
115128 self .orig_args = tuple (args )
116- # List of link options paired with their position on the command line [(i, option), ...].
117- self .link_flags = []
118- self .lib_dirs = []
119-
120- def has_link_flag (self , f ):
121- return f in [x for _ , x in self .link_flags ]
122-
123- def add_link_flag (self , i , flag ):
124- if flag .startswith ('-L' ):
125- self .lib_dirs .append (flag [2 :])
126- # Link flags should be adding in strictly ascending order
127- assert not self .link_flags or i > self .link_flags [- 1 ][0 ], self .link_flags
128- self .link_flags .append ((i , flag ))
129-
130- def append_link_flag (self , flag ):
131- if self .link_flags :
132- index = self .link_flags [- 1 ][0 ] + 1
133- else :
134- index = 1
135- self .add_link_flag (index , flag )
136129
137130
138131class EmccOptions :
@@ -190,6 +183,7 @@ def __init__(self):
190183 self .nostartfiles = False
191184 self .sanitize_minimal_runtime = False
192185 self .sanitize = set ()
186+ self .lib_dirs = []
193187
194188
195189def create_reproduce_file (name , args ):
@@ -662,20 +656,21 @@ def run(args):
662656 if state .mode == Mode .POST_LINK_ONLY :
663657 if len (options .input_files ) != 1 :
664658 exit_with_error ('--post-link requires a single input file' )
665- separate_linker_flags (state , newargs )
659+ linker_args = separate_linker_flags (newargs )[1 ]
660+ linker_args = [f .value for f in linker_args ]
666661 # Delay import of link.py to avoid processing this file when only compiling
667662 from tools import link
668- link .run_post_link (options .input_files [0 ], options , state )
663+ link .run_post_link (options .input_files [0 ], options , linker_args )
669664 return 0
670665
671666 # Compile source code to object files
672667 # When only compiling this function never returns.
673- linker_inputs = phase_compile_inputs (options , state , newargs )
668+ linker_args = phase_compile_inputs (options , state , newargs )
674669
675670 if state .mode == Mode .COMPILE_AND_LINK :
676671 # Delay import of link.py to avoid processing this file when only compiling
677672 from tools import link
678- return link .run (linker_inputs , options , state )
673+ return link .run (options , linker_args )
679674 else :
680675 logger .debug ('stopping after compile phase' )
681676 return 0
@@ -747,26 +742,21 @@ def phase_parse_arguments(state):
747742 return options , newargs
748743
749744
750- def separate_linker_flags (state , newargs ):
751- """Process argument list separating out input files, compiler flags
752- and linker flags.
753-
754- - Linker flags are stored in state.link_flags
755- - Input files and compiler-only flags are returned as two separate lists.
745+ def separate_linker_flags (newargs ):
746+ """Process argument list separating out compiler args and linker args.
756747
757- Both linker flags and input files are stored as pairs of (i, entry) where
758- `i` is the orginal index in the command line arguments. This allow the two
759- lists to be recombined in the correct order by the linker code (link.py).
760-
761- Note that this index can have a fractional part for input arguments that
762- expand into multiple processed arguments, as in -Wl,-f1,-f2.
748+ - Linker flags include input files and are returned a list of LinkFlag objects.
749+ - Compiler flags are those to be passed to `clang -c`.
763750 """
764751
765752 if settings .RUNTIME_LINKED_LIBS :
766753 newargs += settings .RUNTIME_LINKED_LIBS
767754
768- input_files = []
769755 compiler_args = []
756+ linker_args = []
757+
758+ def add_link_arg (flag , is_file = False ):
759+ linker_args .append (LinkFlag (flag , is_file ))
770760
771761 skip = False
772762 for i in range (len (newargs )):
@@ -789,30 +779,24 @@ def get_next_arg():
789779 # https://bugs.python.org/issue1311
790780 if not os .path .exists (arg ) and arg not in (os .devnull , '-' ):
791781 exit_with_error ('%s: No such file or directory ("%s" was expected to be an input file, based on the commandline arguments provided)' , arg , arg )
792- input_files . append (( i , arg ) )
782+ add_link_arg ( arg , True )
793783 elif arg == '-z' :
794- state . add_link_flag ( i , newargs [ i ] )
795- state . add_link_flag ( i + 1 , get_next_arg ())
784+ add_link_arg ( arg )
785+ add_link_arg ( get_next_arg ())
796786 elif arg .startswith ('-Wl,' ):
797- # Multiple comma separated link flags can be specified. Create fake
798- # fractional indices for these: -Wl,a,b,c,d at index 4 becomes:
799- # (4, a), (4.25, b), (4.5, c), (4.75, d)
800- link_flags_to_add = arg .split (',' )[1 :]
801- for flag_index , flag in enumerate (link_flags_to_add ):
802- state .add_link_flag (i + float (flag_index ) / len (link_flags_to_add ), flag )
787+ for flag in arg .split (',' )[1 :]:
788+ add_link_arg (flag )
803789 elif arg == '-Xlinker' :
804- state .add_link_flag (i + 1 , get_next_arg ())
805- elif arg == '-s' :
806- state .add_link_flag (i , newargs [i ])
790+ add_link_arg (get_next_arg ())
807791 elif arg == '-s' or arg .startswith (('-l' , '-L' , '--js-library=' , '-z' )):
808- state . add_link_flag ( i , arg )
792+ add_link_arg ( arg )
809793 elif not arg .startswith ('-o' ) and arg not in ('-nostdlib' , '-nostartfiles' , '-nolibc' , '-nodefaultlibs' , '-s' ):
810794 # All other flags are for the compiler
811795 compiler_args .append (arg )
812796 if skip :
813797 compiler_args .append (get_next_arg ())
814798
815- return compiler_args , input_files
799+ return compiler_args , linker_args
816800
817801
818802@ToolchainProfiler .profile_block ('setup' )
@@ -955,8 +939,7 @@ def get_clang_command_asm():
955939 # filter out the link flags
956940 assert state .mode == Mode .COMPILE_AND_LINK
957941 assert not options .dash_c
958- compile_args , input_files = separate_linker_flags (state , newargs )
959- linker_inputs = []
942+ compile_args , linker_args = separate_linker_flags (newargs )
960943 seen_names = {}
961944
962945 def uniquename (name ):
@@ -967,10 +950,9 @@ def uniquename(name):
967950 def get_object_filename (input_file ):
968951 return in_temp (shared .replace_suffix (uniquename (input_file ), '.o' ))
969952
970- def compile_source_file (i , input_file ):
953+ def compile_source_file (input_file ):
971954 logger .debug (f'compiling source file: { input_file } ' )
972955 output_file = get_object_filename (input_file )
973- linker_inputs .append ((i , output_file ))
974956 if get_file_suffix (input_file ) in ASSEMBLY_EXTENSIONS :
975957 cmd = get_clang_command_asm ()
976958 elif get_file_suffix (input_file ) in PREPROCESSED_EXTENSIONS :
@@ -993,28 +975,29 @@ def compile_source_file(i, input_file):
993975 assert os .path .exists (output_file )
994976 if options .save_temps :
995977 shutil .copyfile (output_file , shared .unsuffixed_basename (input_file ) + '.o' )
978+ return output_file
996979
997- # First, generate LLVM bitcode. For each input file, we get base.o with bitcode
998- for i , input_file in input_files :
980+ # Compile input files individually to temporary locations.
981+ for arg in linker_args :
982+ if not arg .is_file :
983+ continue
984+ input_file = arg .value
999985 file_suffix = get_file_suffix (input_file )
1000986 if file_suffix in SOURCE_EXTENSIONS | ASSEMBLY_EXTENSIONS or (options .dash_c and file_suffix == '.bc' ):
1001- compile_source_file (i , input_file )
987+ arg . value = compile_source_file (input_file )
1002988 elif file_suffix in DYLIB_EXTENSIONS :
1003989 logger .debug (f'using shared library: { input_file } ' )
1004- linker_inputs .append ((i , input_file ))
1005990 elif building .is_ar (input_file ):
1006991 logger .debug (f'using static library: { input_file } ' )
1007- linker_inputs .append ((i , input_file ))
1008992 elif options .input_language :
1009- compile_source_file (i , input_file )
993+ arg . value = compile_source_file (input_file )
1010994 elif input_file == '-' :
1011995 exit_with_error ('-E or -x required when input is from standard input' )
1012996 else :
1013997 # Default to assuming the inputs are object files and pass them to the linker
1014- logger .debug (f'using object file: { input_file } ' )
1015- linker_inputs .append ((i , input_file ))
998+ pass
1016999
1017- return linker_inputs
1000+ return [ f . value for f in linker_args ]
10181001
10191002
10201003def version_string ():
@@ -1319,6 +1302,8 @@ def consume_arg_file():
13191302 'encountered. If this is to a local system header/library, it may '
13201303 'cause problems (local system files make sense for compiling natively '
13211304 'on your system, but not necessarily to JavaScript).' )
1305+ if arg .startswith ('-L' ):
1306+ options .lib_dirs .append (path_name )
13221307 elif check_flag ('--emrun' ):
13231308 options .emrun = True
13241309 elif check_flag ('--cpuprofiler' ):
0 commit comments