Skip to content

Commit 85c099a

Browse files
authored
Avoid exporting/defining main when we try to detect an unexported main (#20971)
In debug builds we attempt to detect and unexported main by adding it to EXPORT_IF_DEFINED, but then ignoring it. However we were not fully ignoring it which resulted in `main` getting run in debug builds but not in release builds.
1 parent 0ad3bf8 commit 85c099a

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ See docs/process.md for more on how version tagging works.
2020

2121
3.1.52 (in development)
2222
-----------------------
23+
- Fix bug where `main` was mistakenly included in debug builds but not in
24+
release builds. (#20971)
2325
- Remove JAVA from the list of `.emscripten` config file settings. In the
2426
past we used this to run the java version of closure compiler. If there are
2527
folks who prefer to use the java version of closure compiler for some reason

test/test_other.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7923,11 +7923,24 @@ def test(contents, expected, args=[], assert_returncode=0): # noqa
79237923
# test backwards compatibility
79247924
test("Module['print']('print'); Module['printErr']('err'); ", 'print\nerr', ['-sEXPORTED_RUNTIME_METHODS=print,printErr', '-Wno-js-compiler'])
79257925

7926-
def test_warn_unexported_main(self):
7927-
warning = 'emcc: warning: `main` is defined in the input files, but `_main` is not in `EXPORTED_FUNCTIONS`, which means it may be eliminated as dead code. Export it if you want `main` to run. [-Wunused-main]'
7926+
@parameterized({
7927+
'': ([],),
7928+
'O2': (['-O2'],),
7929+
})
7930+
def test_warn_unexported_main(self, args):
7931+
warning = 'emcc: warning: `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. [-Wunused-main]'
7932+
7933+
proc = self.run_process([EMCC, test_file('hello_world.c'), '-sEXPORTED_FUNCTIONS=[]'] + args, stderr=PIPE)
7934+
# This warning only shows up when ASSERTIONS are enabled.
7935+
# We run both ways those to ensure that main doesn't get run in either case.
7936+
if '-O2' in args:
7937+
self.assertNotContained(warning, proc.stderr)
7938+
else:
7939+
self.assertContained(warning, proc.stderr)
79287940

7929-
proc = self.run_process([EMCC, test_file('hello_world.c'), '-sEXPORTED_FUNCTIONS=[]'], stderr=PIPE)
7930-
self.assertContained(warning, proc.stderr)
7941+
# Verify that main indeed does not run
7942+
output = self.run_js('a.out.js')
7943+
self.assertEqual('', output)
79317944

79327945
def test_source_file_with_fixed_language_mode(self):
79337946
create_file('src_tmp_fixed_lang', '''

tools/emscripten.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,9 +568,16 @@ def finalize_wasm(infile, outfile, js_syms):
568568
unexpected_exports = [e for e in metadata.all_exports if treat_as_user_export(e)]
569569
unexpected_exports = [asmjs_mangle(e) for e in unexpected_exports]
570570
unexpected_exports = [e for e in unexpected_exports if e not in expected_exports]
571+
572+
# If `_main` was unexpectedly exported we assume it was added to
573+
# EXPORT_IF_DEFINED by emcc.py in order that we can detect it and
574+
# report this warning. In this case we explicitly ignore the export
575+
# and run as if there was no main function since that is defined is
576+
# behaviour for programs that don't include `_main` in EXPORTED_FUNCTIONS.
571577
if not settings.STANDALONE_WASM and '_main' in unexpected_exports:
572-
diagnostics.warning('unused-main', '`main` is defined in the input files, but `_main` is not in `EXPORTED_FUNCTIONS`, which means it may be eliminated as dead code. Export it if you want `main` to run.')
578+
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.')
573579
unexpected_exports.remove('_main')
580+
metadata.all_exports.remove('main')
574581

575582
building.user_requested_exports.update(unexpected_exports)
576583
settings.EXPORTED_FUNCTIONS.extend(unexpected_exports)

0 commit comments

Comments
 (0)