Skip to content

Commit

Permalink
warn/error on missing js library symbols, avoiding false positives by…
Browse files Browse the repository at this point in the history
… telling compiler.js which methods were implemented in C emscripten-core#4077 emscripten-core#2154
  • Loading branch information
kripken committed Feb 5, 2016
1 parent d4a4e3e commit 8c7c1bb
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 3 deletions.
2 changes: 2 additions & 0 deletions emscripten.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ def fix_dot_zero(m):

settings['MAX_GLOBAL_ALIGN'] = metadata['maxGlobalAlign']

settings['IMPLEMENTED_FUNCTIONS'] = metadata['implementedFunctions']

assert not (metadata['simd'] and settings['SPLIT_MEMORY']), 'SIMD is used, but not supported in SPLIT_MEMORY'

# Save settings to a file to work around v8 issue 1579
Expand Down
1 change: 1 addition & 0 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ if (settings_file) {

EXPORTED_FUNCTIONS = set(EXPORTED_FUNCTIONS);
EXCEPTION_CATCHING_WHITELIST = set(EXCEPTION_CATCHING_WHITELIST);
IMPLEMENTED_FUNCTIONS = set(IMPLEMENTED_FUNCTIONS);

// TODO: Implement support for proper preprocessing, e.g. "#if A || B" and "#if defined(A) || defined(B)" to
// avoid needing this here.
Expand Down
6 changes: 3 additions & 3 deletions src/jsifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ function JSify(data, functionsOnly) {
functionStubSigs[item.ident] = Functions.getSignature(item.returnType.text, item.params.map(function(arg) { return arg.type }), false);
}

function addFromLibrary(ident, notDep) {
function addFromLibrary(ident) {
if (ident in addedLibraryItems) return '';
addedLibraryItems[ident] = true;

Expand All @@ -139,7 +139,7 @@ function JSify(data, functionsOnly) {
var noExport = false;

if ((!LibraryManager.library.hasOwnProperty(ident) && !LibraryManager.library.hasOwnProperty(ident + '__inline')) || SIDE_MODULE) {
if (notDep) {
if (!(finalName in IMPLEMENTED_FUNCTIONS)) {
if (VERBOSE || ident.substr(0, 11) !== 'emscripten_') { // avoid warning on emscripten_* functions which are for internal usage anyhow
if (!LINKABLE) {
if (ERROR_ON_UNDEFINED_SYMBOLS) error('unresolved symbol: ' + ident);
Expand Down Expand Up @@ -260,7 +260,7 @@ function JSify(data, functionsOnly) {
delete LibraryManager.library[shortident + '__deps'];
}
}
item.JS = addFromLibrary(shortident, true);
item.JS = addFromLibrary(shortident);
}
}

Expand Down
48 changes: 48 additions & 0 deletions tests/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -5347,6 +5347,54 @@ def test_umask_0(self):
def test_no_missing_symbols(self): # simple hello world should not show any missing symbols
check_execute([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'])

# main() is implemented in C, and even if requested from JS, we should not warn
open('library_foo.js', 'w').write('''
mergeInto(LibraryManager.library, {
my_js__deps: ['main'],
my_js: (function() {
return function() {
console.log("hello " + _nonexistingvariable);
};
}()),
});
''')
open('test.cpp', 'w').write('''
#include<stdio.h>
#include<stdlib.h>
extern "C" {
extern void my_js();
}
int main() {
my_js();
return EXIT_SUCCESS;
}
''')
check_execute([PYTHON, EMCC, 'test.cpp', '-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1', '--js-library', 'library_foo.js'])

# but we do error on a missing js var
open('library_foo.js', 'w').write('''
mergeInto(LibraryManager.library, {
my_js__deps: ['main', 'nonexistingvariable'],
my_js: (function() {
return function() {
console.log("hello " + _nonexistingvariable);
};
}()),
});
''')
proc = Popen([PYTHON, EMCC, 'test.cpp', '-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1', '--js-library', 'library_foo.js'], stderr=PIPE)
out, err = proc.communicate()
assert proc.returncode != 0
assert 'unresolved symbol' in err

# and also for missing C code, of course (without the --js-library, it's just a missing C method)
proc = Popen([PYTHON, EMCC, 'test.cpp', '-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'], stderr=PIPE)
out, err = proc.communicate()
assert proc.returncode != 0
assert 'unresolved symbol' in err

def test_realpath(self):
open('src.c', 'w').write(r'''
#include <stdlib.h>
Expand Down

0 comments on commit 8c7c1bb

Please sign in to comment.