Skip to content

Commit 8818da2

Browse files
authored
file_packager: Cleanup file embedding (#17220)
- Simplify library helper code - Avoid `--pre-js` completely where possible (it is still needed for --preload-file, but not for --embed-file)
1 parent 0859a3a commit 8818da2

File tree

6 files changed

+54
-37
lines changed

6 files changed

+54
-37
lines changed

ChangeLog.md

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ See docs/process.md for more on how version tagging works.
2020

2121
3.2.0
2222
-----
23+
- `tools/file_packager` no longer generates (or requires) any "pre-js" code when
24+
running in `--embed-file` mode. Instead the embedded files are loaded at
25+
static constructor time.
2326
- Emscripten now knows what minimum browser versions the `WASM_BIGINT` feature
2427
requires and will automatically set the defaults accordingly. (#17163)
2528
- Weak undefined symbols fixed in dynamic linking. (#17164)

emcc.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -1014,9 +1014,14 @@ def package_files(options, target):
10141014
rtn.append(object_file)
10151015

10161016
cmd = [shared.FILE_PACKAGER, shared.replace_suffix(target, '.data')] + file_args
1017-
file_code = shared.check_call(cmd, stdout=PIPE).stdout
1018-
1019-
options.pre_js = js_manipulation.add_files_pre_js(options.pre_js, file_code)
1017+
if options.preload_files:
1018+
# Preloading files uses --pre-js code that runs before the module is loaded.
1019+
file_code = shared.check_call(cmd, stdout=PIPE).stdout
1020+
options.pre_js = js_manipulation.add_files_pre_js(options.pre_js, file_code)
1021+
else:
1022+
# Otherwise, we are embedding files, which does not require --pre-js code,
1023+
# and instead relies on a static constrcutor to populate the filesystem.
1024+
shared.check_call(cmd)
10201025

10211026
return rtn
10221027

src/library.js

+17-18
Original file line numberDiff line numberDiff line change
@@ -3626,30 +3626,29 @@ mergeInto(LibraryManager.library, {
36263626
#endif
36273627
#endif
36283628

3629-
_emscripten_fs_load_embedded_files__deps: ['$FS'],
3629+
_emscripten_fs_load_embedded_files__deps: ['$FS', '$PATH'],
36303630
_emscripten_fs_load_embedded_files__sig: 'vp',
36313631
_emscripten_fs_load_embedded_files: function(ptr) {
3632-
#if MEMORY64
3633-
var start64 = ptr >> 3;
3634-
do {
3635-
var name_addr = Number(HEAPU64[start64++]);
3636-
var len = HEAPU32[start64 << 1];
3637-
start64++;
3638-
var content = Number(HEAPU64[start64++]);
3639-
var name = UTF8ToString(name_addr)
3640-
// canOwn this data in the filesystem, it is a slice of wasm memory that will never change
3641-
FS.createDataFile(name, null, HEAP8.subarray(content, content + len), true, true, true);
3642-
} while (HEAPU64[start64]);
3643-
#else
3644-
var start32 = ptr >> 2;
3632+
#if RUNTIME_DEBUG
3633+
err('preloading data files');
3634+
#endif
36453635
do {
3646-
var name_addr = HEAPU32[start32++];
3647-
var len = HEAPU32[start32++];
3648-
var content = HEAPU32[start32++];
3636+
var name_addr = {{{ makeGetValue('ptr', '0', '*') }}};
3637+
ptr += {{{ POINTER_SIZE }}};
3638+
var len = {{{ makeGetValue('ptr', '0', '*') }}};
3639+
ptr += {{{ POINTER_SIZE }}};
3640+
var content = {{{ makeGetValue('ptr', '0', '*') }}};
3641+
ptr += {{{ POINTER_SIZE }}};
36493642
var name = UTF8ToString(name_addr)
3643+
#if RUNTIME_DEBUG
3644+
err('preloading files: ' + name);
3645+
#endif
3646+
FS.createPath('/', PATH.dirname(name), true, true);
36503647
// canOwn this data in the filesystem, it is a slice of wasm memory that will never change
36513648
FS.createDataFile(name, null, HEAP8.subarray(content, content + len), true, true, true);
3652-
} while (HEAPU32[start32]);
3649+
} while ({{{ makeGetValue('ptr', '0', '*') }}});
3650+
#if RUNTIME_DEBUG
3651+
err('done preloading data files');
36533652
#endif
36543653
},
36553654
});

src/library_wasmfs.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ mergeInto(LibraryManager.library, {
1515
'$wasmFSPreloadedFiles',
1616
'$wasmFSPreloadedDirs',
1717
'$asyncLoad',
18+
'$PATH',
1819
],
1920
$FS : {
2021
// TODO: Clean up the following functions - currently copied from library_fs.js directly.
@@ -64,7 +65,15 @@ mergeInto(LibraryManager.library, {
6465
},
6566
createPath: (parent, path, canRead, canWrite) => {
6667
// Cache file path directory names.
67-
wasmFSPreloadedDirs.push({parentPath: parent, childName: path});
68+
var parts = path.split('/').reverse();
69+
while (parts.length) {
70+
var part = parts.pop();
71+
if (!part) continue;
72+
var current = PATH.join2(parent, part);
73+
wasmFSPreloadedDirs.push({parentPath: parent, childName: part});
74+
parent = current;
75+
}
76+
return current;
6877
},
6978
readFile: (path, opts) => {
7079
opts = opts || {};

tests/test_other.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -2756,7 +2756,7 @@ def test_file_packager_embed(self):
27562756
err = self.run_process([FILE_PACKAGER, 'test.data', '--embed', 'data.txt', '--js-output=data.js'], stderr=PIPE).stderr
27572757
self.assertContained('--obj-output is recommended when using --embed', err)
27582758

2759-
self.run_process([FILE_PACKAGER, 'test.data', '--embed', 'data.txt', '--obj-output=data.o', '--js-output=data.js'])
2759+
self.run_process([FILE_PACKAGER, 'test.data', '--embed', 'data.txt', '--obj-output=data.o'])
27602760

27612761
create_file('test.c', '''
27622762
#include <stdio.h>
@@ -2771,7 +2771,7 @@ def test_file_packager_embed(self):
27712771
return 0;
27722772
}
27732773
''')
2774-
self.run_process([EMCC, '--pre-js=data.js', 'test.c', 'data.o', '-sFORCE_FILESYSTEM'])
2774+
self.run_process([EMCC, 'test.c', 'data.o', '-sFORCE_FILESYSTEM'])
27752775
output = self.run_js('a.out.js')
27762776
self.assertContained('hello data', output)
27772777

@@ -5956,9 +5956,9 @@ def test_ld_library_path(self):
59565956
}
59575957
''')
59585958
create_file('pre.js', r'''
5959-
Module['preRun'].push(function (){
5959+
Module['preRun'] = function () {
59605960
ENV['LD_LIBRARY_PATH']='/lib:/usr/lib';
5961-
});
5961+
};
59625962
''')
59635963
create_file('main.c', r'''
59645964
#include <stdio.h>
@@ -9909,19 +9909,19 @@ def test_files_and_module_assignment(self):
99099909
# a pre-js can set Module to a new object or otherwise undo file preloading/
99109910
# embedding changes to Module.preRun. we show an error to avoid confusion
99119911
create_file('pre.js', 'Module = {};')
9912-
create_file('src.cpp', r'''
9912+
create_file('src.c', r'''
99139913
#include <stdio.h>
99149914
int main() {
9915-
printf("file exists: %d\n", !!fopen("src.cpp", "rb"));
9915+
printf("file exists: %p\n", fopen("src.cpp", "rb"));
99169916
}
99179917
''')
9918-
self.run_process([EMXX, 'src.cpp', '--pre-js', 'pre.js', '--embed-file', 'src.cpp'])
9918+
self.run_process([EMCC, 'src.c', '--pre-js=pre.js', '--preload-file=src.c'])
99199919
result = self.run_js('a.out.js', assert_returncode=NON_ZERO)
99209920
self.assertContained('Module.preRun should exist because file support used it; did a pre-js delete it?', result)
99219921

99229922
def test_error(pre):
99239923
create_file('pre.js', pre)
9924-
self.run_process([EMXX, 'src.cpp', '--pre-js', 'pre.js', '--embed-file', 'src.cpp'])
9924+
self.run_process([EMXX, 'src.c', '--pre-js=pre.js', '--preload-file=src.c'])
99259925
result = self.run_js('a.out.js', assert_returncode=NON_ZERO)
99269926
self.assertContained('All preRun tasks that exist before user pre-js code should remain after; did you replace Module or modify Module.preRun?', result)
99279927

tools/file_packager.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,8 @@ def was_seen(name):
537537
err('--obj-output is only applicable when embedding files')
538538
return 1
539539
generate_object_file(data_files)
540+
if not options.has_preloaded:
541+
return 0
540542

541543
ret = generate_js(data_target, data_files, metadata)
542544

@@ -680,13 +682,12 @@ def generate_js(data_target, data_files, metadata):
680682
dirname = os.path.dirname(filename)
681683
basename = os.path.basename(filename)
682684
if file_.mode == 'embed':
683-
if not options.obj_output:
684-
# Embed
685-
data = base64_encode(utils.read_binary(file_.srcpath))
686-
code += " var fileData%d = '%s';\n" % (counter, data)
687-
# canOwn this data in the filesystem (i.e. there is no need to create a copy in the FS layer).
688-
code += (" Module['FS_createDataFile']('%s', '%s', decodeBase64(fileData%d), true, true, true);\n"
689-
% (dirname, basename, counter))
685+
# Embed
686+
data = base64_encode(utils.read_binary(file_.srcpath))
687+
code += " var fileData%d = '%s';\n" % (counter, data)
688+
# canOwn this data in the filesystem (i.e. there is no need to create a copy in the FS layer).
689+
code += (" Module['FS_createDataFile']('%s', '%s', decodeBase64(fileData%d), true, true, true);\n"
690+
% (dirname, basename, counter))
690691
elif file_.mode == 'preload':
691692
# Preload
692693
metadata_el = {

0 commit comments

Comments
 (0)