From f06da924922f7cca20bdfcd8e0d87d4c1ba9ecc8 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 9 Sep 2025 09:52:37 -0700 Subject: [PATCH] Don't build MAIN_MODULE as RELOCATABLE --- emcc.py | 2 +- src/jsifier.mjs | 12 +- src/lib/libcore.js | 19 ++- src/lib/libdylink.js | 86 ++++++++---- src/lib/libglemu.js | 2 +- src/lib/libpthread.js | 2 +- src/modules.mjs | 2 +- src/preamble.js | 30 +++- src/runtime_debug.js | 8 +- test/codesize/test_codesize_cxx_except.json | 8 +- test/codesize/test_codesize_cxx_mangle.json | 8 +- test/codesize/test_codesize_hello_dylink.json | 71 ++++------ .../test_codesize_hello_dylink_all.json | 32 +---- .../test_codesize_minimal_pthreads.json | 8 +- ...t_codesize_minimal_pthreads_memgrowth.json | 8 +- test/common.py | 18 --- test/core/test_dlfcn_self.exports | 2 + test/core/test_relocatable_void_function.c | 26 ---- test/test_core.py | 5 - test/test_other.py | 132 +++++++++--------- tools/building.py | 11 +- tools/cache.py | 2 +- tools/compile.py | 4 +- tools/emscripten.py | 6 +- tools/link.py | 22 ++- tools/system_libs.py | 6 +- 26 files changed, 260 insertions(+), 272 deletions(-) delete mode 100644 test/core/test_relocatable_void_function.c diff --git a/emcc.py b/emcc.py index 2f806e28f0f64..301fc71e0d3c4 100644 --- a/emcc.py +++ b/emcc.py @@ -421,7 +421,7 @@ def phase_setup(options, state): 'unused-command-line-argument', "linker flag ignored during compilation: '%s'" % arg) - if settings.MAIN_MODULE or settings.SIDE_MODULE: + if settings.SIDE_MODULE: settings.RELOCATABLE = 1 if 'USE_PTHREADS' in user_settings: diff --git a/src/jsifier.mjs b/src/jsifier.mjs index 627c740fe5c1c..c92f2e5bbd2fb 100644 --- a/src/jsifier.mjs +++ b/src/jsifier.mjs @@ -121,7 +121,7 @@ function isDefined(symName) { } // 'invoke_' symbols are created at runtime in library_dylink.py so can // always be considered as defined. - if (RELOCATABLE && symName.startsWith('invoke_')) { + if ((MAIN_MODULE || RELOCATABLE) && symName.startsWith('invoke_')) { return true; } return false; @@ -573,7 +573,7 @@ function(${args}) { if (!LibraryManager.library.hasOwnProperty(symbol)) { const isWeakImport = WEAK_IMPORTS.has(symbol); if (!isDefined(symbol) && !isWeakImport) { - if (PROXY_TO_PTHREAD && !MAIN_MODULE && symbol == '__main_argc_argv') { + if (PROXY_TO_PTHREAD && !(MAIN_MODULE || RELOCATABLE) && symbol == '__main_argc_argv') { error('PROXY_TO_PTHREAD proxies main() for you, but no main exists'); return; } @@ -604,7 +604,7 @@ function(${args}) { // emit a stub that will fail at runtime var stubFunctionBody = `abort('missing function: ${symbol}');` - if (RELOCATABLE) { + if (RELOCATABLE || MAIN_MODULE) { // Create a stub for this symbol which can later be replaced by the // dynamic linker. If this stub is called before the symbol is // resolved assert in debug builds or trap in release builds. @@ -763,8 +763,8 @@ function(${args}) { contentText = 'export ' + contentText; } - // Relocatable code needs signatures to create proper wrappers. - if (sig && RELOCATABLE) { + // Dynamic linking needs signatures to create proper wrappers. + if (sig && (MAIN_MODULE || RELOCATABLE)) { if (!WASM_BIGINT) { sig = sig[0].replace('j', 'i') + sig.slice(1).replace(/j/g, 'ii'); } @@ -775,7 +775,7 @@ function(${args}) { } if (isStub) { contentText += `\n${mangled}.stub = true;`; - if (ASYNCIFY && MAIN_MODULE) { + if (ASYNCIFY && (MAIN_MODULE || RELOCATABLE)) { contentText += `\nasyncifyStubs['${symbol}'] = undefined;`; } } diff --git a/src/lib/libcore.js b/src/lib/libcore.js index ef8c6d9893819..d541d536246bf 100644 --- a/src/lib/libcore.js +++ b/src/lib/libcore.js @@ -1773,6 +1773,9 @@ addToLibrary({ }, $dynCall: (sig, ptr, args = [], promising = false) => { +#if ASSERTIONS + assert(ptr, `null function pointer in dynCall`); +#endif #if ASSERTIONS && (DYNCALLS || !WASM_BIGINT || !JSPI) assert(!promising, 'async dynCall is not supported in this mode') #endif @@ -2185,6 +2188,17 @@ addToLibrary({ #endif }, +#if MAIN_MODULE || RELOCATABLE +#if WASM_EXCEPTIONS + // In dynamic linking we define tags here and feed them to each module + __cpp_exception: "new WebAssembly.Tag({'parameters': ['{{{ POINTER_WASM_TYPE }}}']})", +#endif + +#if SUPPORT_LONGJMP == 'wasm' + __c_longjmp: "new WebAssembly.Tag({'parameters': ['{{{ POINTER_WASM_TYPE }}}']})", +#endif +#endif + #if RELOCATABLE // Globals that are normally exported from the wasm module but in relocatable // mode are created here and imported by the module. @@ -2208,11 +2222,12 @@ addToLibrary({ __stack_high: '{{{ STACK_HIGH }}}', __stack_low: '{{{ STACK_LOW }}}', __global_base: '{{{ GLOBAL_BASE }}}', -#if ASYNCIFY == 1 +#endif // RELOCATABLE + +#if (MAIN_MODULE || RELOCATABLE) && ASYNCIFY == 1 __asyncify_state: "new WebAssembly.Global({'value': 'i32', 'mutable': true}, 0)", __asyncify_data: "new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true}, {{{ to64(0) }}})", #endif -#endif // RELOCATABLE _emscripten_fs_load_embedded_files__deps: ['$FS', '$PATH'], _emscripten_fs_load_embedded_files: (ptr) => { diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index a0e19f63197c0..d4631eb280dc1 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -6,8 +6,8 @@ * Dynamic library loading */ -#if !RELOCATABLE -#error "library_dylink.js requires RELOCATABLE" +#if !MAIN_MODULE && !RELOCATABLE +#error "library_dylink.js requires MAIN_MODULE or RELOCATABLE" #endif var LibraryDylink = { @@ -170,10 +170,10 @@ var LibraryDylink = { get(obj, symName) { var rtn = GOT[symName]; if (!rtn) { - rtn = GOT[symName] = new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true}); #if DYLINK_DEBUG == 2 - dbg("new GOT entry: " + symName); + dbg(`new GOT entry: ${symName}`); #endif + rtn = GOT[symName] = new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true}, {{{ to64(-1) }}}); } if (!currentModuleWeakSymbols.has(symName)) { // Any non-weak reference to a symbol marks it as `required`, which @@ -189,6 +189,11 @@ var LibraryDylink = { $isInternalSym: (symName) => { // TODO: find a way to mark these in the binary or avoid exporting them. return [ + 'memory', + '__memory_base', + '__table_base', + '__stack_pointer', + '__indirect_function_table', '__cpp_exception', '__c_longjmp', '__wasm_apply_data_relocs', @@ -230,8 +235,8 @@ var LibraryDylink = { } #endif - GOT[symName] ||= new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true}); - if (replace || GOT[symName].value == 0) { + if (replace || !GOT[symName] || GOT[symName].value == {{{ to64(-1) }}}) { + GOT[symName] ||= new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true}, {{{ to64(-1) }}}); #if DYLINK_DEBUG == 2 dbg(`updateGOT: before: ${symName} : ${GOT[symName].value}`); #endif @@ -265,26 +270,30 @@ var LibraryDylink = { $relocateExports__deps: ['$updateGOT'], $relocateExports__docs: '/** @param {boolean=} replace */', $relocateExports: (exports, memoryBase, replace) => { +#if DYLINK_DEBUG + dbg('relocateExports', memoryBase); +#endif var relocated = {}; + var absSymbols = ['__stack_pointer']; for (var e in exports) { var value = exports[e]; + if (!absSymbols.includes(e) #if SPLIT_MODULE - // Do not modify exports synthesized by wasm-split - if (e.startsWith('%')) { - relocated[e] = value - continue; - } -#endif - if (typeof value?.value != 'undefined') { - // a breaking change in the wasm spec, globals are now objects - // https://github.com/WebAssembly/mutable-global/issues/1 - value = value.value; - } - if (typeof value == {{{ POINTER_JS_TYPE }}}) { - value += {{{ to64('memoryBase') }}}; + // Do not modify exports synthesized by wasm-split + && !e.startsWith('%') +#endif + ) { + if (typeof value?.value != 'undefined') { + // a breaking change in the wasm spec, globals are now objects + // https://github.com/WebAssembly/mutable-global/issues/1 + value = value.value; + } + if (memoryBase && typeof value == {{{ POINTER_JS_TYPE }}}) { + value += {{{ to64('memoryBase') }}}; + } } - relocated[e] = value; + relocated[e] = value } updateGOT(relocated, replace); return relocated; @@ -297,13 +306,17 @@ var LibraryDylink = { dbg('reportUndefinedSymbols'); #endif for (var [symName, entry] of Object.entries(GOT)) { - if (entry.value == 0) { + if (entry.value == {{{ to64(-1) }}}) { +#if DYLINK_DEBUG + dbg(`undef GOT entry: ${symName}`); +#endif var value = resolveGlobalSymbol(symName, true).sym; if (!value && !entry.required) { // Ignore undefined symbols that are imported as weak. #if DYLINK_DEBUG dbg('ignoring undefined weak symbol:', symName); #endif + entry.value = 0; continue; } #if ASSERTIONS @@ -325,7 +338,7 @@ var LibraryDylink = { entry.value = value; #endif } else { - throw new Error(`bad export type for '${symName}': ${typeof value}`); + throw new Error(`bad export type for '${symName}': ${typeof value} (${value})`); } } } @@ -372,7 +385,7 @@ var LibraryDylink = { // Allocate memory even if malloc isn't ready yet. The allocated memory here // must be zero initialized since its used for all static data, including bss. $getMemory__noleakcheck: true, - $getMemory__deps: ['$GOT', '__heap_base', '$alignMemory', 'calloc'], + $getMemory__deps: ['$GOT', 'emscripten_get_sbrk_ptr', '__heap_base', '$alignMemory', 'calloc'], $getMemory: (size) => { // After the runtime is initialized, we must only use sbrk() normally. #if DYLINK_DEBUG @@ -384,14 +397,21 @@ var LibraryDylink = { // avoid having this reported as leak. return _calloc(size, 1); } - var ret = ___heap_base; + var ret = GOT['__heap_base'].value; // Keep __heap_base stack aligned. var end = ret + alignMemory(size, {{{ STACK_ALIGN }}}); #if ASSERTIONS assert(end <= HEAP8.length, 'failure to getMemory - memory growth etc. is not supported there, call malloc/sbrk directly or increase INITIAL_MEMORY'); #endif - ___heap_base = end; GOT['__heap_base'].value = {{{ to64('end') }}}; +#if PTHREADS + if (!ENVIRONMENT_IS_PTHREAD) { +#endif + var sbrk_ptr = _emscripten_get_sbrk_ptr(); + {{{ makeSetValue('sbrk_ptr', 0, 'end', '*') }}} +#if PTHREADS + } +#endif return ret; }, @@ -614,7 +634,7 @@ var LibraryDylink = { ], $loadWebAssemblyModule: (binary, flags, libName, localScope, handle) => { #if DYLINK_DEBUG - dbg('loadWebAssemblyModule:', libName); + dbg('loadWebAssemblyModule:', libName, handle); #endif var metadata = getDylinkMetadata(binary); @@ -633,6 +653,9 @@ var LibraryDylink = { // exclusive access to it for the duration of this function. See the // locking in `dynlink.c`. var firstLoad = !handle || !{{{ makeGetValue('handle', C_STRUCTS.dso.mem_allocated, 'i8') }}}; +#if DYLINK_DEBUG + dbg('firstLoad:', firstLoad); +#endif if (firstLoad) { #endif // alignments are powers of 2 @@ -860,18 +883,27 @@ var LibraryDylink = { if (applyRelocs) { if (runtimeInitialized) { #if DYLINK_DEBUG - dbg('applyRelocs'); + dbg('running __wasm_apply_data_relocs'); #endif applyRelocs(); } else { +#if DYLINK_DEBUG + dbg('delaying __wasm_apply_data_relocs'); +#endif __RELOC_FUNCS__.push(applyRelocs); } } var init = moduleExports['__wasm_call_ctors']; if (init) { if (runtimeInitialized) { +#if DYLINK_DEBUG + dbg('running __wasm_call_ctors'); +#endif init(); } else { +#if DYLINK_DEBUG + dbg('delaying __wasm_call_ctors'); +#endif // we aren't ready to run compiled code yet addOnPostCtor(init); } diff --git a/src/lib/libglemu.js b/src/lib/libglemu.js index b3f6ff60fd867..8265a6ce6e019 100644 --- a/src/lib/libglemu.js +++ b/src/lib/libglemu.js @@ -10,7 +10,7 @@ assert(!FULL_ES3, 'cannot emulate both ES3 and legacy GL'); {{{ const copySigs = (func) => { - if (!RELOCATABLE) return ''; + if (!MAIN_MODULE) return ''; return ` _${func}.sig = _emscripten_${func}.sig = orig_${func}.sig;`; }; const fromPtr = (arg) => { diff --git a/src/lib/libpthread.js b/src/lib/libpthread.js index b4885c15f0a15..e7895cbd26798 100644 --- a/src/lib/libpthread.js +++ b/src/lib/libpthread.js @@ -584,7 +584,7 @@ var LibraryPThread = { #if MAIN_MODULE $registerTLSInit: (tlsInitFunc, moduleExports, metadata) => { #if DYLINK_DEBUG - dbg("registerTLSInit: " + tlsInitFunc); + dbg('registerTLSInit:', tlsInitFunc, metadata.tlsExports); #endif // In relocatable builds, we use the result of calling tlsInitFunc // (`_emscripten_tls_init`) to relocate the TLS exports of the module diff --git a/src/modules.mjs b/src/modules.mjs index 1aa031dcecfb4..3a473855e80bb 100644 --- a/src/modules.mjs +++ b/src/modules.mjs @@ -93,7 +93,7 @@ function calculateLibraries() { libraries.push('libsyscall.js'); } - if (RELOCATABLE) { + if (MAIN_MODULE || RELOCATABLE) { libraries.push('libdylink.js'); } diff --git a/src/preamble.js b/src/preamble.js index fb8954566aa82..e61271953ea1d 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -14,7 +14,7 @@ // An online HTML version (which may be of a different version of Emscripten) // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html -#if RELOCATABLE +#if MAIN_MODULE {{{ makeModuleReceiveWithVar('dynamicLibraries', undefined, '[]') }}} #endif @@ -108,7 +108,7 @@ assert(globalThis.Int32Array && globalThis.Float64Array && Int32Array.prototype. 'JS engine does not provide full typed array support'); #endif -#if RELOCATABLE +#if RELOCATABLE || MAIN_MODULE var __RELOC_FUNCS__ = []; #endif @@ -155,7 +155,7 @@ function initRuntime() { checkStackCookie(); #endif -#if RELOCATABLE +#if MAIN_MODULE callRuntimeCallbacks(__RELOC_FUNCS__); #endif @@ -167,9 +167,15 @@ function initRuntime() { #else wasmExports['__wasm_call_ctors'](); #endif +#if RUNTIME_DEBUG + dbg('done __wasm_call_ctors'); +#endif #endif <<< ATPOSTCTORS >>> +#if RUNTIME_DEBUG + dbg('done ATPOSTCTORS'); +#endif } #if HAS_MAIN @@ -664,7 +670,7 @@ function getWasmImports() { #if SPLIT_MODULE 'placeholder': new Proxy({}, splitModuleProxyHandler), #endif -#if RELOCATABLE +#if MAIN_MODULE || RELOCATABLE 'GOT.mem': new Proxy(wasmImports, GOTHandler), 'GOT.func': new Proxy(wasmImports, GOTHandler), #endif @@ -681,8 +687,18 @@ function getWasmImports() { function receiveInstance(instance, module) { wasmExports = instance.exports; -#if RELOCATABLE - wasmExports = relocateExports(wasmExports, {{{ GLOBAL_BASE }}}); +#if '$wasmTable' in addedLibraryItems && !RELOCATABLE + wasmTable = wasmExports['__indirect_function_table']; + {{{ receivedSymbol('wasmTable') }}} +#if ASSERTIONS && !PURE_WASI + assert(wasmTable, 'table not found in wasm exports'); +#endif +#endif + +#if MAIN_MODULE + // No relocation needed here.. but calling this just so that updateGOT is + // called. + wasmExports = relocateExports(wasmExports, 0); #endif #if ASYNCIFY @@ -771,7 +787,7 @@ function getWasmImports() { assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); trueModule = null; #endif -#if SHARED_MEMORY || RELOCATABLE +#if SHARED_MEMORY || MAIN_MODULE return receiveInstance(result['instance'], result['module']); #else // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line. diff --git a/src/runtime_debug.js b/src/runtime_debug.js index c935295f804f0..a6e6a1823aba2 100644 --- a/src/runtime_debug.js +++ b/src/runtime_debug.js @@ -17,7 +17,13 @@ function dbg(...args) { // TODO(sbc): Unify with err/out implementation in shell.sh. var fs = require('fs'); var utils = require('util'); - var stringify = (a) => typeof a == 'object' ? utils.inspect(a) : a; + function stringify(a) { + switch (typeof a) { + case 'object': return utils.inspect(a); + case 'undefined': return 'undefined'; + } + return a; + } fs.writeSync(2, args.map(stringify).join(' ') + '\n'); } else #endif diff --git a/test/codesize/test_codesize_cxx_except.json b/test/codesize/test_codesize_cxx_except.json index 3cf50e085bf85..6c93f97658368 100644 --- a/test/codesize/test_codesize_cxx_except.json +++ b/test/codesize/test_codesize_cxx_except.json @@ -1,10 +1,10 @@ { - "a.out.js": 23325, - "a.out.js.gz": 9128, + "a.out.js": 23359, + "a.out.js.gz": 9127, "a.out.nodebug.wasm": 171271, "a.out.nodebug.wasm.gz": 57338, - "total": 194596, - "total_gz": 66466, + "total": 194630, + "total_gz": 66465, "sent": [ "__cxa_begin_catch", "__cxa_end_catch", diff --git a/test/codesize/test_codesize_cxx_mangle.json b/test/codesize/test_codesize_cxx_mangle.json index 0b993be3b0329..780ee1423e7ff 100644 --- a/test/codesize/test_codesize_cxx_mangle.json +++ b/test/codesize/test_codesize_cxx_mangle.json @@ -1,10 +1,10 @@ { - "a.out.js": 23375, - "a.out.js.gz": 9148, + "a.out.js": 23409, + "a.out.js.gz": 9146, "a.out.nodebug.wasm": 235312, "a.out.nodebug.wasm.gz": 78933, - "total": 258687, - "total_gz": 88081, + "total": 258721, + "total_gz": 88079, "sent": [ "__cxa_begin_catch", "__cxa_end_catch", diff --git a/test/codesize/test_codesize_hello_dylink.json b/test/codesize/test_codesize_hello_dylink.json index 72b36bbfdb613..d21eb0e6ce365 100644 --- a/test/codesize/test_codesize_hello_dylink.json +++ b/test/codesize/test_codesize_hello_dylink.json @@ -1,50 +1,36 @@ { - "a.out.js": 26931, - "a.out.js.gz": 11472, - "a.out.nodebug.wasm": 18567, - "a.out.nodebug.wasm.gz": 9199, - "total": 45498, - "total_gz": 20671, + "a.out.js": 26316, + "a.out.js.gz": 11272, + "a.out.nodebug.wasm": 17422, + "a.out.nodebug.wasm.gz": 8750, + "total": 43738, + "total_gz": 20022, "sent": [ - "__heap_base", - "__indirect_function_table", - "__memory_base", - "__stack_high", - "__stack_low", - "__stack_pointer", - "__syscall_stat64", - "__table_base", - "emscripten_resize_heap", - "environ_get", - "environ_sizes_get", - "fd_write", - "memory" + "a (fd_write)", + "b (emscripten_resize_heap)", + "c (environ_sizes_get)", + "d (environ_get)", + "e (__syscall_stat64)" ], "imports": [ - "GOT.mem.__heap_base", - "GOT.mem.__stack_high", - "GOT.mem.__stack_low", - "env.__indirect_function_table", - "env.__memory_base", - "env.__stack_pointer", - "env.__syscall_stat64", - "env.__table_base", - "env.emscripten_resize_heap", - "env.memory", - "wasi_snapshot_preview1.environ_get", - "wasi_snapshot_preview1.environ_sizes_get", - "wasi_snapshot_preview1.fd_write" + "a (fd_write)", + "b (emscripten_resize_heap)", + "c (environ_sizes_get)", + "d (environ_get)", + "e (__syscall_stat64)" ], "exports": [ - "__wasm_apply_data_relocs", - "__wasm_call_ctors", - "_emscripten_find_dylib", - "_emscripten_stack_alloc", - "_emscripten_stack_restore", - "calloc", - "emscripten_stack_get_current", - "main", - "setThrew" + "f (memory)", + "g (__wasm_call_ctors)", + "h (main)", + "i (__indirect_function_table)", + "j (_emscripten_find_dylib)", + "k (calloc)", + "l (emscripten_get_sbrk_ptr)", + "m (setThrew)", + "n (_emscripten_stack_restore)", + "o (_emscripten_stack_alloc)", + "p (emscripten_stack_get_current)" ], "funcs": [ "$__emscripten_stdout_close", @@ -55,14 +41,13 @@ "$__stdio_write", "$__strchrnul", "$__towrite", - "$__wasm_apply_data_relocs", "$__wasm_call_ctors", - "$__wasm_start", "$_emscripten_find_dylib", "$_emscripten_stack_alloc", "$_emscripten_stack_restore", "$dlcalloc", "$dlmalloc", + "$emscripten_get_sbrk_ptr", "$emscripten_stack_get_current", "$fmt_fp", "$fmt_u", diff --git a/test/codesize/test_codesize_hello_dylink_all.json b/test/codesize/test_codesize_hello_dylink_all.json index f07e4dfa5ee9d..de9d5157debc4 100644 --- a/test/codesize/test_codesize_hello_dylink_all.json +++ b/test/codesize/test_codesize_hello_dylink_all.json @@ -1,7 +1,7 @@ { - "a.out.js": 245841, - "a.out.nodebug.wasm": 597746, - "total": 843587, + "a.out.js": 254677, + "a.out.nodebug.wasm": 574038, + "total": 828715, "sent": [ "IMG_Init", "IMG_Load", @@ -215,13 +215,6 @@ "__asctime_r", "__assert_fail", "__call_sighandler", - "__global_base", - "__heap_base", - "__indirect_function_table", - "__memory_base", - "__stack_high", - "__stack_low", - "__stack_pointer", "__syscall__newselect", "__syscall_accept4", "__syscall_bind", @@ -271,7 +264,6 @@ "__syscall_truncate64", "__syscall_unlinkat", "__syscall_utimensat", - "__table_base", "_abort_js", "_dlopen_js", "_dlsym_catchup_js", @@ -1118,7 +1110,6 @@ "glutTimerFunc", "lineColor", "lineRGBA", - "memory", "pixelRGBA", "proc_exit", "random_get", @@ -1411,14 +1402,8 @@ "GOT.func.emscripten_glVertexAttribPointer", "GOT.func.emscripten_glViewport", "GOT.func.emscripten_out", - "GOT.mem.__heap_base", - "GOT.mem.__stack_high", - "GOT.mem.__stack_low", "env.__assert_fail", "env.__call_sighandler", - "env.__indirect_function_table", - "env.__memory_base", - "env.__stack_pointer", "env.__syscall__newselect", "env.__syscall_accept4", "env.__syscall_bind", @@ -1468,7 +1453,6 @@ "env.__syscall_truncate64", "env.__syscall_unlinkat", "env.__syscall_utimensat", - "env.__table_base", "env._abort_js", "env._dlopen_js", "env._dlsym_js", @@ -1500,7 +1484,6 @@ "env.emscripten_wget_data", "env.exit", "env.getnameinfo", - "env.memory", "wasi_snapshot_preview1.clock_res_get", "wasi_snapshot_preview1.clock_time_get", "wasi_snapshot_preview1.environ_get", @@ -1729,6 +1712,7 @@ "__gtsf2", "__gttf2", "__h_errno_location", + "__indirect_function_table", "__intscan", "__isalnum_l", "__isalpha_l", @@ -1852,6 +1836,7 @@ "__small_vsprintf", "__stack_chk_fail", "__stack_chk_guard", + "__stack_pointer", "__strcasecmp_l", "__strcoll_l", "__strerror_l", @@ -1953,7 +1938,6 @@ "__wasi_fd_is_valid", "__wasi_syscall_ret", "__wasi_timestamp_to_timespec", - "__wasm_apply_data_relocs", "__wasm_call_ctors", "__wasm_setjmp", "__wasm_setjmp_test", @@ -2714,6 +2698,7 @@ "memcpy", "memmem", "memmove", + "memory", "mempcpy", "memrchr", "memset", @@ -3624,7 +3609,6 @@ "$__libc_current_sigrtmax", "$__libc_current_sigrtmin", "$__llvm_profile_get_num_counters", - "$__loc_is_allocated", "$__localtime_r", "$__lookup_ipliteral", "$__lseek", @@ -3813,11 +3797,9 @@ "$__wasi_fd_is_valid", "$__wasi_syscall_ret", "$__wasi_timestamp_to_timespec", - "$__wasm_apply_data_relocs", "$__wasm_call_ctors", "$__wasm_setjmp", "$__wasm_setjmp_test", - "$__wasm_start", "$__wcscoll_l", "$__wcsftime_l", "$__wcsxfrm_l", @@ -4450,7 +4432,6 @@ "$login_tty", "$logl", "$lookup", - "$lprofBufferIOWrite", "$lprofBufferWriter", "$lprofLockFileHandle", "$lprofMergeValueProfData", @@ -4689,7 +4670,6 @@ "$roundf", "$roundl", "$rsh", - "$savestate", "$sbrk", "$scalb", "$scalbf", diff --git a/test/codesize/test_codesize_minimal_pthreads.json b/test/codesize/test_codesize_minimal_pthreads.json index c0c67fbef525f..07818d1ddff41 100644 --- a/test/codesize/test_codesize_minimal_pthreads.json +++ b/test/codesize/test_codesize_minimal_pthreads.json @@ -1,10 +1,10 @@ { - "a.out.js": 7609, - "a.out.js.gz": 3762, + "a.out.js": 7616, + "a.out.js.gz": 3765, "a.out.nodebug.wasm": 19599, "a.out.nodebug.wasm.gz": 9065, - "total": 27208, - "total_gz": 12827, + "total": 27215, + "total_gz": 12830, "sent": [ "a (memory)", "b (emscripten_get_now)", diff --git a/test/codesize/test_codesize_minimal_pthreads_memgrowth.json b/test/codesize/test_codesize_minimal_pthreads_memgrowth.json index 61156825e3e29..738b88041ed7a 100644 --- a/test/codesize/test_codesize_minimal_pthreads_memgrowth.json +++ b/test/codesize/test_codesize_minimal_pthreads_memgrowth.json @@ -1,10 +1,10 @@ { - "a.out.js": 8036, - "a.out.js.gz": 3962, + "a.out.js": 8043, + "a.out.js.gz": 3967, "a.out.nodebug.wasm": 19600, "a.out.nodebug.wasm.gz": 9066, - "total": 27636, - "total_gz": 13028, + "total": 27643, + "total_gz": 13033, "sent": [ "a (memory)", "b (emscripten_get_now)", diff --git a/test/common.py b/test/common.py index ea0facb8f7086..740a6627ff7ea 100644 --- a/test/common.py +++ b/test/common.py @@ -1967,24 +1967,6 @@ def ccshared(src, linkto=None): ccshared('libc.c', ['liba' + so]) self.set_setting('MAIN_MODULE') - extra_args = ['-L.', 'libb' + so, 'libc' + so] - do_run(r''' - #ifdef __cplusplus - extern "C" { - #endif - void bfunc(); - void cfunc(); - #ifdef __cplusplus - } - #endif - - int test_main() { - bfunc(); - cfunc(); - return 0; - } - ''', - 'a: loaded\na: b (prev: (null))\na: c (prev: b)\n', cflags=extra_args) extra_args = [] for libname in ('liba', 'libb', 'libc'): diff --git a/test/core/test_dlfcn_self.exports b/test/core/test_dlfcn_self.exports index 7c1ea900be697..0bb3488384e51 100644 --- a/test/core/test_dlfcn_self.exports +++ b/test/core/test_dlfcn_self.exports @@ -2,6 +2,7 @@ __THREW__ ___environ __daylight __environ +__heap_base __optpos __optreset __progname @@ -10,6 +11,7 @@ __sig_actions __sig_pending __signgam __stack_chk_guard +__stack_pointer __threwValue __timezone __tzname diff --git a/test/core/test_relocatable_void_function.c b/test/core/test_relocatable_void_function.c deleted file mode 100644 index 094d422c001bd..0000000000000 --- a/test/core/test_relocatable_void_function.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2016 The Emscripten Authors. All rights reserved. - * Emscripten is available under two separate licenses, the MIT license and the - * University of Illinois/NCSA Open Source License. Both these licenses can be - * found in the LICENSE file. - */ - -#include -#include - -void hi_world() { - puts("hi world"); -} - -int main() { - hi_world(); - - // Also test an indirect call. Taking the function by reference makes us go - // through more code paths that could have bugs, like relocatable code needing - // to make wrapper functions for function pointers, which need signatures for - // an imported function from JS. - void (*func)(const char*) = &emscripten_console_log; - func("indirect import"); - - return 0; -} diff --git a/test/test_core.py b/test/test_core.py index 0c9611728978a..3dc4fd3822069 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -6602,11 +6602,6 @@ def test_cubescript(self): self.do_runf('third_party/cubescript/command.cpp', '*\nTemp is 33\n9\n5\nhello, everyone\n*') - @needs_dylink - def test_relocatable_void_function(self): - self.set_setting('RELOCATABLE') - self.do_core_test('test_relocatable_void_function.c', cflags=['-Wno-deprecated']) - @wasm_simd @parameterized({ '': ([],), diff --git a/test/test_other.py b/test/test_other.py index bf43c75bf3c81..4922f14bbb192 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -2127,9 +2127,12 @@ def test_dylink_pthread_static_data(self): # * The global object must have a constructor to make sure that it is # constructed only once (and not once per thread). create_file('side.c', r''' + #include + int value = 0; __attribute__((constructor)) void ctor(void) { + emscripten_dbgf("side module ctor: %p", &value); value = 42; } @@ -2147,14 +2150,17 @@ def test_dylink_pthread_static_data(self): int* get_address(); void* thread_main(void* arg) { - assert(*get_address() == 123); - printf("%d\n", *get_address()); + int* addr = get_address(); + printf("thread_main: %p, %d\n", addr, *addr); + assert(*addr == 123); return NULL; } int main() { - assert(*get_address() == 42); - *get_address() = 123; + int* addr = get_address(); + printf("in main: %p, %d\n", addr, *addr); + assert(*addr == 42); + *addr = 123; pthread_t t; pthread_create(&t, NULL, thread_main, NULL); pthread_join(t, NULL); @@ -2163,10 +2169,10 @@ def test_dylink_pthread_static_data(self): ''') self.do_runf('main.c', '123', cflags=['-pthread', '-Wno-experimental', - '-sPROXY_TO_PTHREAD', - '-sEXIT_RUNTIME', - '-sMAIN_MODULE=2', - 'side.wasm']) + '-sPROXY_TO_PTHREAD', + '-sEXIT_RUNTIME', + '-sMAIN_MODULE=2', + 'side.wasm']) def test_dylink_pthread_warning(self): err = self.expect_fail([EMCC, '-Werror', '-sMAIN_MODULE', '-pthread', test_file('hello_world.c')]) @@ -5618,7 +5624,15 @@ def test_bitcode_linking(self): 'wasm2js': (False, False), 'wasm2js_safe_heap': (False, True), }) - def test_bad_function_pointer_cast(self, opts, wasm, safe): + @parameterized({ + '': (False,), + 'emulate_cases': (True,), + }) + @parameterized({ + '': (False,), + 'dylink': (True,), + }) + def test_bad_function_pointer_cast(self, opts, wasm, safe, emulate_casts, dylink): create_file('src.cpp', r''' #include @@ -5636,31 +5650,28 @@ def test_bad_function_pointer_cast(self, opts, wasm, safe): } ''') - for emulate_casts in (0, 1): - for relocatable in (0, 1): - # wasm2js is not compatible with relocatable mode - if not wasm and relocatable: - continue - cmd = [EMXX, 'src.cpp'] + opts - if not wasm: - cmd += ['-sWASM=0'] - if safe: - cmd += ['-sSAFE_HEAP'] - if emulate_casts: - cmd += ['-sEMULATE_FUNCTION_POINTER_CASTS'] - if relocatable: - cmd += ['-sRELOCATABLE'] # disables asm-optimized safe heap - print(cmd) - self.run_process(cmd) - returncode = 0 if emulate_casts or not wasm else NON_ZERO - output = self.run_js('a.out.js', assert_returncode=returncode) - if emulate_casts or wasm == 0: - # success! - self.assertContained('Hello, world.', output) - else: - # otherwise, the error depends on the mode we are in - # wasm trap raised by the vm - self.assertContained('function signature mismatch', output) + # wasm2js is not compatible with dylink mode + if not wasm and dylink: + self.skipTest("wasm2js + dylink") + cmd = [EMXX, 'src.cpp'] + opts + if not wasm: + cmd += ['-sWASM=0'] + if safe: + cmd += ['-sSAFE_HEAP'] + if emulate_casts: + cmd += ['-sEMULATE_FUNCTION_POINTER_CASTS'] + if dylink: + cmd += ['-sMAIN_MODULE=2'] # disables asm-optimized safe heap + self.run_process(cmd) + returncode = 0 if emulate_casts or not wasm else NON_ZERO + output = self.run_js('a.out.js', assert_returncode=returncode) + if emulate_casts or wasm == 0: + # success! + self.assertContained('Hello, world.', output) + else: + # otherwise, the error depends on the mode we are in + # wasm trap raised by the vm + self.assertContained('function signature mismatch', output) def test_bad_export(self): for exports in ('_main', '_main,foo'): @@ -5693,7 +5704,7 @@ def test_no_dynamic_execution(self): delete_file('a.out.js') # Test that -sDYNAMIC_EXECUTION=0 and -sMAIN_MODULE are allowed together. - self.do_runf('hello_world.c', cflags=['-O1', '-sDYNAMIC_EXECUTION=0', '-sMAIN_MODULE']) + self.do_runf('hello_world.c', cflags=['-O1', '-sDYNAMIC_EXECUTION=0', '-sMAIN_MODULE=2']) create_file('test.c', r''' #include @@ -12293,7 +12304,7 @@ def test_standalone_syscalls(self): '': ([],), 'assertions': (['-sASSERTIONS'],), 'closure': (['-sASSERTIONS', '--closure=1'],), - 'dylink': (['-sMAIN_MODULE'],), + 'dylink': (['-sMAIN_MODULE=2'],), }) def test_webgpu_compiletest(self, args): self.run_process([EMXX, test_file('webgpu_jsvalstore.cpp'), '-Wno-error=deprecated', '-sUSE_WEBGPU', '-sASYNCIFY'] + args) @@ -12697,7 +12708,7 @@ def test_pthread_export_es6(self, args): self.assertContained('hello, world!', output) def test_wasm2js_no_dylink(self): - for arg in ('-sMAIN_MODULE', '-sSIDE_MODULE', '-sRELOCATABLE'): + for arg in ('-sSIDE_MODULE',): print(arg) err = self.expect_fail([EMCC, test_file('hello_world.c'), '-sWASM=0', arg]) self.assertContained('emcc: error: WASM2JS is not compatible with RELOCATABLE', err) @@ -12933,21 +12944,6 @@ def test_gen_struct_info_env(self): with env_modify({'EMCC_CFLAGS': '-O2 BAD_ARG', 'EMCC_FORCE_STDLIBS': '1', 'EMCC_ONLY_FORCED_STDLIBS': '1'}): self.run_process([PYTHON, path_from_root('tools/gen_struct_info.py'), '-o', 'out.json']) - def test_relocatable_limited_exports(self): - # Building with RELOCATABLE should *not* automatically export all sybmols. - self.run_process([EMCC, test_file('hello_world.c'), '-sRELOCATABLE', '-o', 'out.wasm']) - - # Building with RELOCATABLE + LINKABLE should include and export all of the standard library - self.run_process([EMCC, test_file('hello_world.c'), '-sRELOCATABLE', '-sLINKABLE', '-o', 'out_linkable.wasm']) - - exports = self.parse_wasm('out.wasm')[1] - exports_linkable = self.parse_wasm('out_linkable.wasm')[1] - - self.assertLess(len(exports), 20) - self.assertGreater(len(exports_linkable), 1000) - self.assertIn('sendmsg', exports_linkable) - self.assertNotIn('sendmsg', exports) - @requires_v8 def test_shell_Oz(self): # regression test for -Oz working on non-web, non-node environments that @@ -12976,14 +12972,14 @@ def test_em_js_main_module(self): self.set_setting('EXPORTED_FUNCTIONS', '_main,_malloc') self.do_runf('core/test_em_js.cpp') - def test_em_js_main_module_address(self): + def test_em_js_dylink_address(self): # This works under static linking but is known to fail with dynamic linking # See https://github.com/emscripten-core/emscripten/issues/18494 self.do_runf('other/test_em_js_main_module_address.c') - self.set_setting('MAIN_MODULE', 2) - expected = 'Aborted(Assertion failed: Missing signature argument to addFunction: function foo() { err("hello"); })' - self.do_runf('other/test_em_js_main_module_address.c', expected, assert_returncode=NON_ZERO) + self.emcc('other/test_em_js_main_module_address.c', ['-sSIDE_MODULE'], output_filename='libside.so') + expected = 'Aborted(Assertion failed: Missing signature argument to addFunction: () => { err("hello"); })' + self.do_run('', expected, cflags=['-sMAIN_MODULE=2', 'libside.so'], assert_returncode=NON_ZERO) def test_em_js_external_usage(self): # Verify that EM_JS functions can be called from other source files, even in the case @@ -13130,18 +13126,13 @@ def test_reverse_deps_allow_undefined(self): ''') self.do_runf('test.c', cflags=['-sERROR_ON_UNDEFINED_SYMBOLS=0']) - @parameterized({ - 'relocatable': ('-sRELOCATABLE',), - 'linkable': ('-sLINKABLE',), - 'main_module': ('-sMAIN_MODULE',), - }) - def test_check_undefined(self, flag): + def test_main_module_undefined(self): # positive case: no undefined symbols - self.run_process([EMCC, flag, '-sERROR_ON_UNDEFINED_SYMBOLS', test_file('hello_world.c')]) + self.run_process([EMCC, '-sERROR_ON_UNDEFINED_SYMBOLS', '-sMAIN_MODULE', test_file('hello_world.c')]) self.run_js('a.out.js') # negative case: foo is undefined in test_check_undefined.c - err = self.expect_fail([EMCC, flag, '-sERROR_ON_UNDEFINED_SYMBOLS', test_file('other/test_check_undefined.c')]) + err = self.expect_fail([EMCC, '-sERROR_ON_UNDEFINED_SYMBOLS', '-sMAIN_MODULE', test_file('other/test_check_undefined.c')]) self.assertContained('undefined symbol: foo', err) @also_with_wasm64 @@ -14058,12 +14049,17 @@ def test_unsafe_optimizations(self): def test_extended_const(self): self.v8_args += ['--experimental-wasm-extended-const'] # Export at least one global so that we exercise the parsing of the global section. - self.do_runf('hello_world.c', cflags=['-sEXPORTED_FUNCTIONS=_main,___stdout_used', '-mextended-const', '-sMAIN_MODULE=2']) - wat = self.get_wasm_text('hello_world.wasm') + create_file('test.c', r''' + #include + int g_data[10] = {1}; + void test() { + printf("some rodata %d\n", g_data[0]); + } + ''') + self.emcc('test.c', ['-mextended-const', '-sSIDE_MODULE']) + wat = self.get_wasm_text('a.out.wasm') # Test that extended-const expressions are used in the data segments. self.assertContained(r'\(data (\$\S+ )?\(offset \(i32.add\s+\(global.get \$\S+\)\s+\(i32.const \d+\)', wat, regex=True) - # Test that extended-const expressions are used in at least one global initializer. - self.assertContained(r'\(global \$\S+ i32 \(i32.add\s+\(global.get \$\S+\)\s+\(i32.const \d+\)', wat, regex=True) # Smoketest for MEMORY64 setting. Most of the testing of MEMORY64 is by way of the wasm64 # variant of the core test suite. diff --git a/tools/building.py b/tools/building.py index 3c95993c84c56..f784daa38c7d5 100644 --- a/tools/building.py +++ b/tools/building.py @@ -199,7 +199,7 @@ def lld_flags_for_executable(external_symbols): cmd.extend(f'--export-if-defined={e}' for e in settings.EXPORT_IF_DEFINED) - if settings.RELOCATABLE: + if settings.MAIN_MODULE or settings.RELOCATABLE: cmd.append('--experimental-pic') cmd.append('--unresolved-symbols=import-dynamic') if not settings.WASM_BIGINT: @@ -208,6 +208,8 @@ def lld_flags_for_executable(external_symbols): # shared libraries. Because of this we need to disabled signature # checking of shared library functions in this case. cmd.append('--no-shlib-sigcheck') + + if settings.RELOCATABLE: if settings.SIDE_MODULE: cmd.append('-shared') else: @@ -218,6 +220,8 @@ def lld_flags_for_executable(external_symbols): cmd.append('--export-table') if settings.ALLOW_TABLE_GROWTH: cmd.append('--growable-table') + if settings.MAIN_MODULE == 1: + cmd.append('--export-dynamic') if not settings.SIDE_MODULE: cmd += ['-z', 'stack-size=%s' % settings.STACK_SIZE] @@ -272,6 +276,9 @@ def link_lld(args, target, external_symbols=None): args.insert(0, '--whole-archive') args.append('--no-whole-archive') + if settings.MAIN_MODULE: + args.insert(0, '-Bdynamic') + if settings.STRICT and '--no-fatal-warnings' not in args: args.append('--fatal-warnings') @@ -1304,7 +1311,7 @@ def read_and_preprocess(filename, expand_macros=False): def js_legalization_pass_flags(): flags = [] - if settings.RELOCATABLE: + if settings.RELOCATABLE or settings.MAIN_MODULE: # When building in relocatable mode, we also want access the original # non-legalized wasm functions (since wasm modules can and do link to # the original, non-legalized, functions). diff --git a/tools/cache.py b/tools/cache.py index 01f8a6247735a..fd72d8a7a855c 100644 --- a/tools/cache.py +++ b/tools/cache.py @@ -124,7 +124,7 @@ def get_lib_dir(absolute): subdir.append('thinlto') else: subdir.append('lto') - if settings.RELOCATABLE: + if settings.RELOCATABLE or settings.MAIN_MODULE: subdir.append('pic') if subdir: path = Path(path, '-'.join(subdir)) diff --git a/tools/compile.py b/tools/compile.py index 0cc5d33e336f1..e23a05ad7479f 100644 --- a/tools/compile.py +++ b/tools/compile.py @@ -50,10 +50,10 @@ def get_clang_flags(user_args): if '-mbulk-memory' not in user_args: flags.append('-mbulk-memory') - if settings.RELOCATABLE and '-fPIC' not in user_args: + if (settings.MAIN_MODULE or settings.RELOCATABLE) and '-fPIC' not in user_args: flags.append('-fPIC') - if settings.RELOCATABLE or settings.LINKABLE or '-fPIC' in user_args: + if settings.MAIN_MODULE or settings.RELOCATABLE or settings.LINKABLE or '-fPIC' in user_args: if not any(a.startswith('-fvisibility') for a in user_args): # For relocatable code we default to visibility=default in emscripten even # though the upstream backend defaults visibility=hidden. This matches the diff --git a/tools/emscripten.py b/tools/emscripten.py index e37e6e1f86bb7..23c21673c5ed1 100644 --- a/tools/emscripten.py +++ b/tools/emscripten.py @@ -373,8 +373,8 @@ def emscript(in_wasm, out_wasm, outfile_js, js_syms, finalize=True, base_metadat if settings.INITIAL_TABLE == -1: settings.INITIAL_TABLE = dylink_sec.table_size + 1 - if settings.ASYNCIFY == 1: - metadata.imports += ['__asyncify_state', '__asyncify_data'] + if settings.MAIN_MODULE and settings.ASYNCIFY == 1: + metadata.imports += ['__asyncify_state', '__asyncify_data'] if metadata.invoke_funcs: settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$getWasmTableEntry'] @@ -901,7 +901,7 @@ def install_debug_wrapper(sym): return False # Likewise `__trap` can occur before the runtime is initialized since it is used in # abort. - return sym != '__trap' + return sym not in ['__trap', 'emscripten_get_sbrk_ptr'] def should_export(sym): diff --git a/tools/link.py b/tools/link.py index 7050a6e654d59..3b63ab0746c68 100644 --- a/tools/link.py +++ b/tools/link.py @@ -392,7 +392,7 @@ def get_binaryen_passes(): passes += ['--fpcast-emu'] if settings.ASYNCIFY == 1: passes += ['--asyncify'] - if settings.MAIN_MODULE or settings.SIDE_MODULE: + if settings.RELOCATABLE or settings.MAIN_MODULE: passes += ['--pass-arg=asyncify-relocatable'] if settings.ASSERTIONS: passes += ['--pass-arg=asyncify-asserts'] @@ -499,14 +499,13 @@ def get_worker_js_suffix(): def setup_pthreads(): - if settings.RELOCATABLE: - # pthreads + dynamic linking has certain limitations - if settings.SIDE_MODULE: - diagnostics.warning('experimental', '-sSIDE_MODULE + pthreads is experimental') - elif settings.MAIN_MODULE: - diagnostics.warning('experimental', '-sMAIN_MODULE + pthreads is experimental') - elif settings.LINKABLE: - diagnostics.warning('experimental', '-sLINKABLE + pthreads is experimental') + # pthreads + dynamic linking has certain limitations + if settings.SIDE_MODULE: + diagnostics.warning('experimental', '-sSIDE_MODULE + pthreads is experimental') + elif settings.MAIN_MODULE: + diagnostics.warning('experimental', '-sMAIN_MODULE + pthreads is experimental') + elif settings.LINKABLE: + diagnostics.warning('experimental', '-sLINKABLE + pthreads is experimental') if settings.ALLOW_MEMORY_GROWTH and not settings.GROWABLE_ARRAYBUFFERS: diagnostics.warning('pthreads-mem-growth', '-pthread + ALLOW_MEMORY_GROWTH may run non-wasm code slowly, see https://github.com/WebAssembly/design/issues/1271') @@ -1175,13 +1174,11 @@ def limit_incoming_module_api(): '$registerTLSInit', ] - if settings.RELOCATABLE: + if settings.MAIN_MODULE or settings.RELOCATABLE: settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += [ '$reportUndefinedSymbols', '$relocateExports', '$GOTHandler', - '__heap_base', - '__stack_pointer', ] if settings.ASYNCIFY == 1: @@ -1399,6 +1396,7 @@ def limit_incoming_module_api(): if settings.RELOCATABLE: settings.REQUIRED_EXPORTS += ['__wasm_apply_data_relocs'] + settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$wasmTable'] if settings.SIDE_MODULE and 'GLOBAL_BASE' in user_settings: diagnostics.warning('unused-command-line-argument', 'GLOBAL_BASE is not compatible with SIDE_MODULE') diff --git a/tools/system_libs.py b/tools/system_libs.py index 54296e0923bf4..53a457b9c4822 100644 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -65,8 +65,8 @@ def get_base_cflags(build_dir, force_object_files=False, preprocess=True): flags = ['-g', '-sSTRICT', '-Werror'] if settings.LTO and not force_object_files: flags += ['-flto=' + settings.LTO] - if settings.RELOCATABLE: - flags += ['-sRELOCATABLE'] + if settings.RELOCATABLE or settings.MAIN_MODULE: + flags += ['-fPIC'] if preprocess: flags += ['-DEMSCRIPTEN_DYNAMIC_LINKING'] if settings.MEMORY64: @@ -1364,7 +1364,7 @@ def get_files(self): 'system.c', ]) - if settings.RELOCATABLE: + if settings.RELOCATABLE or settings.MAIN_MODULE: libc_files += files_in_path(path='system/lib/libc', filenames=['dynlink.c']) libc_files += files_in_path(