diff --git a/.circleci/config.yml b/.circleci/config.yml index f2eb83890835c..0a6ba54e9a38e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -651,9 +651,14 @@ jobs: wasmfs.test_fs_llseek_rawfs wasmfs.test_freetype minimal0.test_utf - instance.test_async_hello_v8 - instance.test_environment " + test-modularize-instance: + executor: focal + environment: + EMTEST_SKIP_NODE_CANARY: "1" + steps: + - run-tests-linux: + test_targets: "instance" test-wasm2js1: environment: EMTEST_SKIP_NODE_CANARY: "1" @@ -806,26 +811,6 @@ jobs: core0.test_pthread_join_and_asyncify core0.test_async_ccall_promise_jspi* core0.test_cubescript_jspi - instance.test_hello_world - instance.test_dylink_basics - instance.test_cube2hash* - instance.test_exceptions_3* - instance.test_memorygrowth - instance.test_stat - instance.test_iostream_and_determinism - instance.test_fannkuch - instance.test_fasta - instance.test_EXPORTED_RUNTIME_METHODS - instance.test_abort_on_exceptions* - instance.test_ccall - instance.test_dylink_basics* - instance.test_Module_dynamicLibraries* - instance.test_dylink_argv_argc - instance.test_dlmalloc* - instance.test_dyncall* - instance.test_em_asm* - instance.test_embind* - instance.test_module_wasm_memory esm_integration.test_fs_js_api* esm_integration.test_inlinejs3 esm_integration.test_embind_val_basics @@ -1154,6 +1139,9 @@ workflows: - test-other: requires: - build-linux + - test-modularize-instance: + requires: + - build-linux - test-browser-chrome - test-browser-chrome-2gb: requires: diff --git a/site/source/docs/compiling/Modularized-Output.rst b/site/source/docs/compiling/Modularized-Output.rst index 149e1d673f6e8..b726ff1248027 100644 --- a/site/source/docs/compiling/Modularized-Output.rst +++ b/site/source/docs/compiling/Modularized-Output.rst @@ -133,6 +133,8 @@ fix in future releses. Current limitations include: * :ref:`asyncify_lazy_load_code` is not supported (depends on ``wasmExports`` global) +* :ref:`minimal_runtime` is not supported. + * The output of file_packager is not compatible so :ref:`emcc-preload-file` and :ref:`emcc-embed-file` do not work. diff --git a/src/lib/libccall.js b/src/lib/libccall.js index 70efba20aab53..6246f51aa5a7b 100644 --- a/src/lib/libccall.js +++ b/src/lib/libccall.js @@ -6,7 +6,7 @@ addToLibrary({ // Returns the C function with a specified identifier (for C++, you need to do manual name mangling) -#if MODULARIZE == 'instance' +#if MODULARIZE == 'instance' && !INCLUDE_FULL_LIBRARY $getCFunc__deps: [() => error('ccall is not yet compatible with MODULARIZE=instance')], #endif $getCFunc__internal: true, diff --git a/test/common.py b/test/common.py index 0331e043c2a7d..d99a5c76fefd4 100644 --- a/test/common.py +++ b/test/common.py @@ -522,6 +522,8 @@ def metafunc(self, with_minimal_runtime, *args, **kwargs): print('parameterize:minimal_runtime=%s' % with_minimal_runtime) assert self.get_setting('MINIMAL_RUNTIME') is None if with_minimal_runtime: + if self.get_setting('MODULARIZE') == 'instance': + self.skipTest('MODULARIZE=instance is not compatible with MINIMAL_RUNTIME') self.set_setting('MINIMAL_RUNTIME', 1) # This extra helper code is needed to cleanly handle calls to exit() which throw # an ExitCode exception. diff --git a/test/core/pthread/test_pthread_exit_runtime.pre.js b/test/core/pthread/test_pthread_exit_runtime.pre.js index 646b3a5597b21..21b82c2779d0a 100644 --- a/test/core/pthread/test_pthread_exit_runtime.pre.js +++ b/test/core/pthread/test_pthread_exit_runtime.pre.js @@ -1,7 +1,7 @@ var address = 0; Module.onRuntimeInitialized = function() { - address = Module['_join_returned_address'](); + address = _join_returned_address(); assert(address); assert(HEAP8[address] == 0); } diff --git a/test/core/test_env.out b/test/core/test_env.out index 993ec9530ee0f..88c123a949c09 100644 --- a/test/core/test_env.out +++ b/test/core/test_env.out @@ -5,7 +5,7 @@ PATH=/ PWD=/ HOME=/home/web_user LANG=(C|en_US).UTF-8 -_=.*(/test_env.js|./this.program) +_=.*(/test_env.m?js|./this.program) getenv\(PATH\): / getenv\(NONEXISTENT\): \(null\) diff --git a/test/core/test_environ.out b/test/core/test_environ.out index 0ec4fa3b86303..62123014b8149 100644 --- a/test/core/test_environ.out +++ b/test/core/test_environ.out @@ -4,4 +4,4 @@ PATH=/ PWD=/ HOME=/home/web_user LANG=(C|en_US).UTF-8 -_=.*(/test_environ.js|/this.program) +_=.*(/test_environ.m?js|/this.program) diff --git a/test/core/test_main_reads_args.out b/test/core/test_main_reads_args.out index 051e3b5ed2fd3..b193b75c8519e 100644 --- a/test/core/test_main_reads_args.out +++ b/test/core/test_main_reads_args.out @@ -1,2 +1,2 @@ argc: 1 -argv\[0\]: (test_main_reads_args\.js|this\.program) +argv\[0\]: (test_main_reads_args\.m?js|this\.program) diff --git a/test/core/test_utf.c b/test/core/test_utf.c index 506b166c96ed5..fa07a2b5c7566 100644 --- a/test/core/test_utf.c +++ b/test/core/test_utf.c @@ -6,16 +6,21 @@ */ #include -#include #include +#include +#include + +EM_JS_DEPS(deps, "$stringToUTF8OnStack,$getValue"); + int main() { char *c = "μ†ℱ ╋ℯ╳╋ 😇"; printf("%hhu %hhu %hhu %hhu %s\n", c[0], c[1], c[2], c[3], c); - emscripten_run_script( - "var cheez = Module.stringToUTF8OnStack(\"μ†ℱ ╋ℯ╳╋ 😇\");" - "out(UTF8ToString(cheez), Module.getValue(cheez+0, 'i8')&0xff, " - " Module.getValue(cheez+1, 'i8')&0xff, " - " Module.getValue(cheez+2, 'i8')&0xff, " - " Module.getValue(cheez+3, 'i8')&0xff);"); + EM_ASM({ + var cheez = stringToUTF8OnStack("μ†ℱ ╋ℯ╳╋ 😇"); + out(UTF8ToString(cheez), getValue(cheez+0, 'i8')&0xff, + getValue(cheez+1, 'i8')&0xff, + getValue(cheez+2, 'i8')&0xff, + getValue(cheez+3, 'i8')&0xff); + }); } diff --git a/test/test_core.py b/test/test_core.py index 58890ad2ddb27..9d8ecd3d0df3a 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -194,6 +194,8 @@ def metafunc(self, jspi, *args, **kwargs): self.require_jspi() else: self.set_setting('ASYNCIFY') + if self.get_setting('MODULARIZE') == 'instance': + self.skipTest('MODULARIZE=instance is not compatible with ASYNCIFY=1') f(self, *args, **kwargs) parameterize(metafunc, {'': (False,), @@ -211,6 +213,8 @@ def metafunc(self, asyncify, *args, **kwargs): self.require_jspi() elif asyncify == 1: self.set_setting('ASYNCIFY') + if self.get_setting('MODULARIZE') == 'instance': + self.skipTest('MODULARIZE=instance is not compatible with ASYNCIFY=1') else: assert asyncify == 0 f(self, *args, **kwargs) @@ -382,9 +386,10 @@ def assertStartswith(self, output, prefix): def verify_in_strict_mode(self, filename): js = read_file(filename) - filename += '.strict.js' - write_file(filename, '"use strict";\n' + js) - self.run_js(filename) + base, ext = os.path.split(filename) + strict_filename = base + '.strict' + ext + write_file(strict_filename, '"use strict";\n' + js) + self.run_js(strict_filename) def do_core_test(self, testname, **kwargs): self.do_run_in_out_file_test(Path('core', testname), **kwargs) @@ -420,7 +425,8 @@ def test_hello_world(self): self.do_core_test('test_hello_world.c') def test_wasm_synchronous_compilation(self): - self.set_setting('STRICT_JS') + if self.get_setting('MODULARIZE') != 'instance': + self.set_setting('STRICT_JS') self.set_setting('WASM_ASYNC_COMPILATION', 0) self.do_core_test('test_hello_world.c') @@ -1084,6 +1090,7 @@ def test_exceptions_off(self): self.do_runf('core/test_exceptions.cpp', assert_returncode=NON_ZERO) @no_wasmfs('https://github.com/emscripten-core/emscripten/issues/16816') + @no_modularize_instance('MODULARIZE=instance is not compatible with MINIMAL_RUNTIME') def test_exceptions_minimal_runtime(self): self.maybe_closure() self.set_setting('MINIMAL_RUNTIME') @@ -2009,6 +2016,7 @@ def test_runtime_stacksave(self): # Tests that -sMINIMAL_RUNTIME builds can utilize -sALLOW_MEMORY_GROWTH option. @no_4gb('memory growth issues') @no_2gb('memory growth issues') + @no_modularize_instance('MODULARIZE=instance is not compatible with MINIMAL_RUNTIME') def test_minimal_runtime_memorygrowth(self): if self.has_changed_setting('ALLOW_MEMORY_GROWTH'): self.skipTest('test needs to modify memory growth') @@ -2629,6 +2637,7 @@ def test_pthread_tls_dylink(self): self.emcc_args.append('-Wno-experimental') self.do_run_in_out_file_test('pthread/test_pthread_tls_dylink.c') + @no_modularize_instance('uses global Module objecgt') def test_pthread_run_script(self): shutil.copy(test_file('pthread/foo.js'), '.') self.do_runf('pthread/test_pthread_run_script.c') @@ -5647,7 +5656,6 @@ def test_futimens(self): self.do_runf('utime/test_futimens.c', 'success') def test_utf(self): - self.set_setting('EXPORTED_RUNTIME_METHODS', ['getValue', 'setValue', 'UTF8ToString', 'stringToUTF8OnStack']) self.do_core_test('test_utf.c') def test_utf32(self): @@ -5753,6 +5761,7 @@ def test_fs_nodefs_nofollow(self): @crossplatform @requires_node + @no_modularize_instance('expects js filename') def test_fs_nodefs_readdir(self): # externally setup an existing folder structure: existing/a if self.get_setting('WASMFS'): @@ -7105,21 +7114,23 @@ def test(expected, args=None, assert_returncode=0): test('|1|', args=['-DDIRECT']) def test_response_file(self): - response_data = '-o "%s/response_file.js" "%s"' % (self.get_dir(), test_file('hello_world.cpp')) + out_js = self.output_name('response_file') + response_data = '-o "%s" "%s"' % (out_js, test_file('hello_world.cpp')) create_file('rsp_file', response_data.replace('\\', '\\\\')) self.run_process([EMCC, "@rsp_file"] + self.get_emcc_args()) - self.do_run('response_file.js', 'hello, world', no_build=True) + self.do_run(out_js, 'hello, world', no_build=True) self.assertContained('response file not found: foo.txt', self.expect_fail([EMCC, '@foo.txt'])) def test_linker_response_file(self): objfile = 'response_file.o' + out_js = self.output_name('response_file') self.run_process([EMCC, '-c', test_file('hello_world.cpp'), '-o', objfile] + self.get_emcc_args(compile_only=True)) # This should expand into -Wl,--start-group -Wl,--end-group response_data = '--start-group ' + objfile + ' --end-group' create_file('rsp_file', response_data.replace('\\', '\\\\')) - self.run_process([EMCC, "-Wl,@rsp_file", '-o', 'response_file.o.js'] + self.get_emcc_args()) - self.do_run('response_file.o.js', 'hello, world', no_build=True) + self.run_process([EMCC, "-Wl,@rsp_file", '-o', out_js] + self.get_emcc_args()) + self.do_run(out_js, 'hello, world', no_build=True) @no_modularize_instance('uses Module object directly') def test_exported_response(self): @@ -7620,6 +7631,7 @@ def test_embind_wasm_workers(self): 'default': ('DEFAULT', False), 'all_growth': ('ALL', True), }) + @no_modularize_instance('uses Module global') def test_webidl(self, mode, allow_memory_growth): self.set_setting('WASM_ASYNC_COMPILATION', 0) if self.maybe_closure(): @@ -7939,6 +7951,7 @@ def test_modularize_closure_pre(self): self.do_core_test('modularize_closure_pre.c') @no_wasm2js('symbol names look different wasm2js backtraces') + @no_modularize_instance('assumes .js output filename') @also_with_wasm_bigint def test_emscripten_log(self): self.emcc_args += ['-g', '-DRUN_FROM_JS_SHELL', '-Wno-deprecated-pragma'] @@ -8010,6 +8023,7 @@ def test_vswprintf_utf8(self): # Test async sleeps in the presence of invoke_* calls, which can happen with # longjmp or exceptions. + @no_modularize_instance('MODULARIZE=instance is not compatible with ASYNCIFY=1') def test_asyncify_longjmp(self): self.set_setting('ASYNCIFY') self.set_setting('STRICT') @@ -8174,6 +8188,7 @@ def test_async_ccall_promise(self, exit_runtime): self.emcc_args += ['--pre-js', 'pre.js'] self.do_runf('main.c', 'stringf: first\nsecond\n6.4') + @no_modularize_instance('MODULARIZE=instance is not compatible with ASYNCIFY=1') def test_fibers_asyncify(self): self.set_setting('ASYNCIFY') self.maybe_closure() @@ -8184,6 +8199,7 @@ def test_asyncify_unused(self): # test a program not using asyncify, but the pref is set self.do_core_test('test_hello_world.c') + @no_modularize_instance('MODULARIZE=instance is not compatible with ASYNCIFY=1') @parameterized({ 'normal': ([], True), 'removelist_a': (['-sASYNCIFY_REMOVE=["foo(int, double)"]'], False), @@ -8230,6 +8246,7 @@ def test_asyncify_lists(self, args, should_pass, response=None): # virt() manually, rather than have them inferred automatically. 'add_no_prop': (['-sASYNCIFY_IGNORE_INDIRECT', '-sASYNCIFY_ADD=["__original_main","main","virt()"]', '-sASYNCIFY_PROPAGATE_ADD=0'], True), }) + @no_modularize_instance('MODULARIZE=instance is not compatible with ASYNCIFY=1') def test_asyncify_indirect_lists(self, args, should_pass): self.set_setting('ASYNCIFY') self.emcc_args += args @@ -8247,6 +8264,7 @@ def test_asyncify_indirect_lists(self, args, should_pass): raise @with_dylink_reversed + @no_modularize_instance('MODULARIZE=instance is not compatible with ASYNCIFY=1') def test_asyncify_side_module(self): self.set_setting('ASYNCIFY') self.set_setting('ASYNCIFY_IMPORTS', ['my_sleep']) @@ -8276,10 +8294,12 @@ def test_asyncify_side_module(self): ''', 'before sleep\n42\n42\nafter sleep\n', header='void my_sleep(int);', force_c=True) @no_asan('asyncify stack operations confuse asan') + @no_modularize_instance('MODULARIZE=instance is not compatible with ASYNCIFY=1') def test_emscripten_scan_registers(self): self.set_setting('ASYNCIFY') self.do_core_test('test_emscripten_scan_registers.cpp') + @no_modularize_instance('MODULARIZE=instance is not compatible with ASYNCIFY=1') def test_asyncify_assertions(self): self.set_setting('ASYNCIFY') self.set_setting('ASYNCIFY_IMPORTS', ['suspend']) @@ -8288,6 +8308,7 @@ def test_asyncify_assertions(self): @no_lsan('leaks asyncify stack during exit') @no_asan('leaks asyncify stack during exit') + @no_modularize_instance('MODULARIZE=instance is not compatible with ASYNCIFY=1') def test_asyncify_during_exit(self): self.set_setting('ASYNCIFY') self.set_setting('ASSERTIONS') @@ -8423,6 +8444,7 @@ def test_wasm2js(self): @no_sanitize('no wasm2js support yet in sanitizers') @requires_wasm2js + @no_modularize_instance('MODULARIZE is not compatible with MAYBE_WASM2JS') def test_maybe_wasm2js(self): if self.is_wasm2js(): self.skipTest('redundant to test wasm2js in wasm2js* mode') @@ -8430,7 +8452,7 @@ def test_maybe_wasm2js(self): # see that running as wasm works self.do_core_test('test_hello_world.c', emcc_args=['-Wno-deprecated']) # run wasm2js, bundle the code, and use the wasm2js path - cmd = [PYTHON, path_from_root('tools/maybe_wasm2js.py'), 'test_hello_world.js', 'test_hello_world.wasm'] + cmd = [PYTHON, path_from_root('tools/maybe_wasm2js.py'), self.output_name('test_hello_world'), 'test_hello_world.wasm'] if self.is_optimizing(): cmd += ['-O2'] self.run_process(cmd, stdout=open('do_wasm2js.js', 'w')) @@ -8649,15 +8671,14 @@ def test_postrun_exception(self): self.assertContained('ThisFunctionDoesNotExist is not defined', output) def test_postrun_exit_runtime(self): - create_file('post.js', ''' - addOnPostRun(() => err('post run\\n')); - ''') + create_file('pre.js', "Module['postRun'] = () => err('post run\\n');") self.set_setting('EXIT_RUNTIME') - self.emcc_args.append('--post-js=post.js') + self.emcc_args.append('--pre-js=pre.js') self.do_runf('hello_world.c', 'post run') # Tests that building with -sDECLARE_ASM_MODULE_EXPORTS=0 works @also_with_minimal_runtime + @no_modularize_instance('DECLARE_ASM_MODULE_EXPORTS=0 is not compatible with MODULARIZE') def test_no_declare_asm_module_exports(self): self.set_setting('DECLARE_ASM_MODULE_EXPORTS', 0) self.set_setting('WASM_ASYNC_COMPILATION', 0) @@ -8677,6 +8698,7 @@ def test_no_declare_asm_module_exports(self): # Tests that -sMINIMAL_RUNTIME works well in different build modes @no_wasmfs('https://github.com/emscripten-core/emscripten/issues/16816') + @no_modularize_instance('MODULARIZE=instance is not compatible with MINIMAL_RUNTIME') @parameterized({ 'default': ([],), 'streaming': (['-sMINIMAL_RUNTIME_STREAMING_WASM_COMPILATION'],), @@ -8692,6 +8714,7 @@ def test_minimal_runtime_hello_world(self, args): # Test that printf() works in MINIMAL_RUNTIME=1 @no_wasmfs('https://github.com/emscripten-core/emscripten/issues/16816') + @no_modularize_instance('MODULARIZE=instance is not compatible with MINIMAL_RUNTIME') @parameterized({ 'fs': ('FORCE_FILESYSTEM',), 'nofs': ('NO_FILESYSTEM',), @@ -8708,6 +8731,7 @@ def test_minimal_runtime_hello_printf(self, extra_setting): # Tests that -sMINIMAL_RUNTIME works well with SAFE_HEAP @no_wasmfs('https://github.com/emscripten-core/emscripten/issues/16816') + @no_modularize_instance('MODULARIZE=instance is not compatible with MINIMAL_RUNTIME') @no_asan('SAFE_HEAP cannot be used with ASan') def test_minimal_runtime_safe_heap(self): self.set_setting('MINIMAL_RUNTIME') @@ -8722,6 +8746,7 @@ def test_minimal_runtime_safe_heap(self): # Tests global initializer with -sMINIMAL_RUNTIME @no_wasmfs('https://github.com/emscripten-core/emscripten/issues/16816') + @no_modularize_instance('MODULARIZE=instance is not compatible with MINIMAL_RUNTIME') def test_minimal_runtime_global_initializer(self): self.set_setting('MINIMAL_RUNTIME') self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')] @@ -9083,7 +9108,6 @@ def test_pthread_create(self): # test that the node environment can be specified by itself, and that still # works with pthreads (even though we did not specify 'node,worker') self.set_setting('ENVIRONMENT', 'node') - self.set_setting('STRICT_JS') self.set_setting('STRICT') self.do_run_in_out_file_test('core/pthread/create.c') diff --git a/test/test_force_exit.c b/test/test_force_exit.c index 63ede6f040801..da22f5b3cfbbf 100644 --- a/test/test_force_exit.c +++ b/test/test_force_exit.c @@ -32,7 +32,7 @@ int main() { EM_ASM({ // Use callUserCallback here so that ExitStatus is handled correctly - setTimeout(() => callUserCallback(Module._later), 1); + setTimeout(() => callUserCallback(_later), 1); }); printf("exit, but still alive\n"); diff --git a/tools/link.py b/tools/link.py index 3c1384fbb8de3..d8700aee62acd 100644 --- a/tools/link.py +++ b/tools/link.py @@ -828,6 +828,8 @@ def limit_incoming_module_api(): exit_with_error('MODULARIZE=instance is not compatible with -sDYNCALLS') if settings.ASYNCIFY_LAZY_LOAD_CODE: exit_with_error('MODULARIZE=instance is not compatible with -sASYNCIFY_LAZY_LOAD_CODE') + if settings.MINIMAL_RUNTIME: + exit_with_error('MODULARIZE=instance is not compatible with MINIMAL_RUNTIME') if options.use_preload_plugins or len(options.preload_files): exit_with_error('MODULARIZE=instance is not compatible with --embed-file/--preload-file')