diff --git a/ChangeLog.md b/ChangeLog.md index 39586781ad690..9bde8fd1b52df 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -15,6 +15,13 @@ full changeset diff at the end of each section. Current Trunk ------------- + - Breaking change: Do not automatically set EXPORT_ALL for MAIN_MODULES or + SIDE_MODULES. This means that you must explicitly export things that will + be called from outside (normally, on EXPORTED_FUNCTIONS), or + you can manually enable EXPORT_ALL yourself (which returns to the exact + same behavior as before). This change brings us in line with more standard + dynamic linking, and will match what the LLVM wasm backend will have. + See #7312. v1.38.14: 10/22/2018 -------------------- diff --git a/emcc.py b/emcc.py index 7f75e71d91d02..425ba3df944b3 100755 --- a/emcc.py +++ b/emcc.py @@ -1164,7 +1164,6 @@ def check(input_file): if shared.Settings.EMULATED_FUNCTION_POINTERS == 0: shared.Settings.EMULATED_FUNCTION_POINTERS = 2 # by default, use optimized function pointer emulation shared.Settings.ERROR_ON_UNDEFINED_SYMBOLS = shared.Settings.WARN_ON_UNDEFINED_SYMBOLS = 0 - shared.Settings.EXPORT_ALL = 1 if shared.Settings.EMTERPRETIFY: shared.Settings.FINALIZE_ASM_JS = 0 diff --git a/tests/test_browser.py b/tests/test_browser.py index 3d0229fdcd6c8..24c70f9783bac 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -2133,8 +2133,8 @@ def test_runtimelink(self): print(wasm) main, supp = self.setup_runtimelink_test() open('supp.cpp', 'w').write(supp) - run_process([PYTHON, EMCC, 'supp.cpp', '-o', 'supp.' + ('wasm' if wasm else 'js'), '-s', 'SIDE_MODULE=1', '-O2', '-s', 'WASM=%d' % wasm]) - self.btest(main, args=['-DBROWSER=1', '-s', 'MAIN_MODULE=1', '-O2', '-s', 'WASM=%d' % wasm, '-s', 'RUNTIME_LINKED_LIBS=["supp.' + ('wasm' if wasm else 'js') + '"]'], expected='76') + run_process([PYTHON, EMCC, 'supp.cpp', '-o', 'supp.' + ('wasm' if wasm else 'js'), '-s', 'SIDE_MODULE=1', '-O2', '-s', 'WASM=%d' % wasm, '-s', 'EXPORT_ALL=1']) + self.btest(main, args=['-DBROWSER=1', '-s', 'MAIN_MODULE=1', '-O2', '-s', 'WASM=%d' % wasm, '-s', 'RUNTIME_LINKED_LIBS=["supp.' + ('wasm' if wasm else 'js') + '"]', '-s', 'EXPORT_ALL=1'], expected='76') def test_pre_run_deps(self): # Adding a dependency in preRun will delay run @@ -2326,7 +2326,7 @@ def test_emscripten_async_wget2(self): @unittest.skip('non-fastcomp is deprecated and fails in 3.5') def test_module(self): run_process([PYTHON, EMCC, path_from_root('tests', 'browser_module.cpp'), '-o', 'module.js', '-O2', '-s', 'SIDE_MODULE=1', '-s', 'DLOPEN_SUPPORT=1', '-s', 'EXPORTED_FUNCTIONS=["_one", "_two"]']) - self.btest('browser_main.cpp', args=['-O2', '-s', 'MAIN_MODULE=1', '-s', 'DLOPEN_SUPPORT=1'], expected='8') + self.btest('browser_main.cpp', args=['-O2', '-s', 'MAIN_MODULE=1', '-s', 'DLOPEN_SUPPORT=1', '-s', 'EXPORT_ALL=1'], expected='8') def test_preload_module(self): open('library.c', 'w').write(r''' @@ -2335,7 +2335,7 @@ def test_preload_module(self): return 42; } ''') - run_process([PYTHON, EMCC, 'library.c', '-s', 'SIDE_MODULE=1', '-O2', '-o', 'library.wasm', '-s', 'WASM=1']) + run_process([PYTHON, EMCC, 'library.c', '-s', 'SIDE_MODULE=1', '-O2', '-o', 'library.wasm', '-s', 'WASM=1', '-s', 'EXPORT_ALL=1']) os.rename('library.wasm', 'library.so') main = r''' #include @@ -2366,7 +2366,7 @@ def test_preload_module(self): ''' self.btest( main, - args=['-s', 'MAIN_MODULE=1', '--preload-file', '.@/', '-O2', '-s', 'WASM=1', '--use-preload-plugins'], + args=['-s', 'MAIN_MODULE=1', '--preload-file', '.@/', '-O2', '-s', 'WASM=1', '--use-preload-plugins', '-s', 'EXPORT_ALL=1'], expected='0') def test_mmap_file(self): @@ -3294,16 +3294,16 @@ def test_dynamic_link(self): return ret; } ''') - run_process([PYTHON, EMCC, 'side.cpp', '-s', 'SIDE_MODULE=1', '-O2', '-o', 'side.wasm']) - self.btest(self.in_dir('main.cpp'), '2', args=['-s', 'MAIN_MODULE=1', '-O2', '--pre-js', 'pre.js']) + run_process([PYTHON, EMCC, 'side.cpp', '-s', 'SIDE_MODULE=1', '-O2', '-o', 'side.wasm', '-s', 'EXPORT_ALL=1']) + self.btest(self.in_dir('main.cpp'), '2', args=['-s', 'MAIN_MODULE=1', '-O2', '--pre-js', 'pre.js', '-s', 'EXPORT_ALL=1']) print('wasm in worker (we can read binary data synchronously there)') open('pre.js', 'w').write(''' var Module = { dynamicLibraries: ['side.wasm'] }; ''') - run_process([PYTHON, EMCC, 'side.cpp', '-s', 'SIDE_MODULE=1', '-O2', '-o', 'side.wasm', '-s', 'WASM=1']) - self.btest(self.in_dir('main.cpp'), '2', args=['-s', 'MAIN_MODULE=1', '-O2', '--pre-js', 'pre.js', '-s', 'WASM=1', '--proxy-to-worker']) + run_process([PYTHON, EMCC, 'side.cpp', '-s', 'SIDE_MODULE=1', '-O2', '-o', 'side.wasm', '-s', 'WASM=1', '-s', 'EXPORT_ALL=1']) + self.btest(self.in_dir('main.cpp'), '2', args=['-s', 'MAIN_MODULE=1', '-O2', '--pre-js', 'pre.js', '-s', 'WASM=1', '--proxy-to-worker', '-s', 'EXPORT_ALL=1']) print('wasm (will auto-preload since no sync binary reading)') @@ -3311,7 +3311,7 @@ def test_dynamic_link(self): Module.dynamicLibraries = ['side.wasm']; ''') # same wasm side module works - self.btest(self.in_dir('main.cpp'), '2', args=['-s', 'MAIN_MODULE=1', '-O2', '--pre-js', 'pre.js', '-s', 'WASM=1']) + self.btest(self.in_dir('main.cpp'), '2', args=['-s', 'MAIN_MODULE=1', '-O2', '--pre-js', 'pre.js', '-s', 'WASM=1', '-s', 'EXPORT_ALL=1']) @requires_graphics_hardware @no_chrome("required synchronous wasm compilation") @@ -3341,9 +3341,9 @@ def test_dynamic_link_glemu(self): return (const char *)glGetString(GL_EXTENSIONS); } ''') - run_process([PYTHON, EMCC, 'side.cpp', '-s', 'SIDE_MODULE=1', '-O2', '-o', 'side.wasm', '-lSDL']) + run_process([PYTHON, EMCC, 'side.cpp', '-s', 'SIDE_MODULE=1', '-O2', '-o', 'side.wasm', '-lSDL', '-s', 'EXPORT_ALL=1']) - self.btest(self.in_dir('main.cpp'), '1', args=['-s', 'MAIN_MODULE=1', '-O2', '-s', 'LEGACY_GL_EMULATION=1', '-lSDL', '-lGL', '--pre-js', 'pre.js']) + self.btest(self.in_dir('main.cpp'), '1', args=['-s', 'MAIN_MODULE=1', '-O2', '-s', 'LEGACY_GL_EMULATION=1', '-lSDL', '-lGL', '--pre-js', 'pre.js', '-s', 'EXPORT_ALL=1']) def test_memory_growth_during_startup(self): open('data.dat', 'w').write('X' * (30 * 1024 * 1024)) diff --git a/tests/test_core.py b/tests/test_core.py index 48e94bc335ba0..73f38713f9951 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -2426,10 +2426,12 @@ def test_runtimelink(self): def prep_dlfcn_lib(self): self.set_setting('MAIN_MODULE', 0) self.set_setting('SIDE_MODULE', 1) + self.set_setting('EXPORT_ALL', 1) def prep_dlfcn_main(self): self.set_setting('MAIN_MODULE', 1) self.set_setting('SIDE_MODULE', 0) + self.set_setting('EXPORT_ALL', 1) with open('lib_so_pre.js', 'w') as f: f.write(''' @@ -3325,6 +3327,9 @@ def zzztest_dlfcn_exceptions(self): # TODO: make this work. need to forward temp ''') def dylink_test(self, main, side, expected, header=None, main_emcc_args=[], force_c=False, need_reverse=True, auto_load=True): + # shared settings + self.set_setting('EXPORT_ALL', 1) + if header: open('header.h', 'w').write(header) @@ -3800,7 +3805,7 @@ def test_dylink_global_var_jslib(self): void call_side() { printf("side: jslib_x is %d.\n", jslib_x); } - ''', expected=['main: jslib_x is 148.\nside: jslib_x is 148.\n'], main_emcc_args=['--js-library', 'lib.js']) + ''', expected=['main: jslib_x is 148.\nside: jslib_x is 148.\n'], main_emcc_args=['--js-library', 'lib.js', '-s', 'EXPORTED_FUNCTIONS=["_main", "_jslib_x"]']) @needs_dlfcn def test_dylink_many_postSets(self): @@ -4034,7 +4039,7 @@ def test_dylink_hyper_dupe(self): printf("only_in_third_1: %d, %d, %d, %d\n", sidef(), sideg, second_to_third, x); } ''') - run_process([PYTHON, EMCC, 'third.cpp', '-s', 'SIDE_MODULE=1'] + Building.COMPILER_TEST_OPTS + self.emcc_args + ['-o', 'third' + dylib_suffix]) + run_process([PYTHON, EMCC, 'third.cpp', '-s', 'SIDE_MODULE=1', '-s', 'EXPORT_ALL=1'] + Building.COMPILER_TEST_OPTS + self.emcc_args + ['-o', 'third' + dylib_suffix]) self.dylink_test(main=r''' #include diff --git a/tests/test_other.py b/tests/test_other.py index 4cfd3f315bccc..ae673ee02047f 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3004,7 +3004,8 @@ def test_proxyfs(self): '--embed-file', 'proxyfs_embed.txt', '--pre-js', 'proxyfs_pre.js', '-s', 'EXTRA_EXPORTED_RUNTIME_METHODS=["ccall", "cwrap"]', '-s', 'BINARYEN_ASYNC_COMPILATION=0', - '-s', 'MAIN_MODULE=1']) + '-s', 'MAIN_MODULE=1', + '-s', 'EXPORT_ALL=1']) # Following shutil.copyfile just prevent 'require' of node.js from caching js-object. # See https://nodejs.org/api/modules.html shutil.copyfile('proxyfs_test.js', 'proxyfs_test1.js') @@ -6230,7 +6231,7 @@ def test(main_args=[], library_args=[], expected='hello from main\nhello from li #endif } ''') - run_process([PYTHON, EMCC, 'library.c', '-s', 'SIDE_MODULE=1', '-O2', '-o', library_file, '-s', 'WASM=' + str(wasm)] + library_args) + run_process([PYTHON, EMCC, 'library.c', '-s', 'SIDE_MODULE=1', '-O2', '-o', library_file, '-s', 'WASM=' + str(wasm), '-s', 'EXPORT_ALL=1'] + library_args) open('main.c', 'w').write(r''' #include #include @@ -6266,12 +6267,14 @@ def percent_diff(x, y): full = test() # printf is not used in main, but libc was linked in, so it's there printf = test(library_args=['-DUSE_PRINTF']) - # dce in main, and side happens to be ok since it uses puts as well - dce = test(main_args=['-s', 'MAIN_MODULE=2']) + # dce in main, and it fails since puts is not exported + dce = test(main_args=['-s', 'MAIN_MODULE=2'], expected=('cannot', 'undefined')) + # with exporting, it works + dce = test(main_args=['-s', 'MAIN_MODULE=2', '-s', 'EXPORTED_FUNCTIONS=["_main", "_puts"]']) # printf is not used in main, and we dce, so we failz dce_fail = test(main_args=['-s', 'MAIN_MODULE=2'], library_args=['-DUSE_PRINTF'], expected=('cannot', 'undefined')) # exporting printf in main keeps it alive for the library - dce_save = test(main_args=['-s', 'MAIN_MODULE=2', '-s', 'EXPORTED_FUNCTIONS=["_main", "_printf"]'], library_args=['-DUSE_PRINTF']) + dce_save = test(main_args=['-s', 'MAIN_MODULE=2', '-s', 'EXPORTED_FUNCTIONS=["_main", "_printf", "_puts"]'], library_args=['-DUSE_PRINTF']) assert percent_diff(full[0], printf[0]) < 4 assert percent_diff(dce[0], dce_fail[0]) < 4 @@ -6377,10 +6380,10 @@ def test_ld_library_path(self): ''') - run_process([PYTHON, EMCC, '-o', 'libhello1.wasm', 'hello1.c', '-s', 'SIDE_MODULE=1']) - run_process([PYTHON, EMCC, '-o', 'libhello2.wasm', 'hello2.c', '-s', 'SIDE_MODULE=1']) - run_process([PYTHON, EMCC, '-o', 'libhello3.wasm', 'hello3.c', '-s', 'SIDE_MODULE=1']) - run_process([PYTHON, EMCC, '-o', 'libhello4.wasm', 'hello4.c', '-s', 'SIDE_MODULE=1']) + run_process([PYTHON, EMCC, '-o', 'libhello1.wasm', 'hello1.c', '-s', 'SIDE_MODULE=1', '-s', 'EXPORT_ALL=1']) + run_process([PYTHON, EMCC, '-o', 'libhello2.wasm', 'hello2.c', '-s', 'SIDE_MODULE=1', '-s', 'EXPORT_ALL=1']) + run_process([PYTHON, EMCC, '-o', 'libhello3.wasm', 'hello3.c', '-s', 'SIDE_MODULE=1', '-s', 'EXPORT_ALL=1']) + run_process([PYTHON, EMCC, '-o', 'libhello4.wasm', 'hello4.c', '-s', 'SIDE_MODULE=1', '-s', 'EXPORT_ALL=1']) run_process([PYTHON, EMCC, '-o', 'main.js', 'main.c', '-s', 'MAIN_MODULE=1', '-s', 'TOTAL_MEMORY=' + str(32 * 1024 * 1024), '--embed-file', 'libhello1.wasm@/lib/libhello1.wasm', '--embed-file', 'libhello2.wasm@/usr/lib/libhello2.wasm', @@ -6453,8 +6456,8 @@ def test_dlopen_rtld_global(self): } ''') - run_process([PYTHON, EMCC, '-o', 'libhello1.js', 'hello1.c', '-s', 'SIDE_MODULE=1', '-s', 'WASM=0']) - run_process([PYTHON, EMCC, '-o', 'libhello2.js', 'hello2.c', '-s', 'SIDE_MODULE=1', '-s', 'WASM=0']) + run_process([PYTHON, EMCC, '-o', 'libhello1.js', 'hello1.c', '-s', 'SIDE_MODULE=1', '-s', 'WASM=0', '-s', 'EXPORT_ALL=1']) + run_process([PYTHON, EMCC, '-o', 'libhello2.js', 'hello2.c', '-s', 'SIDE_MODULE=1', '-s', 'WASM=0', '-s', 'EXPORT_ALL=1']) run_process([PYTHON, EMCC, '-o', 'main.js', 'main.c', '-s', 'MAIN_MODULE=1', '-s', 'WASM=0', '--embed-file', 'libhello1.js', '--embed-file', 'libhello2.js']) @@ -8245,7 +8248,7 @@ def test(filename, expectations): 0, [], ['tempDoublePtr', 'waka'], 8, 0, 0, 0), # noqa; totally empty! # but we don't metadce with linkable code! other modules may want it (['-O3', '-s', 'MAIN_MODULE=1'], - 1489, ['invoke_v'], ['waka'], 469663, 149, 1443, None), # noqa; don't compare the # of functions in a main module, which changes a lot + 1489, ['invoke_v'], ['waka'], 226057, 30, 75, None), # noqa; don't compare the # of functions in a main module, which changes a lot ]) # noqa print('test on a minimal pure computational thing') @@ -8286,9 +8289,9 @@ def test_legalize_js_ffi(self): # test disabling of JS FFI legalization wasm_dis = os.path.join(Building.get_binaryen_bin(), 'wasm-dis') for (args, js_ffi) in [ - (['-s', 'LEGALIZE_JS_FFI=1', '-s', 'SIDE_MODULE=1', '-O2'], True), - (['-s', 'LEGALIZE_JS_FFI=0', '-s', 'SIDE_MODULE=1', '-O2'], False), - (['-s', 'LEGALIZE_JS_FFI=0', '-s', 'SIDE_MODULE=1', '-O0'], False), + (['-s', 'LEGALIZE_JS_FFI=1', '-s', 'SIDE_MODULE=1', '-O2', '-s', 'EXPORT_ALL=1'], True), + (['-s', 'LEGALIZE_JS_FFI=0', '-s', 'SIDE_MODULE=1', '-O2', '-s', 'EXPORT_ALL=1'], False), + (['-s', 'LEGALIZE_JS_FFI=0', '-s', 'SIDE_MODULE=1', '-O0', '-s', 'EXPORT_ALL=1'], False), (['-s', 'LEGALIZE_JS_FFI=0', '-s', 'WARN_ON_UNDEFINED_SYMBOLS=0', '-O0'], False), ]: if self.is_wasm_backend() and 'SIDE_MODULE=1' in args: