Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion test/browser/test_sdl_key_proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,3 @@ int main(int argc, char **argv) {
emscripten_runtime_keepalive_push();
return 0;
}

13 changes: 11 additions & 2 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -2375,6 +2375,15 @@ def test_undefined_exported_function(self):
cmd = [EMXX, test_file('hello_world.cpp')]
self.run_process(cmd)

# adding a missing symbol to EXPORTED_FUNCTIONS should cause failure
cmd += ['-sEXPORTED_FUNCTIONS=_foobar']
err = self.expect_fail(cmd)
self.assertContained('wasm-ld: error: symbol exported via --export not found: foobar', err)

def test_undefined_exported_js_function(self):
cmd = [EMXX, test_file('hello_world.cpp')]
self.run_process(cmd)

# adding a missing symbol to EXPORTED_FUNCTIONS should cause failure
cmd += ['-sEXPORTED_FUNCTIONS=foobar']
err = self.expect_fail(cmd)
Expand Down Expand Up @@ -7226,7 +7235,7 @@ def test_no_warn_exported_jslibfunc(self):
err = self.expect_fail([EMCC, test_file('hello_world.c'),
'-sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=alGetError',
'-sEXPORTED_FUNCTIONS=_main,_alGet'])
self.assertContained('error: undefined exported symbol: "_alGet" [-Wundefined] [-Werror]', err)
self.assertContained('wasm-ld: error: symbol exported via --export not found: alGet', err)

def test_musl_syscalls(self):
self.run_process([EMCC, test_file('hello_world.c')])
Expand Down Expand Up @@ -10074,7 +10083,7 @@ def test_dash_s_list_parsing(self):
# stray slash
('EXPORTED_FUNCTIONS=["_a", "_b",\\ "_c", "_d"]', 'undefined exported symbol: "\\\\ "_c"'),
# missing comma
('EXPORTED_FUNCTIONS=["_a", "_b" "_c", "_d"]', 'emcc: error: undefined exported symbol: "_b" "_c" [-Wundefined] [-Werror]'),
('EXPORTED_FUNCTIONS=["_a", "_b" "_c", "_d"]', 'wasm-ld: error: symbol exported via --export not found: b" "_c'),
]:
print(export_arg)
proc = self.run_process([EMCC, 'src.c', '-s', export_arg], stdout=PIPE, stderr=PIPE, check=not expected)
Expand Down
8 changes: 4 additions & 4 deletions tools/building.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,20 +191,20 @@ def lld_flags_for_executable(external_symbols):
c_exports = [e for e in settings.EXPORTED_FUNCTIONS if is_c_symbol(e)]
# Strip the leading underscores
c_exports = [demangle_c_symbol_name(e) for e in c_exports]
c_exports += settings.EXPORT_IF_DEFINED
# Filter out symbols external/JS symbols
c_exports = [e for e in c_exports if e not in external_symbols]
c_exports += settings.REQUIRED_EXPORTS
if settings.MAIN_MODULE:
c_exports += side_module_external_deps(external_symbols)
for export in c_exports:
cmd.append('--export-if-defined=' + export)

for export in settings.REQUIRED_EXPORTS:
if settings.ERROR_ON_UNDEFINED_SYMBOLS:
cmd.append('--export=' + export)
else:
cmd.append('--export-if-defined=' + export)

for e in settings.EXPORT_IF_DEFINED:
cmd.append('--export-if-defined=' + e)

if settings.RELOCATABLE:
cmd.append('--experimental-pic')
cmd.append('--unresolved-symbols=import-dynamic')
Expand Down
28 changes: 16 additions & 12 deletions tools/emscripten.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from tools.utils import exit_with_error, path_from_root, removeprefix
from tools.shared import DEBUG, asmjs_mangle
from tools.shared import treat_as_user_export
from tools.settings import settings
from tools.settings import settings, user_settings

sys.path.append(path_from_root('third_party'))
import leb128
Expand Down Expand Up @@ -555,6 +555,7 @@ def finalize_wasm(infile, outfile, js_syms):

expected_exports = set(settings.EXPORTED_FUNCTIONS)
expected_exports.update(asmjs_mangle(s) for s in settings.REQUIRED_EXPORTS)
expected_exports.update(asmjs_mangle(s) for s in settings.EXPORT_IF_DEFINED)
# Assume that when JS symbol dependencies are exported it is because they
# are needed by by a JS symbol and are not being explicitly exported due
# to EMSCRIPTEN_KEEPALIVE (llvm.used).
Expand All @@ -569,18 +570,21 @@ def finalize_wasm(infile, outfile, js_syms):
unexpected_exports = [asmjs_mangle(e) for e in unexpected_exports]
unexpected_exports = [e for e in unexpected_exports if e not in expected_exports]

# If `_main` was unexpectedly exported we assume it was added to
# EXPORT_IF_DEFINED by emcc.py in order that we can detect it and
# report this warning. In this case we explicitly ignore the export
# and run as if there was no main function since that is defined is
# behaviour for programs that don't include `_main` in EXPORTED_FUNCTIONS.
if not settings.STANDALONE_WASM and '_main' in unexpected_exports:
diagnostics.warning('unused-main', '`main` is defined in the input files, but `_main` is not in `EXPORTED_FUNCTIONS`. Add it to this list if you want `main` to run.')
unexpected_exports.remove('_main')
if 'main' in metadata.all_exports:
metadata.all_exports.remove('main')
if not settings.STANDALONE_WASM and 'main' in metadata.all_exports or '__main_argc_argv' in metadata.all_exports:
if 'EXPORTED_FUNCTIONS' in user_settings and '_main' not in settings.USER_EXPORTED_FUNCTIONS:
# If `_main` was unexpectedly exported we assume it was added to
# EXPORT_IF_DEFINED by `phase_linker_setup` in order that we can detect
# it and report this warning. After reporting the warning we explicitly
# ignore the export and run as if there was no main function since that
# is defined is behaviour for programs that don't include `_main` in
# EXPORTED_FUNCTIONS.
diagnostics.warning('unused-main', '`main` is defined in the input files, but `_main` is not in `EXPORTED_FUNCTIONS`. Add it to this list if you want `main` to run.')
if 'main' in metadata.all_exports:
metadata.all_exports.remove('main')
else:
metadata.all_exports.remove('__main_argc_argv')
else:
metadata.all_exports.remove('__main_argc_argv')
unexpected_exports.append('_main')

building.user_requested_exports.update(unexpected_exports)
settings.EXPORTED_FUNCTIONS.extend(unexpected_exports)
Expand Down
10 changes: 6 additions & 4 deletions tools/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -810,11 +810,13 @@ def phase_linker_setup(options, state, newargs):
# 2. If the user doesn't export anything we default to exporting `_main` (unless `--no-entry`
# is specified (see above).
if 'EXPORTED_FUNCTIONS' in user_settings:
if '_main' not in settings.USER_EXPORTED_FUNCTIONS:
if '_main' in settings.USER_EXPORTED_FUNCTIONS:
settings.EXPORTED_FUNCTIONS.remove('_main')
settings.EXPORT_IF_DEFINED.append('main')
else:
settings.EXPECT_MAIN = 0
else:
assert not settings.EXPORTED_FUNCTIONS
settings.EXPORTED_FUNCTIONS = ['_main']
settings.EXPORT_IF_DEFINED.append('main')

if settings.STANDALONE_WASM:
# In STANDALONE_WASM mode we either build a command or a reactor.
Expand All @@ -838,7 +840,7 @@ def phase_linker_setup(options, state, newargs):
# Note the exports the user requested
building.user_requested_exports.update(settings.EXPORTED_FUNCTIONS)

if '_main' in settings.EXPORTED_FUNCTIONS:
if '_main' in settings.EXPORTED_FUNCTIONS or 'main' in settings.EXPORT_IF_DEFINED:
settings.EXPORT_IF_DEFINED.append('__main_argc_argv')
elif settings.ASSERTIONS and not settings.STANDALONE_WASM:
# In debug builds when `main` is not explicitly requested as an
Expand Down