5858"""
5959
6060import base64
61+ import ctypes
62+ import fnmatch
63+ import json
6164import os
62- import sys
63- import shutil
65+ import posixpath
6466import random
67+ import shutil
68+ import sys
6569import uuid
66- import ctypes
70+ from subprocess import PIPE
6771
6872__scriptdir__ = os .path .dirname (os .path .abspath (__file__ ))
6973__rootdir__ = os .path .dirname (__scriptdir__ )
7074sys .path .append (__rootdir__ )
7175
72- import posixpath
7376from tools import shared , utils , js_manipulation
74- from subprocess import PIPE
75- import fnmatch
76- import json
7777
7878if len (sys .argv ) == 1 :
7979 print ('''Usage: file_packager TARGET [--preload A [B..]] [--embed C [D..]] [--exclude E [F..]]] [--js-output=OUTPUT.js] [--no-force] [--use-preload-cache] [--indexedDB-name=EM_PRELOAD_CACHE] [--separate-metadata] [--lz4] [--use-preload-plugins]
9898new_data_files = []
9999
100100
101+ class Options :
102+ def __init__ (self ):
103+ self .export_name = 'Module'
104+ self .has_preloaded = False
105+ self .jsoutput = None
106+ self .from_emcc = False
107+ self .force = True
108+ # If set to True, IndexedDB (IDBFS in library_idbfs.js) is used to locally
109+ # cache VFS XHR so that subsequent page loads can read the data from the
110+ # offline cache instead.
111+ self .use_preload_cache = False
112+ self .indexeddb_name = 'EM_PRELOAD_CACHE'
113+ # If set to True, the package metadata is stored separately from js-output
114+ # file which makes js-output file immutable to the package content changes.
115+ # If set to False, the package metadata is stored inside the js-output file
116+ # which makes js-output file to mutate on each invocation of this packager tool.
117+ self .separate_metadata = False
118+ self .lz4 = False
119+ self .use_preload_plugins = False
120+ self .support_node = True
121+
122+
123+ class DataFile :
124+ def __init__ (self , srcpath , dstpath , mode , explicit_dst_path ):
125+ self .srcpath = srcpath
126+ self .dstpath = dstpath
127+ self .mode = mode
128+ self .explicit_dst_path = explicit_dst_path
129+
130+
131+ options = Options ()
132+
133+
101134def base64_encode (b ):
102135 b64 = base64 .b64encode (b )
103136 return b64 .decode ('ascii' )
@@ -154,48 +187,22 @@ def add(mode, rootpathsrc, rootpathdst):
154187 # Convert source filename relative to root directory of target FS.
155188 dstpath = os .path .join (rootpathdst ,
156189 os .path .relpath (fullname , rootpathsrc ))
157- new_data_files .append ({ ' srcpath' : fullname , ' dstpath' : dstpath ,
158- 'mode' : mode , ' explicit_dst_path' : True } )
190+ new_data_files .append (DataFile ( srcpath = fullname , dstpath = dstpath ,
191+ mode = mode , explicit_dst_path = True ) )
159192 elif DEBUG :
160193 print ('Skipping file "%s" from inclusion in the emscripten '
161194 'virtual file system.' % fullname , file = sys .stderr )
162195 dirnames .clear ()
163196 dirnames .extend (new_dirnames )
164197
165198
166- class Options :
167- def __init__ (self ):
168- self .export_name = 'Module'
169- self .has_preloaded = False
170- self .jsoutput = None
171- self .from_emcc = False
172- self .force = True
173- # If set to True, IndexedDB (IDBFS in library_idbfs.js) is used to locally
174- # cache VFS XHR so that subsequent page loads can read the data from the
175- # offline cache instead.
176- self .use_preload_cache = False
177- self .indexeddb_name = 'EM_PRELOAD_CACHE'
178- # If set to True, the package metadata is stored separately from js-output
179- # file which makes js-output file immutable to the package content changes.
180- # If set to False, the package metadata is stored inside the js-output file
181- # which makes js-output file to mutate on each invocation of this packager tool.
182- self .separate_metadata = False
183- self .lz4 = False
184- self .use_preload_plugins = False
185- self .support_node = True
186-
187-
188- options = Options ()
189-
190-
191199def main ():
192200 data_files = []
193201 plugins = []
194202 leading = ''
195203
196204 for arg in sys .argv [2 :]:
197205 if arg == '--preload' :
198- options .has_preloaded = True
199206 leading = 'preload'
200207 elif arg == '--embed' :
201208 leading = 'embed'
@@ -256,8 +263,8 @@ def main():
256263 # Use source path as destination path.
257264 srcpath = dstpath = arg .replace ('@@' , '@' )
258265 if os .path .isfile (srcpath ) or os .path .isdir (srcpath ):
259- data_files .append ({ ' srcpath' : srcpath , ' dstpath' : dstpath , ' mode' : mode ,
260- 'explicit_dst_path' : uses_at_notation } )
266+ data_files .append (DataFile ( srcpath = srcpath , dstpath = dstpath , mode = mode ,
267+ explicit_dst_path = uses_at_notation ) )
261268 else :
262269 print ('error: ' + arg + ' does not exist' , file = sys .stderr )
263270 return 1
@@ -267,12 +274,13 @@ def main():
267274 print ('Unknown parameter:' , arg , file = sys .stderr )
268275 return 1
269276
270- if (not options .force ) and not data_files :
271- options .has_preloaded = False
272- if not options .has_preloaded or options .jsoutput is None :
273- assert not options .separate_metadata , (
274- 'cannot separate-metadata without both --preloaded files '
275- 'and a specified --js-output' )
277+ options .has_preloaded = any (f .mode == 'preload' for f in data_files )
278+
279+ if options .separate_metadata :
280+ if not options .has_preloaded or not options .jsoutput :
281+ print ('cannot separate-metadata without both --preloaded files '
282+ 'and a specified --js-output' )
283+ return 1
276284
277285 if not options .from_emcc :
278286 print ('Remember to build the main file with -s FORCE_FILESYSTEM=1 '
@@ -285,13 +293,13 @@ def main():
285293 return 1
286294
287295 for file_ in data_files :
288- if not should_ignore (file_ [ ' srcpath' ] ):
289- if os .path .isdir (file_ [ ' srcpath' ] ):
290- add (file_ [ ' mode' ] , file_ [ ' srcpath' ] , file_ [ ' dstpath' ] )
296+ if not should_ignore (file_ . srcpath ):
297+ if os .path .isdir (file_ . srcpath ):
298+ add (file_ . mode , file_ . srcpath , file_ . dstpath )
291299 else :
292300 new_data_files .append (file_ )
293301 data_files = [file_ for file_ in new_data_files
294- if not os .path .isdir (file_ [ ' srcpath' ] )]
302+ if not os .path .isdir (file_ . srcpath )]
295303 if len (data_files ) == 0 :
296304 print ('Nothing to do!' , file = sys .stderr )
297305 sys .exit (1 )
@@ -301,55 +309,55 @@ def main():
301309 # even if we cd'd into a symbolic link.
302310 curr_abspath = os .path .abspath (os .getcwd ())
303311
304- for file_ in data_files :
305- if not file_ [ 'explicit_dst_path' ] :
312+ if not file_ . explicit_dst_path :
313+ for file_ in data_files :
306314 # This file was not defined with src@dst, so we inferred the destination
307315 # from the source. In that case, we require that the destination not be
308316 # under the current location
309- path = file_ [ ' dstpath' ]
317+ path = file_ . dstpath
310318 # Use os.path.realpath to resolve any symbolic links to hard paths,
311319 # to match the structure in curr_abspath.
312320 abspath = os .path .realpath (os .path .abspath (path ))
313321 if DEBUG :
314- print (path , abspath , curr_abspath , file = sys .stderr )
322+ print (path , abspath , curr_abspath , file = sys .stderr )
315323 if not abspath .startswith (curr_abspath ):
316324 print ('Error: Embedding "%s" which is below the current directory '
317325 '"%s". This is invalid since the current directory becomes the '
318326 'root that the generated code will see' % (path , curr_abspath ),
319327 file = sys .stderr )
320328 sys .exit (1 )
321- file_ [ ' dstpath' ] = abspath [len (curr_abspath ) + 1 :]
329+ file_ . dstpath = abspath [len (curr_abspath ) + 1 :]
322330 if os .path .isabs (path ):
323331 print ('Warning: Embedding an absolute file/directory name "%s" to the '
324332 'virtual filesystem. The file will be made available in the '
325333 'relative path "%s". You can use the explicit syntax '
326334 '--preload-file srcpath@dstpath to explicitly specify the target '
327335 'location the absolute source path should be directed to.'
328- % (path , file_ [ ' dstpath' ] ), file = sys .stderr )
336+ % (path , file_ . dstpath ), file = sys .stderr )
329337
330338 for file_ in data_files :
331339 # name in the filesystem, native and emulated
332- file_ [ ' dstpath' ] = file_ [ ' dstpath' ] .replace (os .path .sep , '/' )
340+ file_ . dstpath = file_ . dstpath .replace (os .path .sep , '/' )
333341 # If user has submitted a directory name as the destination but omitted
334342 # the destination filename, use the filename from source file
335- if file_ [ ' dstpath' ] .endswith ('/' ):
336- file_ [ ' dstpath' ] = file_ [ ' dstpath' ] + os .path .basename (file_ [ ' srcpath' ] )
343+ if file_ . dstpath .endswith ('/' ):
344+ file_ . dstpath = file_ . dstpath + os .path .basename (file_ . srcpath )
337345 # make destination path always relative to the root
338- file_ [ ' dstpath' ] = posixpath .normpath (os .path .join ('/' , file_ [ ' dstpath' ] ))
346+ file_ . dstpath = posixpath .normpath (os .path .join ('/' , file_ . dstpath ))
339347 if DEBUG :
340348 print ('Packaging file "%s" to VFS in path "%s".'
341- % (file_ [ ' srcpath' ] , file_ [ ' dstpath' ] ), file = sys .stderr )
349+ % (file_ . srcpath , file_ . dstpath ), file = sys .stderr )
342350
343351 # Remove duplicates (can occur naively, for example preload dir/, preload dir/subdir/)
344- seen = {}
352+ seen = set ()
345353
346354 def was_seen (name ):
347- if seen . get ( name ) :
348- return True
349- seen [ name ] = 1
355+ if name in seen :
356+ return True
357+ seen . add ( name )
350358 return False
351359
352- data_files = [file_ for file_ in data_files if not was_seen (file_ [ ' dstpath' ] )]
360+ data_files = [file_ for file_ in data_files if not was_seen (file_ . dstpath )]
353361
354362 if AV_WORKAROUND :
355363 random .shuffle (data_files )
@@ -414,7 +422,7 @@ def generate_js(data_files, metadata):
414422 # Set up folders
415423 partial_dirs = []
416424 for file_ in data_files :
417- dirname = os .path .dirname (file_ [ ' dstpath' ] )
425+ dirname = os .path .dirname (file_ . dstpath )
418426 dirname = dirname .lstrip ('/' ) # absolute paths start with '/', remove that
419427 if dirname != '' :
420428 parts = dirname .split ('/' )
@@ -431,10 +439,10 @@ def generate_js(data_files, metadata):
431439 start = 0
432440 with open (data_target , 'wb' ) as data :
433441 for file_ in data_files :
434- file_ [ ' data_start' ] = start
435- with open (file_ [ ' srcpath' ] , 'rb' ) as f :
442+ file_ . data_start = start
443+ with open (file_ . srcpath , 'rb' ) as f :
436444 curr = f .read ()
437- file_ [ ' data_end' ] = start + len (curr )
445+ file_ . data_end = start + len (curr )
438446 if AV_WORKAROUND :
439447 curr += '\x00 '
440448 start += len (curr )
@@ -499,21 +507,21 @@ def generate_js(data_files, metadata):
499507 }\n ''' % (create_preloaded if options .use_preload_plugins else create_data )
500508
501509 for (counter , file_ ) in enumerate (data_files ):
502- filename = file_ [ ' dstpath' ]
510+ filename = file_ . dstpath
503511 dirname = os .path .dirname (filename )
504512 basename = os .path .basename (filename )
505- if file_ [ ' mode' ] == 'embed' :
513+ if file_ . mode == 'embed' :
506514 # Embed
507- data = base64_encode (utils .read_binary (file_ [ ' srcpath' ] ))
515+ data = base64_encode (utils .read_binary (file_ . srcpath ))
508516 code += " var fileData%d = '%s';\n " % (counter , data )
509517 code += (" Module['FS_createDataFile']('%s', '%s', decodeBase64(fileData%d), true, true, false);\n "
510518 % (dirname , basename , counter ))
511- elif file_ [ ' mode' ] == 'preload' :
519+ elif file_ . mode == 'preload' :
512520 # Preload
513521 metadata_el = {
514- 'filename' : file_ [ ' dstpath' ] ,
515- 'start' : file_ [ ' data_start' ] ,
516- 'end' : file_ [ ' data_end' ] ,
522+ 'filename' : file_ . dstpath ,
523+ 'start' : file_ . data_start ,
524+ 'end' : file_ . data_end ,
517525 }
518526 if filename [- 4 :] in AUDIO_SUFFIXES :
519527 metadata_el ['audio' ] = 1
0 commit comments