2121$ emcc -g2 -gsource-map a.o b.o -o result.js
2222See https://emscripten.org/docs/porting/Debugging.html for more details.
2323
24- This takes a wasm file and a paths file, which is a text file containing a list
25- of paths as inputs. The paths file should contain a single path per line. A
26- single split module will be generated per specified path. If a specified path
27- contains another specified path, functions contained in the inner path will be
28- split as the inner path's module, and the rest of the functions will be split as
29- the outer path's module. Functions that do not belong to any of the specified
30- paths will remain in the primary module.
24+ This takes a wasm file and a paths file as inputs. The paths file defines how
25+ to split modules. The format is similar to the manifest file for wasm-split, but
26+ with paths instead of function names. A module is defined by a name on a line,
27+ followed by paths on subsequent lines. Modules are separated by empty lines.
28+ For example:
29+ module1
30+ path/to/a
31+ path/to/b
32+
33+ module2
34+ path/to/c
35+
36+ This will create two modules, 'module1' and 'module2'. 'module1' will contain
37+ functions from source files under path/to/a and path/to/b. 'module2' will
38+ contain functions from source files under path/to/c.
39+
40+ If a specified path contains another specified path, functions contained in the
41+ inner path will be split as the inner path's module, and the rest of the
42+ functions will be split as the outer path's module. Functions that do not belong
43+ to any of the specified paths will remain in the primary module.
3144
3245The paths in the paths file can be either absolute or relative, but they should
3346match those of 'sources' field in the source map file. Sometimes a source map's
@@ -238,6 +251,50 @@ def is_synthesized_func(func):
238251 return path_to_funcs
239252
240253
254+ # 1. Strip whitespaces
255+ # 2. Normalize separators
256+ # 3. Make /a/b/c and /a/b/c/ equivalent
257+ def normalize_path (path ):
258+ return utils .normalize_path (path .strip ()).rstrip (os .sep )
259+
260+
261+ def parse_paths_file (paths_file_content ):
262+ module_to_paths = {}
263+ path_to_module = {}
264+ cur_module = None
265+ cur_paths = []
266+
267+ for line in paths_file_content .splitlines ():
268+ line = line .strip ()
269+ if not line :
270+ if cur_module :
271+ if not cur_paths :
272+ diagnostics .warn (f"Module '{ cur_module } ' has no paths specified." )
273+ module_to_paths [cur_module ] = cur_paths
274+ cur_module = None
275+ cur_paths = []
276+ continue
277+
278+ if not cur_module :
279+ cur_module = line
280+ else :
281+ path = normalize_path (line )
282+ if path in path_to_module :
283+ exit_with_error ("Path '{path}' cannot be assigned to module '{cur_module}; it is already assigned to module '{path_to_module[path]}'" )
284+ cur_paths .append (path )
285+ path_to_module [path ] = cur_module
286+
287+ if cur_module :
288+ if not cur_paths :
289+ diagnostics .warn (f"Module '{ cur_module } ' has no paths specified." )
290+ module_to_paths [cur_module ] = cur_paths
291+
292+ if not module_to_paths :
293+ exit_with_error ('The paths file is empty or invalid.' )
294+
295+ return module_to_paths
296+
297+
241298def main ():
242299 args , forwarded_args = parse_args ()
243300 check_errors (args )
@@ -247,32 +304,41 @@ def main():
247304 print_sources (sourcemap )
248305 return
249306
250- paths = utils .read_file (args .paths_file ).splitlines ()
251- paths = [utils .normalize_path (path .strip ()) for path in paths if path .strip ()]
252- # To make /a/b/c and /a/b/c/ equivalent
253- paths = [path .rstrip (os .sep ) for path in paths ]
254- # Remove duplicates
255- paths = list (dict .fromkeys (paths ))
307+ content = utils .read_file (args .paths_file )
308+ module_to_paths = parse_paths_file (content )
256309
257310 # Compute {path: list of functions} map
258- path_to_funcs = get_path_to_functions_map (args .wasm , sourcemap , paths )
311+ all_paths = []
312+ for paths in module_to_paths .values ():
313+ all_paths .extend (paths )
314+ path_to_funcs = get_path_to_functions_map (args .wasm , sourcemap , all_paths )
259315
260316 # Write .manifest file
261317 with tempfile .NamedTemporaryFile (suffix = ".manifest" , mode = 'w+' , delete = args .preserve_manifest ) as f :
262318 manifest = f .name
263- for i , path in enumerate (paths ):
264- f .write (f'{ i } \n ' )
265- if not path_to_funcs [path ]:
266- diagnostics .warn (f'{ path } does not match any functions' )
319+ for i , (module , paths ) in enumerate (module_to_paths .items ()):
320+ if i != 0 : # Unless we are the first entry add a newline separator
321+ f .write ('\n ' )
322+ funcs = []
323+ for path in paths :
324+ if not path_to_funcs [path ]:
325+ diagnostics .warn (f'{ path } does not match any functions' )
326+ funcs += path_to_funcs [path ]
327+ if not funcs :
328+ diagnostics .warn (f"Module '{ module } ' does not match any functions" )
329+
267330 if args .verbose :
268- print (f'{ path } : { len (path_to_funcs [path ])} functions' )
269- for func in path_to_funcs [path ]:
270- print (' ' + func )
331+ print (f'{ module } : { len (funcs )} functions' )
332+ for path in paths :
333+ if path in path_to_funcs :
334+ print (f' { path } : { len (path_to_funcs [path ])} functions' )
335+ for func in path_to_funcs [path ]:
336+ print (' ' + func )
271337 print ()
272- for func in path_to_funcs [path ]:
338+
339+ f .write (f'{ module } \n ' )
340+ for func in funcs :
273341 f .write (func + '\n ' )
274- if i < len (paths ) - 1 :
275- f .write ('\n ' )
276342 f .flush ()
277343
278344 cmd = [args .wasm_split , '--multi-split' , args .wasm , '--manifest' , manifest ]
0 commit comments