From 6a148a2548b4387784e251961b9a24b000c03e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 25 Oct 2016 00:05:05 +0300 Subject: [PATCH 01/18] If environment variable EMSCRIPTEN_STRICT is set, don't pass the preprocessor define EMSCRIPTEN to compiled code. --- emcc.py | 5 ++++- tools/shared.py | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/emcc.py b/emcc.py index 8af5674d24f45..e0d023e62f699 100755 --- a/emcc.py +++ b/emcc.py @@ -250,7 +250,10 @@ def filter_emscripten_options(argv): if compiler == shared.EMCC: compiler = [shared.PYTHON, shared.EMCC] else: compiler = [compiler] cmd = compiler + list(filter_emscripten_options(sys.argv[1:])) - if not use_js: cmd += shared.EMSDK_OPTS + ['-D__EMSCRIPTEN__', '-DEMSCRIPTEN'] + if not use_js: + cmd += shared.EMSDK_OPTS + ['-D__EMSCRIPTEN__'] + # The preprocessor define EMSCRIPTEN is deprecated. Don't pass it to code in strict mode. Code should use the define __EMSCRIPTEN__ instead. + if not os.environ.get('EMSCRIPTEN_STRICT') or int(os.environ.get('EMSCRIPTEN_STRICT')) == 0: cmd += ['-DEMSCRIPTEN'] if use_js: cmd += ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'] # configure tests should fail when an undefined symbol exists logging.debug('just configuring: ' + ' '.join(cmd)) diff --git a/tools/shared.py b/tools/shared.py index c9ce4ea7850a8..485c91a80f76d 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -927,12 +927,14 @@ def get_llvm_target(): if LLVM_TARGET == WASM_TARGET: # wasm target does not automatically define emscripten stuff, so do it here. - COMPILER_OPTS = COMPILER_OPTS + ['-DEMSCRIPTEN', - '-D__EMSCRIPTEN__', + COMPILER_OPTS = COMPILER_OPTS + ['-D__EMSCRIPTEN__', '-Dunix', '-D__unix', '-D__unix__'] + # The preprocessor define EMSCRIPTEN is deprecated. Don't pass it to code in strict mode. Code should use the define __EMSCRIPTEN__ instead. + if not os.environ.get('EMSCRIPTEN_STRICT') or int(os.environ.get('EMSCRIPTEN_STRICT')) == 0: COMPILER_OPTS += ['-DEMSCRIPTEN'] + # Changes to default clang behavior # Implicit functions can cause horribly confusing function pointer type errors, see #2175 From 8e3bf5b6218270fdc1c5f59c07458c6c8bcb0a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 25 Oct 2016 00:11:54 +0300 Subject: [PATCH 02/18] -s ERROR_ON_UNDEFINED_SYMBOLS=1 should be the default value, so set it in strict mode. --- tools/shared.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/shared.py b/tools/shared.py index 485c91a80f76d..c7704376736e9 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1098,6 +1098,11 @@ def load(self, args=[]): settings = re.sub(r'var ([\w\d]+)', r'self.attrs["\1"]', settings) exec settings + # Apply default values for settings that are configured from environment variables. + if os.environ.get('EMSCRIPTEN_STRICT') and int(os.environ.get('EMSCRIPTEN_STRICT')) != 0: + # The default value -s ERROR_ON_UNDEFINED_SYMBOLS=0 is deprecated. Use the default value 1 in strict mode. + self.attrs['ERROR_ON_UNDEFINED_SYMBOLS'] = 1 + # Apply additional settings. First -O, then -s for i in range(len(args)): if args[i].startswith('-O'): From b8e913002e98f5572b4b8a0cadde9727528991c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 25 Oct 2016 00:25:08 +0300 Subject: [PATCH 03/18] Convert "emcc: cannot find library" warning to an option configurable with -s ERROR_ON_MISSING_LIBRARIES=0/1. Default to 0, but in EMSCRIPTEN_STRICT mode, default to 1. --- emcc.py | 8 +++++++- src/settings.js | 13 +++++++++++++ tools/shared.py | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/emcc.py b/emcc.py index e0d023e62f699..bf9423ff9f312 100755 --- a/emcc.py +++ b/emcc.py @@ -938,7 +938,13 @@ def detect_fixed_language_mode(args): if found: break if found: break if not found and lib not in ['GL', 'GLU', 'glut', 'm', 'c', 'SDL', 'stdc++', 'pthread']: # whitelist our default libraries - logging.warning('emcc: cannot find library "%s"', lib) + emscripten_strict_mode = os.environ.get('EMSCRIPTEN_STRICT') and int(os.environ.get('EMSCRIPTEN_STRICT')) != 0 + error_on_missing_libraries = (emscripten_strict_mode and not 'ERROR_ON_MISSING_LIBRARIES=0' in settings_changes) or 'ERROR_ON_MISSING_LIBRARIES=1' in settings_changes + if error_on_missing_libraries: + logging.fatal('emcc: cannot find library "%s"', lib) + exit(1) + else: + logging.warning('emcc: cannot find library "%s"', lib) # If not compiling to JS, then we are compiling to an intermediate bitcode objects or library, so # ignore dynamic linking, since multiple dynamic linkings can interfere with each other diff --git a/src/settings.js b/src/settings.js index 7926a42f7965d..3b6ae646ed3bd 100644 --- a/src/settings.js +++ b/src/settings.js @@ -501,6 +501,19 @@ var WARN_ON_UNDEFINED_SYMBOLS = 1; // If set to 1, we will warn on any undefined var ERROR_ON_UNDEFINED_SYMBOLS = 0; // If set to 1, we will give a compile-time error on any // undefined symbols (see WARN_ON_UNDEFINED_SYMBOLS). + // The default value for this is currently 0, but will be + // transitioned to 1 in the future. To keep relying on + // building with -s ERROR_ON_UNDEFINED_SYMBOLS=0 setting, + // prefer to set that option explicitly in your build system. + +var ERROR_ON_MISSING_LIBRARIES = 0; // If set to 1, any -lfoo directives pointing to nonexisting + // library files will issue a linker error. + + // The default value for this is currently 0, but will be + // transitioned to 1 in the future. To keep relying on + // building with -s ERROR_ON_MISSING_LIBRARIES=0 setting, + // prefer to set that option explicitly in your build system. + var SMALL_XHR_CHUNKS = 0; // Use small chunk size for binary synchronous XHR's in Web Workers. // Used for testing. // See test_chunked_synchronous_xhr in runner.py and library.js. diff --git a/tools/shared.py b/tools/shared.py index c7704376736e9..d0f23ea2adae8 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1102,6 +1102,7 @@ def load(self, args=[]): if os.environ.get('EMSCRIPTEN_STRICT') and int(os.environ.get('EMSCRIPTEN_STRICT')) != 0: # The default value -s ERROR_ON_UNDEFINED_SYMBOLS=0 is deprecated. Use the default value 1 in strict mode. self.attrs['ERROR_ON_UNDEFINED_SYMBOLS'] = 1 + self.attrs['ERROR_ON_MISSING_LIBRARIES'] = 1 # Apply additional settings. First -O, then -s for i in range(len(args)): From 4e1eabec6ecdfe220a9a9cf0551147e4bf32e226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 25 Oct 2016 00:27:30 +0300 Subject: [PATCH 04/18] Remove Emscripten include path system/include/emscripten in EMSCRIPTEN_STRICT build mode. --- tools/shared.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/shared.py b/tools/shared.py index d0f23ea2adae8..016a859608e82 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -952,13 +952,17 @@ def get_llvm_target(): C_INCLUDE_PATHS = [ path_from_root('system', 'include', 'compat'), path_from_root('system', 'include'), - path_from_root('system', 'include', 'emscripten'), path_from_root('system', 'include', 'SSE'), path_from_root('system', 'include', 'libc'), path_from_root('system', 'lib', 'libc', 'musl', 'arch', 'emscripten'), path_from_root('system', 'local', 'include') ] + # The system include path system/include/emscripten/ is deprecated, i.e. instead of #include , one should pass in #include . + # This path is not available in EMSCRIPTEN_STRICT mode. + if not os.environ.get('EMSCRIPTEN_STRICT') or int(os.environ.get('EMSCRIPTEN_STRICT')) == 0: + C_INCLUDE_PATHS += [path_from_root('system', 'include', 'emscripten')] + CXX_INCLUDE_PATHS = [ path_from_root('system', 'include', 'libcxx'), path_from_root('system', 'lib', 'libcxxabi', 'include') From f2d975a124bed4f0cdc282e311b965911f59318d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 25 Oct 2016 00:37:45 +0300 Subject: [PATCH 05/18] Add EMSCRIPTEN_STRICT as a linker setting as well. --- emcc.py | 2 +- src/settings.js | 4 ++++ tools/shared.py | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/emcc.py b/emcc.py index bf9423ff9f312..1db9c8ba4d251 100755 --- a/emcc.py +++ b/emcc.py @@ -938,7 +938,7 @@ def detect_fixed_language_mode(args): if found: break if found: break if not found and lib not in ['GL', 'GLU', 'glut', 'm', 'c', 'SDL', 'stdc++', 'pthread']: # whitelist our default libraries - emscripten_strict_mode = os.environ.get('EMSCRIPTEN_STRICT') and int(os.environ.get('EMSCRIPTEN_STRICT')) != 0 + emscripten_strict_mode = (os.environ.get('EMSCRIPTEN_STRICT') and int(os.environ.get('EMSCRIPTEN_STRICT')) != 0) or 'EMSCRIPTEN_STRICT=1' in settings_changes error_on_missing_libraries = (emscripten_strict_mode and not 'ERROR_ON_MISSING_LIBRARIES=0' in settings_changes) or 'ERROR_ON_MISSING_LIBRARIES=1' in settings_changes if error_on_missing_libraries: logging.fatal('emcc: cannot find library "%s"', lib) diff --git a/src/settings.js b/src/settings.js index 3b6ae646ed3bd..054f7d5733b59 100644 --- a/src/settings.js +++ b/src/settings.js @@ -487,6 +487,10 @@ var LINKABLE = 0; // If set to 1, this file can be linked with others, either as // LINKABLE of 0 is very useful in that we can reduce the size of the // generated code very significantly, by removing everything not actually used. +var EMSCRIPTEN_STRICT = 0; // Emscripten 'strict' build mode: Drop supporting any deprecated build options. + // Set the environment variable EMSCRIPTEN_STRICT=1 or pass -s EMSCRIPTEN_STRICT=1 + // to test that a codebase builds nicely in forward compatible manner. + var WARN_ON_UNDEFINED_SYMBOLS = 1; // If set to 1, we will warn on any undefined symbols that // are not resolved by the library_*.js files. Note that // it is common in large projects to diff --git a/tools/shared.py b/tools/shared.py index 016a859608e82..b785431e34fd3 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1104,7 +1104,8 @@ def load(self, args=[]): # Apply default values for settings that are configured from environment variables. if os.environ.get('EMSCRIPTEN_STRICT') and int(os.environ.get('EMSCRIPTEN_STRICT')) != 0: - # The default value -s ERROR_ON_UNDEFINED_SYMBOLS=0 is deprecated. Use the default value 1 in strict mode. + # Specify default values for Emscripten strict mode. + self.attrs['EMSCRIPTEN_STRICT'] = 1 self.attrs['ERROR_ON_UNDEFINED_SYMBOLS'] = 1 self.attrs['ERROR_ON_MISSING_LIBRARIES'] = 1 From 1b3fe4241f1e39039b3bd0368eea3235a227a796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 25 Oct 2016 01:04:00 +0300 Subject: [PATCH 06/18] In EMSCRIPTEN_STRICT mode, stop autolinking to all system provided JS libraries, but instead require explicitly specifying which ones to link to on command line. --- emcc.py | 41 +++++++++++++++++++++++++------ src/modules.js | 65 ++++++++++++++++++++++++++++++++----------------- src/settings.js | 3 +++ 3 files changed, 80 insertions(+), 29 deletions(-) diff --git a/emcc.py b/emcc.py index 1db9c8ba4d251..16a33c1104ca8 100755 --- a/emcc.py +++ b/emcc.py @@ -921,6 +921,8 @@ def detect_fixed_language_mode(args): if separate_asm: shared.Settings.SEPARATE_ASM = os.path.basename(asm_target) + system_js_libraries = [] + # Find library files for i, lib in libs: logging.debug('looking for library "%s"', lib) @@ -937,14 +939,39 @@ def detect_fixed_language_mode(args): break if found: break if found: break - if not found and lib not in ['GL', 'GLU', 'glut', 'm', 'c', 'SDL', 'stdc++', 'pthread']: # whitelist our default libraries - emscripten_strict_mode = (os.environ.get('EMSCRIPTEN_STRICT') and int(os.environ.get('EMSCRIPTEN_STRICT')) != 0) or 'EMSCRIPTEN_STRICT=1' in settings_changes - error_on_missing_libraries = (emscripten_strict_mode and not 'ERROR_ON_MISSING_LIBRARIES=0' in settings_changes) or 'ERROR_ON_MISSING_LIBRARIES=1' in settings_changes - if error_on_missing_libraries: - logging.fatal('emcc: cannot find library "%s"', lib) - exit(1) + if not found: + # Some native libraries are implemented in Emscripten as system side JS libraries + js_system_libraries = { + 'c': '', + 'EGL': 'library_egl.js', + 'GL': 'library_gl.js', + 'GLESv2': 'library_gl.js', + 'GLEW': 'library_glew.js', + 'glfw': 'library_glfw.js', + 'glfw3': 'library_glfw.js', + 'GLU': '', + 'glut': 'library_glut.js', + 'm': '', + 'openal': 'library_openal.js', + 'pthread': '', + 'SDL': 'library_sdl.js', + 'stdc++': '' + } + if lib in js_system_libraries: + if len(js_system_libraries[lib]) > 0: + system_js_libraries += [js_system_libraries[lib]] + elif lib.endswith('.js') and os.path.isfile(shared.path_from_root('src', 'library_' + lib)): + system_js_libraries += ['library_' + lib] else: - logging.warning('emcc: cannot find library "%s"', lib) + emscripten_strict_mode = (os.environ.get('EMSCRIPTEN_STRICT') and int(os.environ.get('EMSCRIPTEN_STRICT')) != 0) or 'EMSCRIPTEN_STRICT=1' in settings_changes + error_on_missing_libraries = (emscripten_strict_mode and not 'ERROR_ON_MISSING_LIBRARIES=0' in settings_changes) or 'ERROR_ON_MISSING_LIBRARIES=1' in settings_changes + if error_on_missing_libraries: + logging.fatal('emcc: cannot find library "%s"', lib) + exit(1) + else: + logging.warning('emcc: cannot find library "%s"', lib) + + settings_changes.append('SYSTEM_JS_LIBRARIES="' + ','.join(system_js_libraries) + '"') # If not compiling to JS, then we are compiling to an intermediate bitcode objects or library, so # ignore dynamic linking, since multiple dynamic linkings can interfere with each other diff --git a/src/modules.js b/src/modules.js index aaff60faefe9f..ef8a1a08182b3 100644 --- a/src/modules.js +++ b/src/modules.js @@ -96,41 +96,62 @@ var LibraryManager = { load: function() { if (this.library) return; + // Core system libraries (always linked against) var libraries = [ 'library.js', 'library_browser.js', 'library_formatString.js', 'library_path.js', - 'library_syscall.js' + 'library_syscall.js', + 'library_html5.js' ]; + if (!NO_FILESYSTEM) { + // Core filesystem libraries (always linked against, unless -s NO_FILESYSTEM=1 is specified) libraries = libraries.concat([ 'library_fs.js', - 'library_idbfs.js', 'library_memfs.js', - 'library_nodefs.js', - 'library_sockfs.js', - 'library_workerfs.js', 'library_tty.js', - 'library_lz4.js', + ]); + + // Additional filesystem libraries (in strict mode, link to these explicitly via -lxxx.js) + if (!EMSCRIPTEN_STRICT) { + libraries = libraries.concat([ + 'library_idbfs.js', + 'library_nodefs.js', + 'library_sockfs.js', + 'library_workerfs.js', + 'library_lz4.js', + ]); + } + } + + // Additional JS libraries (in strict mode, link to these explicitly via -lxxx.js) + if (!EMSCRIPTEN_STRICT) { + libraries = libraries.concat([ + 'library_sdl.js', + 'library_gl.js', + 'library_glut.js', + 'library_xlib.js', + 'library_egl.js', + 'library_openal.js', + 'library_glfw.js', + 'library_uuid.js', + 'library_glew.js', + 'library_signals.js', + 'library_idbstore.js', + 'library_async.js', + 'library_vr.js' ]); } - libraries = libraries.concat([ - 'library_sdl.js', - 'library_gl.js', - 'library_glut.js', - 'library_xlib.js', - 'library_egl.js', - 'library_openal.js', - 'library_glfw.js', - 'library_uuid.js', - 'library_glew.js', - 'library_html5.js', - 'library_signals.js', - 'library_idbstore.js', - 'library_async.js', - 'library_vr.js' - ]).concat(additionalLibraries); + + // If there are any explicitly specified system JS libraries to link to, add those to link. + if (SYSTEM_JS_LIBRARIES) { + SYSTEM_JS_LIBRARIES = SYSTEM_JS_LIBRARIES.split(','); + libraries = libraries.concat(SYSTEM_JS_LIBRARIES); + } + + libraries = libraries.concat(additionalLibraries); if (BOOTSTRAPPING_STRUCT_INFO) libraries = ['library_bootstrap_structInfo.js', 'library_formatString.js']; if (ONLY_MY_CODE) { diff --git a/src/settings.js b/src/settings.js index 054f7d5733b59..2d4e14d6a72c7 100644 --- a/src/settings.js +++ b/src/settings.js @@ -518,6 +518,9 @@ var ERROR_ON_MISSING_LIBRARIES = 0; // If set to 1, any -lfoo directives pointin // building with -s ERROR_ON_MISSING_LIBRARIES=0 setting, // prefer to set that option explicitly in your build system. +var SYSTEM_JS_LIBRARIES = []; // Specifies a list of Emscripten-provided JS libraries to link against. + // (internal, use -lfoo or -lfoo.js to link to Emscripten system JS libraries) + var SMALL_XHR_CHUNKS = 0; // Use small chunk size for binary synchronous XHR's in Web Workers. // Used for testing. // See test_chunked_synchronous_xhr in runner.py and library.js. From 72c97d188b778377d7d310a0aac1c0a5fd1b7321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 26 Oct 2016 12:16:31 +0300 Subject: [PATCH 07/18] Rename Emscripten strict mode to EMCC_STRICT=1 env var/-s STRICT=1 linker flag. --- emcc.py | 4 ++-- src/modules.js | 4 ++-- src/settings.js | 6 +++--- tools/shared.py | 14 +++++++++----- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/emcc.py b/emcc.py index 16a33c1104ca8..f7553cb83b918 100755 --- a/emcc.py +++ b/emcc.py @@ -253,7 +253,7 @@ def filter_emscripten_options(argv): if not use_js: cmd += shared.EMSDK_OPTS + ['-D__EMSCRIPTEN__'] # The preprocessor define EMSCRIPTEN is deprecated. Don't pass it to code in strict mode. Code should use the define __EMSCRIPTEN__ instead. - if not os.environ.get('EMSCRIPTEN_STRICT') or int(os.environ.get('EMSCRIPTEN_STRICT')) == 0: cmd += ['-DEMSCRIPTEN'] + if not shared.is_emscripten_strict(): cmd += ['-DEMSCRIPTEN'] if use_js: cmd += ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'] # configure tests should fail when an undefined symbol exists logging.debug('just configuring: ' + ' '.join(cmd)) @@ -963,7 +963,7 @@ def detect_fixed_language_mode(args): elif lib.endswith('.js') and os.path.isfile(shared.path_from_root('src', 'library_' + lib)): system_js_libraries += ['library_' + lib] else: - emscripten_strict_mode = (os.environ.get('EMSCRIPTEN_STRICT') and int(os.environ.get('EMSCRIPTEN_STRICT')) != 0) or 'EMSCRIPTEN_STRICT=1' in settings_changes + emscripten_strict_mode = shared.is_emscripten_strict() or 'STRICT=1' in settings_changes error_on_missing_libraries = (emscripten_strict_mode and not 'ERROR_ON_MISSING_LIBRARIES=0' in settings_changes) or 'ERROR_ON_MISSING_LIBRARIES=1' in settings_changes if error_on_missing_libraries: logging.fatal('emcc: cannot find library "%s"', lib) diff --git a/src/modules.js b/src/modules.js index ef8a1a08182b3..4c1c8a676e81b 100644 --- a/src/modules.js +++ b/src/modules.js @@ -115,7 +115,7 @@ var LibraryManager = { ]); // Additional filesystem libraries (in strict mode, link to these explicitly via -lxxx.js) - if (!EMSCRIPTEN_STRICT) { + if (!STRICT) { libraries = libraries.concat([ 'library_idbfs.js', 'library_nodefs.js', @@ -127,7 +127,7 @@ var LibraryManager = { } // Additional JS libraries (in strict mode, link to these explicitly via -lxxx.js) - if (!EMSCRIPTEN_STRICT) { + if (!STRICT) { libraries = libraries.concat([ 'library_sdl.js', 'library_gl.js', diff --git a/src/settings.js b/src/settings.js index 2d4e14d6a72c7..badd9e527a3c5 100644 --- a/src/settings.js +++ b/src/settings.js @@ -487,9 +487,9 @@ var LINKABLE = 0; // If set to 1, this file can be linked with others, either as // LINKABLE of 0 is very useful in that we can reduce the size of the // generated code very significantly, by removing everything not actually used. -var EMSCRIPTEN_STRICT = 0; // Emscripten 'strict' build mode: Drop supporting any deprecated build options. - // Set the environment variable EMSCRIPTEN_STRICT=1 or pass -s EMSCRIPTEN_STRICT=1 - // to test that a codebase builds nicely in forward compatible manner. +var STRICT = 0; // Emscripten 'strict' build mode: Drop supporting any deprecated build options. + // Set the environment variable EMCC_STRICT=1 or pass -s STRICT=1 + // to test that a codebase builds nicely in forward compatible manner. var WARN_ON_UNDEFINED_SYMBOLS = 1; // If set to 1, we will warn on any undefined symbols that // are not resolved by the library_*.js files. Note that diff --git a/tools/shared.py b/tools/shared.py index b785431e34fd3..dcacdb1e6c426 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -472,6 +472,10 @@ def find_temp_directory(): def get_emscripten_version(path): return open(path).read().strip().replace('"', '') +# Returns true if Emscripten is running in 'strict' mode, in which deprecated compiler features are not supported. +def is_emscripten_strict(): + return (os.environ.get('EMCC_STRICT') and int(os.environ.get('EMCC_STRICT')) != 0) or Settings.STRICT + # Check that basic stuff we need (a JS engine to compile, Node.js, and Clang and LLVM) # exists. # The test runner always does this check (through |force|). emcc does this less frequently, @@ -933,7 +937,7 @@ def get_llvm_target(): '-D__unix__'] # The preprocessor define EMSCRIPTEN is deprecated. Don't pass it to code in strict mode. Code should use the define __EMSCRIPTEN__ instead. - if not os.environ.get('EMSCRIPTEN_STRICT') or int(os.environ.get('EMSCRIPTEN_STRICT')) == 0: COMPILER_OPTS += ['-DEMSCRIPTEN'] + if not is_emscripten_strict(): COMPILER_OPTS += ['-DEMSCRIPTEN'] # Changes to default clang behavior @@ -959,8 +963,8 @@ def get_llvm_target(): ] # The system include path system/include/emscripten/ is deprecated, i.e. instead of #include , one should pass in #include . - # This path is not available in EMSCRIPTEN_STRICT mode. - if not os.environ.get('EMSCRIPTEN_STRICT') or int(os.environ.get('EMSCRIPTEN_STRICT')) == 0: + # This path is not available in Emscripten strict mode. + if not is_emscripten_strict(): C_INCLUDE_PATHS += [path_from_root('system', 'include', 'emscripten')] CXX_INCLUDE_PATHS = [ @@ -1103,9 +1107,9 @@ def load(self, args=[]): exec settings # Apply default values for settings that are configured from environment variables. - if os.environ.get('EMSCRIPTEN_STRICT') and int(os.environ.get('EMSCRIPTEN_STRICT')) != 0: + if is_emscripten_strict(): # Specify default values for Emscripten strict mode. - self.attrs['EMSCRIPTEN_STRICT'] = 1 + self.attrs['STRICT'] = 1 self.attrs['ERROR_ON_UNDEFINED_SYMBOLS'] = 1 self.attrs['ERROR_ON_MISSING_LIBRARIES'] = 1 From 381eca8d997e9175f5c8e11eb317e11f5cd741b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 26 Oct 2016 12:31:32 +0300 Subject: [PATCH 08/18] Add root level include emscripten.h so that both forms #include and #include can be used in the future. --- system/include/emscripten.h | 1 + 1 file changed, 1 insertion(+) create mode 100644 system/include/emscripten.h diff --git a/system/include/emscripten.h b/system/include/emscripten.h new file mode 100644 index 0000000000000..b1aad2034aad2 --- /dev/null +++ b/system/include/emscripten.h @@ -0,0 +1 @@ +#include "emscripten/emscripten.h" From af265a581a528a5e7c0fd1ee7bdb724e7b720059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 26 Oct 2016 21:40:02 +0300 Subject: [PATCH 09/18] Finalize EMCC_STRICT mode for linking to libraries. Improve browser suite to pass in EMCC_STRICT mode. --- emcc.py | 14 +- src/library_fs.js | 18 ++- src/modules.js | 7 +- tests/test_browser.py | 332 +++++++++++++++++++++--------------------- tools/shared.py | 7 +- 5 files changed, 208 insertions(+), 170 deletions(-) diff --git a/emcc.py b/emcc.py index f7553cb83b918..1f031e809cc9f 100755 --- a/emcc.py +++ b/emcc.py @@ -954,12 +954,18 @@ def detect_fixed_language_mode(args): 'm': '', 'openal': 'library_openal.js', 'pthread': '', + 'X11': 'library_xlib.js', 'SDL': 'library_sdl.js', - 'stdc++': '' + 'stdc++': '', + 'uuid': 'library_uuid.js' } if lib in js_system_libraries: if len(js_system_libraries[lib]) > 0: system_js_libraries += [js_system_libraries[lib]] + + # TODO: This is unintentional due to historical reasons. Improve EGL to use HTML5 API to avoid depending on GLUT. + if lib == 'EGL': system_js_libraries += ['library_glut.js'] + elif lib.endswith('.js') and os.path.isfile(shared.path_from_root('src', 'library_' + lib)): system_js_libraries += ['library_' + lib] else: @@ -971,6 +977,12 @@ def detect_fixed_language_mode(args): else: logging.warning('emcc: cannot find library "%s"', lib) + # Certain linker flags imply some link libraries to be pulled in by default. + if 'EMTERPRETIFY_ASYNC=1' in settings_changes: system_js_libraries += ['library_async.js'] + if 'ASYNCIFY=1' in settings_changes: system_js_libraries += ['library_async.js'] + if 'LZ4=1' in settings_changes: system_js_libraries += ['library_lz4.js'] + if 'USE_SDL=1' in settings_changes: system_js_libraries += ['library_sdl.js'] + if 'USE_SDL=2' in settings_changes: system_js_libraries += ['library_egl.js', 'library_glut.js', 'library_gl.js'] settings_changes.append('SYSTEM_JS_LIBRARIES="' + ','.join(system_js_libraries) + '"') # If not compiling to JS, then we are compiling to an intermediate bitcode objects or library, so diff --git a/src/library_fs.js b/src/library_fs.js index 1b60f2ad29804..e581d93354fad 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -1,5 +1,15 @@ mergeInto(LibraryManager.library, { - $FS__deps: ['$ERRNO_CODES', '$ERRNO_MESSAGES', '__setErrNo', '$PATH', '$TTY', '$MEMFS', '$IDBFS', '$NODEFS', '$WORKERFS', 'stdin', 'stdout', 'stderr'], + $FS__deps: ['$ERRNO_CODES', '$ERRNO_MESSAGES', '__setErrNo', '$PATH', '$TTY', '$MEMFS', +#if __EMSCRIPTEN_HAS_idbfs_js__ + '$IDBFS', +#endif +#if __EMSCRIPTEN_HAS_nodefs_js__ + '$NODEFS', +#endif +#if __EMSCRIPTEN_HAS_workerfs_js__ + '$WORKERFS', +#endif + 'stdin', 'stdout', 'stderr'], $FS__postset: 'FS.staticInit();' + '__ATINIT__.unshift(function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() });' + '__ATMAIN__.push(function() { FS.ignorePermissions = false });' + @@ -1382,9 +1392,15 @@ mergeInto(LibraryManager.library, { FS.filesystems = { 'MEMFS': MEMFS, +#if __EMSCRIPTEN_HAS_idbfs_js__ 'IDBFS': IDBFS, +#endif +#if __EMSCRIPTEN_HAS_nodefs_js__ 'NODEFS': NODEFS, +#endif +#if __EMSCRIPTEN_HAS_workerfs_js__ 'WORKERFS': WORKERFS, +#endif }; }, init: function(input, output, error) { diff --git a/src/modules.js b/src/modules.js index 4c1c8a676e81b..c9238c3cf3e76 100644 --- a/src/modules.js +++ b/src/modules.js @@ -102,6 +102,7 @@ var LibraryManager = { 'library_browser.js', 'library_formatString.js', 'library_path.js', + 'library_signals.js', 'library_syscall.js', 'library_html5.js' ]; @@ -138,7 +139,6 @@ var LibraryManager = { 'library_glfw.js', 'library_uuid.js', 'library_glew.js', - 'library_signals.js', 'library_idbstore.js', 'library_async.js', 'library_vr.js' @@ -148,6 +148,11 @@ var LibraryManager = { // If there are any explicitly specified system JS libraries to link to, add those to link. if (SYSTEM_JS_LIBRARIES) { SYSTEM_JS_LIBRARIES = SYSTEM_JS_LIBRARIES.split(','); + // For each system JS library library_xxx.js, add a preprocessor token __EMSCRIPTEN_HAS_xxx_js__ so that code can conditionally dead code eliminate out + // if a particular feature is not being linked in. + for (var i = 0; i < SYSTEM_JS_LIBRARIES.length; ++i) { + global['__EMSCRIPTEN_HAS_' + SYSTEM_JS_LIBRARIES[i].replace('.', '_').replace('library_', '') + '__'] = 1 + } libraries = libraries.concat(SYSTEM_JS_LIBRARIES); } diff --git a/tests/test_browser.py b/tests/test_browser.py index 4e00a91feff59..425831b0665f6 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -62,8 +62,8 @@ def setUpClass(self): print def test_sdl1(self): - self.btest('hello_world_sdl.cpp', reference='htmltest.png') - self.btest('hello_world_sdl.cpp', reference='htmltest.png', args=['-s', 'USE_SDL=1']) # is the default anyhow + self.btest('hello_world_sdl.cpp', reference='htmltest.png', args=['-lSDL', '-lGL']) + self.btest('hello_world_sdl.cpp', reference='htmltest.png', args=['-s', 'USE_SDL=1', '-lGL']) # is the default anyhow def test_html_source_map(self): cpp_file = os.path.join(self.get_dir(), 'src.cpp') @@ -560,11 +560,11 @@ def test(): #test() def test_sdl_swsurface(self): - self.btest('sdl_swsurface.c', expected='1') + self.btest('sdl_swsurface.c', args=['-lSDL', '-lGL'], expected='1') def test_sdl_surface_lock_opts(self): # Test Emscripten-specific extensions to optimize SDL_LockSurface and SDL_UnlockSurface. - self.btest('hello_world_sdl.cpp', reference='htmltest.png', message='You should see "hello, world!" and a colored cube.', args=['-DTEST_SDL_LOCK_OPTS']) + self.btest('hello_world_sdl.cpp', reference='htmltest.png', message='You should see "hello, world!" and a colored cube.', args=['-DTEST_SDL_LOCK_OPTS', '-lSDL', '-lGL']) def test_sdl_image(self): # load an image file, get pixel data. Also O2 coverage for --preload-file, and memory-init @@ -575,7 +575,7 @@ def test_sdl_image(self): for dest, dirname, basename in [('screenshot.jpg', '/', 'screenshot.jpg'), ('screenshot.jpg@/assets/screenshot.jpg', '/assets', 'screenshot.jpg')]: Popen([ - PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_image.c'), '-o', 'page.html', '-O2', '--memory-init-file', str(mem), + PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_image.c'), '-o', 'page.html', '-O2', '-lSDL', '-lGL', '--memory-init-file', str(mem), '--preload-file', dest, '-DSCREENSHOT_DIRNAME="' + dirname + '"', '-DSCREENSHOT_BASENAME="' + basename + '"', '--use-preload-plugins' ]).communicate() self.run_browser('page.html', '', '/report_result?600') @@ -584,7 +584,7 @@ def test_sdl_image_jpeg(self): shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.jpeg')) open(os.path.join(self.get_dir(), 'sdl_image_jpeg.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_image.c')).read())) Popen([ - PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_image_jpeg.c'), '-o', 'page.html', + PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_image_jpeg.c'), '-o', 'page.html', '-lSDL', '-lGL', '--preload-file', 'screenshot.jpeg', '-DSCREENSHOT_DIRNAME="/"', '-DSCREENSHOT_BASENAME="screenshot.jpeg"', '--use-preload-plugins' ]).communicate() self.run_browser('page.html', '', '/report_result?600') @@ -592,36 +592,36 @@ def test_sdl_image_jpeg(self): def test_sdl_image_prepare(self): # load an image file, get pixel data. shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.not')) - self.btest('sdl_image_prepare.c', reference='screenshot.jpg', args=['--preload-file', 'screenshot.not'], also_proxied=True) + self.btest('sdl_image_prepare.c', reference='screenshot.jpg', args=['--preload-file', 'screenshot.not', '-lSDL', '-lGL'], also_proxied=True) def test_sdl_image_prepare_data(self): # load an image file, get pixel data. shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.not')) - self.btest('sdl_image_prepare_data.c', reference='screenshot.jpg', args=['--preload-file', 'screenshot.not']) + self.btest('sdl_image_prepare_data.c', reference='screenshot.jpg', args=['--preload-file', 'screenshot.not', '-lSDL', '-lGL']) def test_sdl_image_must_prepare(self): # load an image file, get pixel data. shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.jpg')) - self.btest('sdl_image_must_prepare.c', reference='screenshot.jpg', args=['--preload-file', 'screenshot.jpg']) + self.btest('sdl_image_must_prepare.c', reference='screenshot.jpg', args=['--preload-file', 'screenshot.jpg', '-lSDL', '-lGL']) def test_sdl_stb_image(self): # load an image file, get pixel data. shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.not')) - self.btest('sdl_stb_image.c', reference='screenshot.jpg', args=['-s', 'STB_IMAGE=1', '--preload-file', 'screenshot.not']) + self.btest('sdl_stb_image.c', reference='screenshot.jpg', args=['-s', 'STB_IMAGE=1', '--preload-file', 'screenshot.not', '-lSDL', '-lGL']) def test_sdl_stb_image_data(self): # load an image file, get pixel data. shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.not')) - self.btest('sdl_stb_image_data.c', reference='screenshot.jpg', args=['-s', 'STB_IMAGE=1', '--preload-file', 'screenshot.not']) + self.btest('sdl_stb_image_data.c', reference='screenshot.jpg', args=['-s', 'STB_IMAGE=1', '--preload-file', 'screenshot.not', '-lSDL', '-lGL']) def test_sdl_canvas(self): self.clear() - self.btest('sdl_canvas.c', expected='1', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('sdl_canvas.c', expected='1', args=['-s', 'LEGACY_GL_EMULATION=1', '-lSDL', '-lGL']) # some extra coverage self.clear() - self.btest('sdl_canvas.c', expected='1', args=['-s', 'LEGACY_GL_EMULATION=1', '-O0', '-s', 'SAFE_HEAP=1']) + self.btest('sdl_canvas.c', expected='1', args=['-s', 'LEGACY_GL_EMULATION=1', '-O0', '-s', 'SAFE_HEAP=1', '-lSDL', '-lGL']) self.clear() - self.btest('sdl_canvas.c', expected='1', args=['-s', 'LEGACY_GL_EMULATION=1', '-O2', '-s', 'SAFE_HEAP=1']) + self.btest('sdl_canvas.c', expected='1', args=['-s', 'LEGACY_GL_EMULATION=1', '-O2', '-s', 'SAFE_HEAP=1', '-lSDL', '-lGL']) def post_manual_reftest(self, reference=None): self.reftest(path_from_root('tests', self.reference if reference is None else reference)) @@ -647,10 +647,10 @@ def post_manual_reftest(self, reference=None): def test_sdl_canvas_proxy(self): open('data.txt', 'w').write('datum') - self.btest('sdl_canvas_proxy.c', reference='sdl_canvas_proxy.png', args=['--proxy-to-worker', '--preload-file', 'data.txt'], manual_reference=True, post_build=self.post_manual_reftest) + self.btest('sdl_canvas_proxy.c', reference='sdl_canvas_proxy.png', args=['--proxy-to-worker', '--preload-file', 'data.txt', '-lSDL', '-lGL'], manual_reference=True, post_build=self.post_manual_reftest) def test_glgears_proxy(self): - self.btest('hello_world_gles_proxy.c', reference='gears.png', args=['--proxy-to-worker', '-s', 'GL_TESTING=1', '-DSTATIC_GEARS=1'], manual_reference=True, post_build=self.post_manual_reftest) + self.btest('hello_world_gles_proxy.c', reference='gears.png', args=['--proxy-to-worker', '-s', 'GL_TESTING=1', '-DSTATIC_GEARS=1', '-lGL', '-lglut'], manual_reference=True, post_build=self.post_manual_reftest) # test noProxy option applied at runtime @@ -682,7 +682,7 @@ def copy(to, js_mod, html_mod = lambda x: x): def test_glgears_proxy_jstarget(self): # test .js target with --proxy-worker; emits 2 js files, client and worker - Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles_proxy.c'), '-o', 'test.js', '--proxy-to-worker', '-s', 'GL_TESTING=1']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles_proxy.c'), '-o', 'test.js', '--proxy-to-worker', '-s', 'GL_TESTING=1', '-lGL', '-lglut']).communicate() open('test.html', 'w').write(open(path_from_root('src', 'shell_minimal.html')).read().replace('{{{ SCRIPT }}}', '')) self.post_manual_reftest('gears.png') self.run_browser('test.html', None, '/report_result?0') @@ -694,8 +694,8 @@ def test_sdl_canvas_alpha(self): Module['arguments'] = ['-0']; ''') - self.btest('sdl_canvas_alpha.c', reference='sdl_canvas_alpha.png', reference_slack=12) - self.btest('sdl_canvas_alpha.c', args=['--pre-js', 'flag_0.js'], reference='sdl_canvas_alpha_flag_0.png', reference_slack=12) + self.btest('sdl_canvas_alpha.c', args=['-lSDL', '-lGL'], reference='sdl_canvas_alpha.png', reference_slack=12) + self.btest('sdl_canvas_alpha.c', args=['--pre-js', 'flag_0.js', '-lSDL', '-lGL'], reference='sdl_canvas_alpha_flag_0.png', reference_slack=12) def test_sdl_key(self): @@ -734,7 +734,7 @@ def test_sdl_key(self): ''' % ('setTimeout(function() {' if delay else '', '}, 1);' if delay else '', 'setTimeout(function() {' if delay else '', '}, 1);' if delay else '')) open(os.path.join(self.get_dir(), 'sdl_key.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_key.c')).read())) - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_key.c'), '-o', 'page.html'] + defines + emterps + ['--pre-js', 'pre.js', '-s', '''EXPORTED_FUNCTIONS=['_main']''', '-s', 'NO_EXIT_RUNTIME=1']).communicate() + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_key.c'), '-o', 'page.html'] + defines + emterps + ['--pre-js', 'pre.js', '-s', '''EXPORTED_FUNCTIONS=['_main']''', '-s', 'NO_EXIT_RUNTIME=1', '-lSDL', '-lGL']).communicate() self.run_browser('page.html', '', '/report_result?223092870') def test_sdl_key_proxy(self): @@ -781,7 +781,7 @@ def post(): ''') open('test.html', 'w').write(html) - self.btest('sdl_key_proxy.c', '223092870', args=['--proxy-to-worker', '--pre-js', 'pre.js', '-s', '''EXPORTED_FUNCTIONS=['_main', '_one']''', '-s', 'NO_EXIT_RUNTIME=1'], manual_reference=True, post_build=post) + self.btest('sdl_key_proxy.c', '223092870', args=['--proxy-to-worker', '--pre-js', 'pre.js', '-s', '''EXPORTED_FUNCTIONS=['_main', '_one']''', '-s', 'NO_EXIT_RUNTIME=1', '-lSDL', '-lGL'], manual_reference=True, post_build=post) def test_keydown_preventdefault_proxy(self): def post(): @@ -858,7 +858,7 @@ def test_sdl_text(self): ''') open(os.path.join(self.get_dir(), 'sdl_text.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_text.c')).read())) - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_text.c'), '-o', 'page.html', '--pre-js', 'pre.js', '-s', '''EXPORTED_FUNCTIONS=['_main', '_one']''']).communicate() + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_text.c'), '-o', 'page.html', '--pre-js', 'pre.js', '-s', '''EXPORTED_FUNCTIONS=['_main', '_one']''', '-lSDL', '-lGL']).communicate() self.run_browser('page.html', '', '/report_result?1') def test_sdl_mouse(self): @@ -891,7 +891,7 @@ def test_sdl_mouse(self): ''') open(os.path.join(self.get_dir(), 'sdl_mouse.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_mouse.c')).read())) - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_mouse.c'), '-O2', '--minify', '0', '-o', 'page.html', '--pre-js', 'pre.js']).communicate() + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_mouse.c'), '-O2', '--minify', '0', '-o', 'page.html', '--pre-js', 'pre.js', '-lSDL', '-lGL']).communicate() self.run_browser('page.html', '', '/report_result?1') def test_sdl_mouse_offsets(self): @@ -969,14 +969,14 @@ def test_sdl_mouse_offsets(self): ''') open(os.path.join(self.get_dir(), 'sdl_mouse.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_mouse.c')).read())) - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_mouse.c'), '-DTEST_SDL_MOUSE_OFFSETS', '-O2', '--minify', '0', '-o', 'sdl_mouse.js', '--pre-js', 'pre.js']).communicate() + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_mouse.c'), '-DTEST_SDL_MOUSE_OFFSETS', '-O2', '--minify', '0', '-o', 'sdl_mouse.js', '--pre-js', 'pre.js', '-lSDL', '-lGL']).communicate() self.run_browser('page.html', '', '/report_result?1') def test_glut_touchevents(self): - self.btest('glut_touchevents.c', '1') + self.btest('glut_touchevents.c', '1', args=['-lglut']) def test_glut_wheelevents(self): - self.btest('glut_wheelevents.c', '1') + self.btest('glut_wheelevents.c', '1', args=['-lglut']) def test_sdl_joystick_1(self): # Generates events corresponding to the Working Draft of the HTML5 Gamepad API. @@ -1011,7 +1011,7 @@ def test_sdl_joystick_1(self): ''') open(os.path.join(self.get_dir(), 'sdl_joystick.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_joystick.c')).read())) - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_joystick.c'), '-O2', '--minify', '0', '-o', 'page.html', '--pre-js', 'pre.js']).communicate() + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_joystick.c'), '-O2', '--minify', '0', '-o', 'page.html', '--pre-js', 'pre.js', '-lSDL', '-lGL']).communicate() self.run_browser('page.html', '', '/report_result?2') def test_sdl_joystick_2(self): @@ -1051,7 +1051,7 @@ def test_sdl_joystick_2(self): ''') open(os.path.join(self.get_dir(), 'sdl_joystick.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_joystick.c')).read())) - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_joystick.c'), '-O2', '--minify', '0', '-o', 'page.html', '--pre-js', 'pre.js']).communicate() + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_joystick.c'), '-O2', '--minify', '0', '-o', 'page.html', '--pre-js', 'pre.js', '-lSDL', '-lGL']).communicate() self.run_browser('page.html', '', '/report_result?2') def test_webgl_context_attributes(self): @@ -1093,14 +1093,14 @@ def test_webgl_context_attributes(self): shutil.copyfile(filepath, temp_filepath) # perform tests with attributes activated - self.btest('test_webgl_context_attributes_glut.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED']) - self.btest('test_webgl_context_attributes_sdl.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED']) - self.btest('test_webgl_context_attributes_glfw.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED']) + self.btest('test_webgl_context_attributes_glut.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-lglut', '-lGLEW']) + self.btest('test_webgl_context_attributes_sdl.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-lSDL', '-lGLEW']) + self.btest('test_webgl_context_attributes_glfw.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-lglfw', '-lGLEW']) # perform tests with attributes desactivated - self.btest('test_webgl_context_attributes_glut.c', '1', args=['--js-library', 'check_webgl_attributes_support.js']) - self.btest('test_webgl_context_attributes_sdl.c', '1', args=['--js-library', 'check_webgl_attributes_support.js']) - self.btest('test_webgl_context_attributes_glfw.c', '1', args=['--js-library', 'check_webgl_attributes_support.js']) + self.btest('test_webgl_context_attributes_glut.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-lGL', '-lglut', '-lGLEW']) + self.btest('test_webgl_context_attributes_sdl.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-lGL', '-lSDL', '-lGLEW']) + self.btest('test_webgl_context_attributes_glfw.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-lGL', '-lglfw', '-lGLEW']) def test_emscripten_get_now(self): self.btest('emscripten_get_now.cpp', '1') @@ -1124,8 +1124,8 @@ def test_fs_idbfs_sync(self): for mode in [[], ['-s', 'MEMFS_APPEND_TO_TYPED_ARRAYS=1']]: for extra in [[], ['-DEXTRA_WORK']]: secret = str(time.time()) - self.btest(path_from_root('tests', 'fs', 'test_idbfs_sync.c'), '1', force_c=True, args=mode + ['-DFIRST', '-DSECRET=\"' + secret + '\"', '-s', '''EXPORTED_FUNCTIONS=['_main', '_test', '_success']''']) - self.btest(path_from_root('tests', 'fs', 'test_idbfs_sync.c'), '1', force_c=True, args=mode + ['-DSECRET=\"' + secret + '\"', '-s', '''EXPORTED_FUNCTIONS=['_main', '_test', '_success']'''] + extra) + self.btest(path_from_root('tests', 'fs', 'test_idbfs_sync.c'), '1', force_c=True, args=mode + ['-lidbfs.js', '-DFIRST', '-DSECRET=\"' + secret + '\"', '-s', '''EXPORTED_FUNCTIONS=['_main', '_test', '_success']''']) + self.btest(path_from_root('tests', 'fs', 'test_idbfs_sync.c'), '1', force_c=True, args=mode + ['-lidbfs.js', '-DSECRET=\"' + secret + '\"', '-s', '''EXPORTED_FUNCTIONS=['_main', '_test', '_success']'''] + extra) def test_fs_idbfs_fsync(self): # sync from persisted state into memory before main() @@ -1142,7 +1142,7 @@ def test_fs_idbfs_fsync(self): }; ''') - args = ['--pre-js', 'pre.js', '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1']; + args = ['--pre-js', 'pre.js', '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-lidbfs.js'] for mode in [[], ['-s', 'MEMFS_APPEND_TO_TYPED_ARRAYS=1']]: secret = str(time.time()) self.btest(path_from_root('tests', 'fs', 'test_idbfs_fsync.c'), '1', force_c=True, args=args + mode + ['-DFIRST', '-DSECRET=\"' + secret + '\"', '-s', '''EXPORTED_FUNCTIONS=['_main', '_success']''']) @@ -1169,14 +1169,14 @@ def test_fs_workerfs_read(self): }, '/work'); }; ''' % (secret, secret2)) - self.btest(path_from_root('tests', 'fs', 'test_workerfs_read.c'), '1', force_c=True, args=['--pre-js', 'pre.js', '-DSECRET=\"' + secret + '\"', '-DSECRET2=\"' + secret2 + '\"', '--proxy-to-worker']) + self.btest(path_from_root('tests', 'fs', 'test_workerfs_read.c'), '1', force_c=True, args=['-lworkerfs.js', '--pre-js', 'pre.js', '-DSECRET=\"' + secret + '\"', '-DSECRET2=\"' + secret2 + '\"', '--proxy-to-worker']) def test_fs_workerfs_package(self): open('file1.txt', 'w').write('first') if not os.path.exists('sub'): os.makedirs('sub') open(os.path.join('sub', 'file2.txt'), 'w').write('second') Popen([PYTHON, FILE_PACKAGER, 'files.data', '--preload', 'file1.txt', os.path.join('sub', 'file2.txt'), '--separate-metadata', '--js-output=files.js']).communicate() - self.btest(os.path.join('fs', 'test_workerfs_package.cpp'), '1', args=['--proxy-to-worker']) + self.btest(os.path.join('fs', 'test_workerfs_package.cpp'), '1', args=['-lworkerfs.js', '--proxy-to-worker']) def test_fs_lz4fs_package(self): # generate data @@ -1230,17 +1230,17 @@ def test_idbstore(self): secret = str(time.time()) for stage in [0, 1, 2, 3, 0, 1, 2, 0, 0, 1, 4, 2, 5]: self.clear() - self.btest(path_from_root('tests', 'idbstore.c'), str(stage), force_c=True, args=['-DSTAGE=' + str(stage), '-DSECRET=\"' + secret + '\"']) + self.btest(path_from_root('tests', 'idbstore.c'), str(stage), force_c=True, args=['-lidbstore.js', '-DSTAGE=' + str(stage), '-DSECRET=\"' + secret + '\"']) def test_idbstore_sync(self): secret = str(time.time()) self.clear() - self.btest(path_from_root('tests', 'idbstore_sync.c'), '6', force_c=True, args=['-DSECRET=\"' + secret + '\"', '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '--memory-init-file', '1', '-O3', '-g2']) + self.btest(path_from_root('tests', 'idbstore_sync.c'), '6', force_c=True, args=['-lidbstore.js', '-DSECRET=\"' + secret + '\"', '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '--memory-init-file', '1', '-O3', '-g2']) def test_idbstore_sync_worker(self): secret = str(time.time()) self.clear() - self.btest(path_from_root('tests', 'idbstore_sync_worker.c'), '6', force_c=True, args=['-DSECRET=\"' + secret + '\"', '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '--memory-init-file', '1', '-O3', '-g2', '--proxy-to-worker', '-s', 'TOTAL_MEMORY=75000000']) + self.btest(path_from_root('tests', 'idbstore_sync_worker.c'), '6', force_c=True, args=['-lidbstore.js', '-DSECRET=\"' + secret + '\"', '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '--memory-init-file', '1', '-O3', '-g2', '--proxy-to-worker', '-s', 'TOTAL_MEMORY=75000000']) def test_force_exit(self): self.btest('force_exit.c', force_c=True, expected='17') @@ -1256,94 +1256,94 @@ def test_sdl_pumpevents(self): document.dispatchEvent(event); } ''') - self.btest('sdl_pumpevents.c', expected='7', args=['--pre-js', 'pre.js']) + self.btest('sdl_pumpevents.c', expected='7', args=['--pre-js', 'pre.js', '-lSDL', '-lGL']) def test_sdl_canvas_size(self): self.btest('sdl_canvas_size.c', expected='1', - args=['-O2', '--minify', '0', '--shell-file', path_from_root('tests', 'sdl_canvas_size.html')]) + args=['-O2', '--minify', '0', '--shell-file', path_from_root('tests', 'sdl_canvas_size.html'), '-lSDL', '-lGL']) def test_sdl_gl_read(self): # SDL, OpenGL, readPixels open(os.path.join(self.get_dir(), 'sdl_gl_read.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_gl_read.c')).read())) - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_gl_read.c'), '-o', 'something.html']).communicate() + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_gl_read.c'), '-o', 'something.html', '-lSDL', '-lGL']).communicate() self.run_browser('something.html', '.', '/report_result?1') def test_sdl_gl_mapbuffers(self): - self.btest('sdl_gl_mapbuffers.c', expected='1', args=['-s', 'FULL_ES3=1'], + self.btest('sdl_gl_mapbuffers.c', expected='1', args=['-s', 'FULL_ES3=1', '-lSDL', '-lGL'], message='You should see a blue triangle.') def test_sdl_ogl(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_ogl.c', reference='screenshot-gray-purple.png', reference_slack=1, - args=['-O2', '--minify', '0', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins'], + args=['-O2', '--minify', '0', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins', '-lSDL', '-lGL'], message='You should see an image with gray at the top.') def test_sdl_ogl_defaultmatrixmode(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_ogl_defaultMatrixMode.c', reference='screenshot-gray-purple.png', reference_slack=1, - args=['--minify', '0', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins'], + args=['--minify', '0', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins', '-lSDL', '-lGL'], message='You should see an image with gray at the top.') def test_sdl_ogl_p(self): # Immediate mode with pointers shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_ogl_p.c', reference='screenshot-gray.png', reference_slack=1, - args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins'], + args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins', '-lSDL', '-lGL'], message='You should see an image with gray at the top.') def test_sdl_ogl_proc_alias(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_ogl_proc_alias.c', reference='screenshot-gray-purple.png', reference_slack=1, - args=['-O2', '-g2', '-s', 'INLINING_LIMIT=1', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins']) + args=['-O2', '-g2', '-s', 'INLINING_LIMIT=1', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins', '-lSDL', '-lGL']) def test_sdl_fog_simple(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_fog_simple.c', reference='screenshot-fog-simple.png', - args=['-O2', '--minify', '0', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins'], + args=['-O2', '--minify', '0', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins', '-lSDL', '-lGL'], message='You should see an image with fog.') def test_sdl_fog_negative(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_fog_negative.c', reference='screenshot-fog-negative.png', - args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins'], + args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins', '-lSDL', '-lGL'], message='You should see an image with fog.') def test_sdl_fog_density(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_fog_density.c', reference='screenshot-fog-density.png', - args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins'], + args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins', '-lSDL', '-lGL'], message='You should see an image with fog.') def test_sdl_fog_exp2(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_fog_exp2.c', reference='screenshot-fog-exp2.png', - args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins'], + args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins', '-lSDL', '-lGL'], message='You should see an image with fog.') def test_sdl_fog_linear(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_fog_linear.c', reference='screenshot-fog-linear.png', reference_slack=1, - args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins'], + args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins', '-lSDL', '-lGL'], message='You should see an image with fog.') def test_glfw(self): - self.btest('glfw.c', '1', args=['-s', 'LEGACY_GL_EMULATION=1']) - self.btest('glfw.c', '1', args=['-s', 'LEGACY_GL_EMULATION=1', '-s', 'USE_GLFW=2']) + self.btest('glfw.c', '1', args=['-s', 'LEGACY_GL_EMULATION=1', '-lglfw', '-lGL']) + self.btest('glfw.c', '1', args=['-s', 'LEGACY_GL_EMULATION=1', '-s', 'USE_GLFW=2', '-lglfw', '-lGL']) def test_glfw_minimal(self): - self.btest('glfw_minimal.c', '1', args=[]) - self.btest('glfw_minimal.c', '1', args=['-s', 'USE_GLFW=2']) + self.btest('glfw_minimal.c', '1', args=['-lglfw', '-lGL']) + self.btest('glfw_minimal.c', '1', args=['-s', 'USE_GLFW=2', '-lglfw', '-lGL']) def test_egl(self): open(os.path.join(self.get_dir(), 'test_egl.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'test_egl.c')).read())) - Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'test_egl.c'), '-o', 'page.html']).communicate() + Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'test_egl.c'), '-o', 'page.html', '-lEGL', '-lGL']).communicate() self.run_browser('page.html', '', '/report_result?1') def test_egl_width_height(self): open(os.path.join(self.get_dir(), 'test_egl_width_height.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'test_egl_width_height.c')).read())) - Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'test_egl_width_height.c'), '-o', 'page.html']).communicate() + Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'test_egl_width_height.c'), '-o', 'page.html', '-lEGL', '-lGL']).communicate() self.run_browser('page.html', 'Should print "(300, 150)" -- the size of the canvas in pixels', '/report_result?1') def test_worker(self): @@ -1454,31 +1454,31 @@ def test_chunked_synchronous_xhr(self): def test_glgears(self): self.btest('hello_world_gles.c', reference='gears.png', reference_slack=3, - args=['-DHAVE_BUILTIN_SINCOS'], outfile='something.html', + args=['-DHAVE_BUILTIN_SINCOS', '-lGL', '-lglut'], outfile='something.html', message='You should see animating gears.') def test_glgears_long(self): for proxy in [0, 1]: print 'proxy', proxy - self.btest('hello_world_gles.c', expected=map(str, range(30, 500)), args=['-DHAVE_BUILTIN_SINCOS', '-DLONGTEST'] + (['--proxy-to-worker'] if proxy else []), timeout=30) + self.btest('hello_world_gles.c', expected=map(str, range(30, 500)), args=['-DHAVE_BUILTIN_SINCOS', '-DLONGTEST', '-lGL', '-lglut'] + (['--proxy-to-worker'] if proxy else []), timeout=30) def test_glgears_animation(self): es2_suffix = ['', '_full', '_full_944'] for full_es2 in [0, 1, 2]: print full_es2 Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles%s.c' % es2_suffix[full_es2]), '-o', 'something.html', - '-DHAVE_BUILTIN_SINCOS', '-s', 'GL_TESTING=1', + '-DHAVE_BUILTIN_SINCOS', '-s', 'GL_TESTING=1', '-lGL', '-lglut', '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')] + (['-s', 'FULL_ES2=1'] if full_es2 else []), ).communicate() self.run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true') def test_fulles2_sdlproc(self): - self.btest('full_es2_sdlproc.c', '1', args=['-s', 'GL_TESTING=1', '-DHAVE_BUILTIN_SINCOS', '-s', 'FULL_ES2=1']) + self.btest('full_es2_sdlproc.c', '1', args=['-s', 'GL_TESTING=1', '-DHAVE_BUILTIN_SINCOS', '-s', 'FULL_ES2=1', '-lGL', '-lSDL', '-lglut']) def test_glgears_deriv(self): self.btest('hello_world_gles_deriv.c', reference='gears.png', reference_slack=2, - args=['-DHAVE_BUILTIN_SINCOS'], outfile='something.html', + args=['-DHAVE_BUILTIN_SINCOS', '-lGL', '-lglut'], outfile='something.html', message='You should see animating gears.') with open('something.html') as f: assert 'gl-matrix' not in f.read(), 'Should not include glMatrix when not needed' @@ -1498,14 +1498,14 @@ def book_path(*pathelems): for program in programs: print program basename = os.path.basename(program) - args = [] + args = ['-lGL', '-lEGL', '-lX11'] if basename == 'CH10_MultiTexture.bc': shutil.copyfile(book_path('Chapter_10', 'MultiTexture', 'basemap.tga'), os.path.join(self.get_dir(), 'basemap.tga')) shutil.copyfile(book_path('Chapter_10', 'MultiTexture', 'lightmap.tga'), os.path.join(self.get_dir(), 'lightmap.tga')) - args = ['--preload-file', 'basemap.tga', '--preload-file', 'lightmap.tga'] + args += ['--preload-file', 'basemap.tga', '--preload-file', 'lightmap.tga'] elif basename == 'CH13_ParticleSystem.bc': shutil.copyfile(book_path('Chapter_13', 'ParticleSystem', 'smoke.tga'), os.path.join(self.get_dir(), 'smoke.tga')) - args = ['--preload-file', 'smoke.tga', '-O2'] # test optimizations and closure here as well for more coverage + args += ['--preload-file', 'smoke.tga', '-O2'] # test optimizations and closure here as well for more coverage self.btest(program, reference=book_path(basename.replace('.bc', '.png')), args=args, timeout=30) @@ -1532,11 +1532,11 @@ def test_gles2_emulation(self): path_from_root('tests', 'glbook', 'Common', 'esShader.c'), path_from_root('tests', 'glbook', 'Common', 'esShapes.c'), path_from_root('tests', 'glbook', 'Common', 'esTransform.c'), - '-s', 'FULL_ES2=1', + '-s', 'FULL_ES2=1', '-lGL', '-lEGL', '-lX11', '--preload-file', 'basemap.tga', '--preload-file', 'lightmap.tga', '--preload-file', 'smoke.tga']) def test_emscripten_api(self): - self.btest('emscripten_api_browser.cpp', '1', args=['-s', '''EXPORTED_FUNCTIONS=['_main', '_third']''']) + self.btest('emscripten_api_browser.cpp', '1', args=['-s', '''EXPORTED_FUNCTIONS=['_main', '_third']''', '-lSDL']) def test_emscripten_api2(self): def setup(): @@ -1563,7 +1563,7 @@ def test_emscripten_api_infloop(self): def test_emscripten_fs_api(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) # preloaded *after* run - self.btest('emscripten_fs_api_browser.cpp', '1') + self.btest('emscripten_fs_api_browser.cpp', '1', args=['-lSDL']) def test_emscripten_fs_api2(self): self.btest('emscripten_fs_api_browser2.cpp', '1', args=['-s', "ASSERTIONS=0"]) @@ -1583,80 +1583,80 @@ def test_emscripten_main_loop_setimmediate(self): self.btest('emscripten_main_loop_setimmediate.cpp', '1', args=args) def test_sdl_quit(self): - self.btest('sdl_quit.c', '1') + self.btest('sdl_quit.c', '1', args=['-lSDL', '-lGL']) def test_sdl_resize(self): - self.btest('sdl_resize.c', '1') + self.btest('sdl_resize.c', '1', args=['-lSDL', '-lGL']) def test_glshaderinfo(self): - self.btest('glshaderinfo.cpp', '1') + self.btest('glshaderinfo.cpp', '1', args=['-lGL', '-lglut']) def test_glgetattachedshaders(self): - self.btest('glgetattachedshaders.c', '1') + self.btest('glgetattachedshaders.c', '1', args=['-lGL', '-lEGL']) def test_sdlglshader(self): - self.btest('sdlglshader.c', reference='sdlglshader.png', args=['-O2', '--closure', '1', '-s', 'LEGACY_GL_EMULATION=1']) + self.btest('sdlglshader.c', reference='sdlglshader.png', args=['-O2', '--closure', '1', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_sdlglshader2(self): - self.btest('sdlglshader2.c', expected='1', args=['-s', 'LEGACY_GL_EMULATION=1'], also_proxied=True) + self.btest('sdlglshader2.c', expected='1', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL'], also_proxied=True) def test_gl_glteximage(self): - self.btest('gl_teximage.c', '1') + self.btest('gl_teximage.c', '1', args=['-lGL', '-lSDL']) def test_gl_textures(self): - self.btest('gl_textures.cpp', '0') + self.btest('gl_textures.cpp', '0', args=['-lGL']) def test_gl_ps(self): # pointers and a shader shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('gl_ps.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins'], reference_slack=1) + self.btest('gl_ps.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL', '--use-preload-plugins'], reference_slack=1) def test_gl_ps_packed(self): # packed data that needs to be strided shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('gl_ps_packed.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins'], reference_slack=1) + self.btest('gl_ps_packed.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL', '--use-preload-plugins'], reference_slack=1) def test_gl_ps_strides(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('gl_ps_strides.c', reference='gl_ps_strides.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins']) + self.btest('gl_ps_strides.c', reference='gl_ps_strides.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL', '--use-preload-plugins']) def test_gl_ps_worker(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('gl_ps_worker.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins'], reference_slack=1, also_proxied=True) + self.btest('gl_ps_worker.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL', '--use-preload-plugins'], reference_slack=1, also_proxied=True) def test_gl_renderers(self): - self.btest('gl_renderers.c', reference='gl_renderers.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1']) + self.btest('gl_renderers.c', reference='gl_renderers.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_gl_stride(self): - self.btest('gl_stride.c', reference='gl_stride.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1']) + self.btest('gl_stride.c', reference='gl_stride.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_gl_vertex_buffer_pre(self): - self.btest('gl_vertex_buffer_pre.c', reference='gl_vertex_buffer_pre.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1']) + self.btest('gl_vertex_buffer_pre.c', reference='gl_vertex_buffer_pre.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_gl_vertex_buffer(self): - self.btest('gl_vertex_buffer.c', reference='gl_vertex_buffer.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1'], reference_slack=1) + self.btest('gl_vertex_buffer.c', reference='gl_vertex_buffer.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL'], reference_slack=1) def test_gles2_uniform_arrays(self): - self.btest('gles2_uniform_arrays.cpp', args=['-s', 'GL_ASSERTIONS=1'], expected=['1'], also_proxied=True) + self.btest('gles2_uniform_arrays.cpp', args=['-s', 'GL_ASSERTIONS=1', '-lGL', '-lSDL'], expected=['1'], also_proxied=True) def test_gles2_conformance(self): - self.btest('gles2_conformance.cpp', args=['-s', 'GL_ASSERTIONS=1'], expected=['1']) + self.btest('gles2_conformance.cpp', args=['-s', 'GL_ASSERTIONS=1', '-lGL', '-lSDL'], expected=['1']) def test_matrix_identity(self): - self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840', '1588195328'], args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840', '1588195328'], args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_pre(self): - self.btest('cubegeom_pre.c', reference='cubegeom_pre.png', args=['-s', 'LEGACY_GL_EMULATION=1']) - self.btest('cubegeom_pre.c', reference='cubegeom_pre.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-s', 'RELOCATABLE=1']) + self.btest('cubegeom_pre.c', reference='cubegeom_pre.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) + self.btest('cubegeom_pre.c', reference='cubegeom_pre.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL', '-s', 'RELOCATABLE=1']) def test_cubegeom_pre2(self): - self.btest('cubegeom_pre2.c', reference='cubegeom_pre2.png', args=['-s', 'GL_DEBUG=1', '-s', 'LEGACY_GL_EMULATION=1']) # some coverage for GL_DEBUG not breaking the build + self.btest('cubegeom_pre2.c', reference='cubegeom_pre2.png', args=['-s', 'GL_DEBUG=1', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) # some coverage for GL_DEBUG not breaking the build def test_cubegeom_pre3(self): - self.btest('cubegeom_pre3.c', reference='cubegeom_pre2.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_pre3.c', reference='cubegeom_pre2.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom(self): - self.btest('cubegeom.c', reference='cubegeom.png', args=['-O2', '-g', '-s', 'LEGACY_GL_EMULATION=1'], also_proxied=True) + self.btest('cubegeom.c', reference='cubegeom.png', args=['-O2', '-g', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL'], also_proxied=True) def test_cubegeom_proc(self): open('side.c', 'w').write(r''' @@ -1671,87 +1671,87 @@ def test_cubegeom_proc(self): } ''') for opts in [0, 1]: - self.btest('cubegeom_proc.c', reference='cubegeom.png', args=['-O' + str(opts), 'side.c', '-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_proc.c', reference='cubegeom.png', args=['-O' + str(opts), 'side.c', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_glew(self): - self.btest('cubegeom_glew.c', reference='cubegeom.png', args=['-O2', '--closure', '1', '-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_glew.c', reference='cubegeom.png', args=['-O2', '--closure', '1', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lGLEW', '-lSDL']) def test_cubegeom_color(self): - self.btest('cubegeom_color.c', reference='cubegeom_color.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_color.c', reference='cubegeom_color.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_normal(self): - self.btest('cubegeom_normal.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1'], also_proxied=True) + self.btest('cubegeom_normal.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL'], also_proxied=True) def test_cubegeom_normal_dap(self): # draw is given a direct pointer to clientside memory, no element array buffer - self.btest('cubegeom_normal_dap.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1'], also_proxied=True) + self.btest('cubegeom_normal_dap.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL'], also_proxied=True) def test_cubegeom_normal_dap_far(self): # indices do nto start from 0 - self.btest('cubegeom_normal_dap_far.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_normal_dap_far.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_normal_dap_far_range(self): # glDrawRangeElements - self.btest('cubegeom_normal_dap_far_range.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_normal_dap_far_range.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_normal_dap_far_glda(self): # use glDrawArrays - self.btest('cubegeom_normal_dap_far_glda.c', reference='cubegeom_normal_dap_far_glda.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_normal_dap_far_glda.c', reference='cubegeom_normal_dap_far_glda.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_normal_dap_far_glda_quad(self): # with quad - self.btest('cubegeom_normal_dap_far_glda_quad.c', reference='cubegeom_normal_dap_far_glda_quad.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_normal_dap_far_glda_quad.c', reference='cubegeom_normal_dap_far_glda_quad.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_mt(self): - self.btest('cubegeom_mt.c', reference='cubegeom_mt.png', args=['-s', 'LEGACY_GL_EMULATION=1']) # multitexture + self.btest('cubegeom_mt.c', reference='cubegeom_mt.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) # multitexture def test_cubegeom_color2(self): - self.btest('cubegeom_color2.c', reference='cubegeom_color2.png', args=['-s', 'LEGACY_GL_EMULATION=1'], also_proxied=True) + self.btest('cubegeom_color2.c', reference='cubegeom_color2.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL'], also_proxied=True) def test_cubegeom_texturematrix(self): - self.btest('cubegeom_texturematrix.c', reference='cubegeom_texturematrix.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_texturematrix.c', reference='cubegeom_texturematrix.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_fog(self): - self.btest('cubegeom_fog.c', reference='cubegeom_fog.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_fog.c', reference='cubegeom_fog.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_pre_vao(self): - self.btest('cubegeom_pre_vao.c', reference='cubegeom_pre_vao.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_pre_vao.c', reference='cubegeom_pre_vao.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_pre2_vao(self): - self.btest('cubegeom_pre2_vao.c', reference='cubegeom_pre_vao.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_pre2_vao.c', reference='cubegeom_pre_vao.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_pre2_vao2(self): - self.btest('cubegeom_pre2_vao2.c', reference='cubegeom_pre2_vao2.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('cubegeom_pre2_vao2.c', reference='cubegeom_pre2_vao2.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_cubegeom_u4fv_2(self): - self.btest('cubegeom_u4fv_2.c', reference='cubegeom_u4fv_2.png', args=['-s', 'LEGACY_GL_EMULATION=1']) - self.btest('cubegeom_u4fv_2.c', reference='cubegeom_u4fv_2.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-s', 'SPLIT_MEMORY=16777216']) # check for uniform4fv slice being valid in split memory + self.btest('cubegeom_u4fv_2.c', reference='cubegeom_u4fv_2.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) + self.btest('cubegeom_u4fv_2.c', reference='cubegeom_u4fv_2.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL', '-s', 'SPLIT_MEMORY=16777216']) # check for uniform4fv slice being valid in split memory def test_cube_explosion(self): - self.btest('cube_explosion.c', reference='cube_explosion.png', args=['-s', 'LEGACY_GL_EMULATION=1'], also_proxied=True) + self.btest('cube_explosion.c', reference='cube_explosion.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL'], also_proxied=True) def test_glgettexenv(self): - self.btest('glgettexenv.c', args=['-s', 'LEGACY_GL_EMULATION=1'], expected=['1']) + self.btest('glgettexenv.c', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL'], expected=['1']) def test_sdl_canvas_blank(self): - self.btest('sdl_canvas_blank.c', reference='sdl_canvas_blank.png') + self.btest('sdl_canvas_blank.c', args=['-lSDL', '-lGL'], reference='sdl_canvas_blank.png') def test_sdl_canvas_palette(self): - self.btest('sdl_canvas_palette.c', reference='sdl_canvas_palette.png') + self.btest('sdl_canvas_palette.c', args=['-lSDL', '-lGL'], reference='sdl_canvas_palette.png') def test_sdl_canvas_twice(self): - self.btest('sdl_canvas_twice.c', reference='sdl_canvas_twice.png') + self.btest('sdl_canvas_twice.c', args=['-lSDL', '-lGL'], reference='sdl_canvas_twice.png') def test_sdl_set_clip_rect(self): - self.btest('sdl_set_clip_rect.c', reference='sdl_set_clip_rect.png') + self.btest('sdl_set_clip_rect.c', args=['-lSDL', '-lGL'], reference='sdl_set_clip_rect.png') def test_sdl_maprgba(self): - self.btest('sdl_maprgba.c', reference='sdl_maprgba.png', reference_slack=3) + self.btest('sdl_maprgba.c', args=['-lSDL', '-lGL'], reference='sdl_maprgba.png', reference_slack=3) def test_sdl_create_rgb_surface_from(self): - self.btest('sdl_create_rgb_surface_from.c', reference='sdl_create_rgb_surface_from.png') + self.btest('sdl_create_rgb_surface_from.c', args=['-lSDL', '-lGL'], reference='sdl_create_rgb_surface_from.png') def test_sdl_rotozoom(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'screenshot.png', '--use-preload-plugins'], reference_slack=3) + self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'screenshot.png', '--use-preload-plugins', '-lSDL', '-lGL'], reference_slack=3) def test_sdl_gfx_primitives(self): - self.btest('sdl_gfx_primitives.c', reference='sdl_gfx_primitives.png', reference_slack=1) + self.btest('sdl_gfx_primitives.c', args=['-lSDL', '-lGL'], reference='sdl_gfx_primitives.png', reference_slack=1) def test_sdl_canvas_palette_2(self): open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' @@ -1772,30 +1772,30 @@ def test_sdl_canvas_palette_2(self): Module['arguments'] = ['-b']; ''') - self.btest('sdl_canvas_palette_2.c', reference='sdl_canvas_palette_r.png', args=['--pre-js', 'pre.js', '--pre-js', 'args-r.js']) - self.btest('sdl_canvas_palette_2.c', reference='sdl_canvas_palette_g.png', args=['--pre-js', 'pre.js', '--pre-js', 'args-g.js']) - self.btest('sdl_canvas_palette_2.c', reference='sdl_canvas_palette_b.png', args=['--pre-js', 'pre.js', '--pre-js', 'args-b.js']) + self.btest('sdl_canvas_palette_2.c', reference='sdl_canvas_palette_r.png', args=['--pre-js', 'pre.js', '--pre-js', 'args-r.js', '-lSDL', '-lGL']) + self.btest('sdl_canvas_palette_2.c', reference='sdl_canvas_palette_g.png', args=['--pre-js', 'pre.js', '--pre-js', 'args-g.js', '-lSDL', '-lGL']) + self.btest('sdl_canvas_palette_2.c', reference='sdl_canvas_palette_b.png', args=['--pre-js', 'pre.js', '--pre-js', 'args-b.js', '-lSDL', '-lGL']) def test_sdl_alloctext(self): - self.btest('sdl_alloctext.c', expected='1', args=['-O2', '-s', 'TOTAL_MEMORY=' + str(1024*1024*8)]) + self.btest('sdl_alloctext.c', expected='1', args=['-O2', '-s', 'TOTAL_MEMORY=' + str(1024*1024*8), '-lSDL', '-lGL']) def test_sdl_surface_refcount(self): - self.btest('sdl_surface_refcount.c', expected='1') + self.btest('sdl_surface_refcount.c', args=['-lSDL'], expected='1') def test_sdl_free_screen(self): - self.btest('sdl_free_screen.cpp', reference='htmltest.png') + self.btest('sdl_free_screen.cpp', args=['-lSDL', '-lGL'], reference='htmltest.png') def test_glbegin_points(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('glbegin_points.c', reference='glbegin_points.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '--use-preload-plugins']) + self.btest('glbegin_points.c', reference='glbegin_points.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL', '--use-preload-plugins']) def test_s3tc(self): shutil.copyfile(path_from_root('tests', 'screenshot.dds'), os.path.join(self.get_dir(), 'screenshot.dds')) - self.btest('s3tc.c', reference='s3tc.png', args=['--preload-file', 'screenshot.dds', '-s', 'LEGACY_GL_EMULATION=1']) + self.btest('s3tc.c', reference='s3tc.png', args=['--preload-file', 'screenshot.dds', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_s3tc_ffp_only(self): shutil.copyfile(path_from_root('tests', 'screenshot.dds'), os.path.join(self.get_dir(), 'screenshot.dds')) - self.btest('s3tc.c', reference='s3tc.png', args=['--preload-file', 'screenshot.dds', '-s', 'LEGACY_GL_EMULATION=1', '-s', 'GL_FFP_ONLY=1']) + self.btest('s3tc.c', reference='s3tc.png', args=['--preload-file', 'screenshot.dds', '-s', 'LEGACY_GL_EMULATION=1', '-s', 'GL_FFP_ONLY=1', '-lGL', '-lSDL']) def test_s3tc_crunch(self): try: @@ -1813,7 +1813,7 @@ def test(args): shutil.move('ship.dds', 'ship.donotfindme.dds') # make sure we load from the compressed shutil.move('bloom.dds', 'bloom.donotfindme.dds') # make sure we load from the compressed shutil.move('water.dds', 'water.donotfindme.dds') # make sure we load from the compressed - self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', reference_slack=11, args=['--pre-js', 'pre.js', '-s', 'LEGACY_GL_EMULATION=1']) + self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', reference_slack=11, args=['--pre-js', 'pre.js', '-s', 'LEGACY_GL_EMULATION=1', '-lGL']) test([]) test(['text.txt']) # also package a non-crunch file @@ -1830,30 +1830,30 @@ def test_s3tc_crunch_split(self): # load several datafiles/outputs of file packa shutil.move('ship.dds', 'ship.donotfindme.dds') # make sure we load from the compressed shutil.move('bloom.dds', 'bloom.donotfindme.dds') # make sure we load from the compressed shutil.move('water.dds', 'water.donotfindme.dds') # make sure we load from the compressed - self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', reference_slack=11, args=['--pre-js', 'asset_a.js', '--pre-js', 'asset_b.js', '-s', 'LEGACY_GL_EMULATION=1']) + self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', reference_slack=11, args=['--pre-js', 'asset_a.js', '--pre-js', 'asset_b.js', '-s', 'LEGACY_GL_EMULATION=1', '-lGL']) def test_aniso(self): if SPIDERMONKEY_ENGINE in JS_ENGINES: # asm.js-ification check - Popen([PYTHON, EMCC, path_from_root('tests', 'aniso.c'), '-O2', '-g2', '-s', 'LEGACY_GL_EMULATION=1']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'aniso.c'), '-O2', '-g2', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL', '-Wno-incompatible-pointer-types']).communicate() Settings.ASM_JS = 1 self.run_generated_code(SPIDERMONKEY_ENGINE, 'a.out.js', assert_returncode=None) print 'passed asm test' shutil.copyfile(path_from_root('tests', 'water.dds'), 'water.dds') - self.btest('aniso.c', reference='aniso.png', reference_slack=2, args=['--preload-file', 'water.dds', '-s', 'LEGACY_GL_EMULATION=1']) + self.btest('aniso.c', reference='aniso.png', reference_slack=2, args=['--preload-file', 'water.dds', '-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL', '-Wno-incompatible-pointer-types']) def test_tex_nonbyte(self): - self.btest('tex_nonbyte.c', reference='tex_nonbyte.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('tex_nonbyte.c', reference='tex_nonbyte.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_float_tex(self): - self.btest('float_tex.cpp', reference='float_tex.png') + self.btest('float_tex.cpp', reference='float_tex.png', args=['-lGL', '-lglut']) def test_subdata(self): - self.btest('gl_subdata.cpp', reference='float_tex.png') + self.btest('gl_subdata.cpp', reference='float_tex.png', args=['-lGL', '-lglut']) def test_perspective(self): - self.btest('perspective.c', reference='perspective.png', args=['-s', 'LEGACY_GL_EMULATION=1']) + self.btest('perspective.c', reference='perspective.png', args=['-s', 'LEGACY_GL_EMULATION=1', '-lGL', '-lSDL']) def test_runtimelink(self): main, supp = self.setup_runtimelink_test() @@ -2102,7 +2102,7 @@ def test_emrun(self): # This does not actually verify anything except that --cpuprofiler and --memoryprofiler compiles. # Run interactive.test_cpuprofiler_memoryprofiler for interactive testing. def test_cpuprofiler_memoryprofiler(self): - self.btest('hello_world_gles.c', expected='0', args=['-DLONGTEST=1', '-DTEST_MEMORYPROFILER_ALLOCATIONS_MAP=1', '-O2', '--cpuprofiler', '--memoryprofiler'], timeout=30) + self.btest('hello_world_gles.c', expected='0', args=['-DLONGTEST=1', '-DTEST_MEMORYPROFILER_ALLOCATIONS_MAP=1', '-O2', '--cpuprofiler', '--memoryprofiler', '-lGL', '-lglut'], timeout=30) def test_uuid(self): # Run with ./runner.py browser.test_uuid @@ -2111,7 +2111,7 @@ def test_uuid(self): # First run tests in Node and/or SPIDERMONKEY using run_js. Use closure compiler so we can check that # require('crypto').randomBytes and window.crypto.getRandomValues doesn't get minified out. - Popen([PYTHON, EMCC, '-O2', '--closure', '1', path_from_root('tests', 'uuid', 'test.c'), '-o', 'test.js'], stdout=PIPE, stderr=PIPE).communicate() + Popen([PYTHON, EMCC, '-O2', '--closure', '1', path_from_root('tests', 'uuid', 'test.c'), '-o', 'test.js', '-luuid'], stdout=PIPE, stderr=PIPE).communicate() test_js_closure = open('test.js').read() @@ -2127,13 +2127,13 @@ def test_uuid(self): try_delete(path_from_root('tests', 'uuid', 'test.js.map')) # Now run test in browser - self.btest(path_from_root('tests', 'uuid', 'test.c'), '1') + self.btest(path_from_root('tests', 'uuid', 'test.c'), '1', args=['-luuid']) def test_glew(self): - self.btest(path_from_root('tests', 'glew.c'), expected='1') - self.btest(path_from_root('tests', 'glew.c'), args=['-s', 'LEGACY_GL_EMULATION=1'], expected='1') - self.btest(path_from_root('tests', 'glew.c'), args=['-DGLEW_MX'], expected='1') - self.btest(path_from_root('tests', 'glew.c'), args=['-s', 'LEGACY_GL_EMULATION=1', '-DGLEW_MX'], expected='1') + self.btest(path_from_root('tests', 'glew.c'), args=['-lGL', '-lSDL', '-lGLEW'], expected='1') + self.btest(path_from_root('tests', 'glew.c'), args=['-lGL', '-lSDL', '-lGLEW', '-s', 'LEGACY_GL_EMULATION=1'], expected='1') + self.btest(path_from_root('tests', 'glew.c'), args=['-lGL', '-lSDL', '-lGLEW', '-DGLEW_MX'], expected='1') + self.btest(path_from_root('tests', 'glew.c'), args=['-lGL', '-lSDL', '-lGLEW', '-s', 'LEGACY_GL_EMULATION=1', '-DGLEW_MX'], expected='1') def test_doublestart_bug(self): open('pre.js', 'w').write(r''' @@ -2155,39 +2155,39 @@ def test_html5(self): def test_html5_webgl_create_context(self): for opts in [[], ['-O2', '-g1', '--closure', '1'], ['-s', 'FULL_ES2=1']]: print opts - self.btest(path_from_root('tests', 'webgl_create_context.cpp'), args=opts, expected='0', timeout=20) + self.btest(path_from_root('tests', 'webgl_create_context.cpp'), args=opts + ['-lGL'], expected='0', timeout=20) # Verify bug https://github.com/kripken/emscripten/issues/4556: creating a WebGL context to Module.canvas without an ID explicitly assigned to it. def test_html5_webgl_create_context2(self): - self.btest(path_from_root('tests', 'webgl_create_context2.cpp'), args=['--shell-file', path_from_root('tests', 'webgl_create_context2_shell.html')], expected='0', timeout=20) + self.btest(path_from_root('tests', 'webgl_create_context2.cpp'), args=['--shell-file', path_from_root('tests', 'webgl_create_context2_shell.html'), '-lGL'], expected='0', timeout=20) def test_html5_webgl_destroy_context(self): for opts in [[], ['-O2', '-g1'], ['-s', 'FULL_ES2=1']]: print opts - self.btest(path_from_root('tests', 'webgl_destroy_context.cpp'), args=opts + ['--shell-file', path_from_root('tests/webgl_destroy_context_shell.html'), '-s', 'NO_EXIT_RUNTIME=1'], expected='0', timeout=20) + self.btest(path_from_root('tests', 'webgl_destroy_context.cpp'), args=opts + ['--shell-file', path_from_root('tests/webgl_destroy_context_shell.html'), '-s', 'NO_EXIT_RUNTIME=1', '-lGL'], expected='0', timeout=20) def test_webgl_context_params(self): if WINDOWS: return self.skip('SKIPPED due to bug https://bugzilla.mozilla.org/show_bug.cgi?id=1310005 - WebGL implementation advertises implementation defined GL_IMPLEMENTATION_COLOR_READ_TYPE/FORMAT pair that it cannot read with') - self.btest(path_from_root('tests', 'webgl_color_buffer_readpixels.cpp'), expected='0', timeout=20) + self.btest(path_from_root('tests', 'webgl_color_buffer_readpixels.cpp'), args=['-lGL'], expected='0', timeout=20) def test_webgl2(self): for opts in [[], ['-O2', '-g1', '--closure', '1'], ['-s', 'FULL_ES2=1']]: print opts - self.btest(path_from_root('tests', 'webgl2.cpp'), args=['-s', 'USE_WEBGL2=1'] + opts, expected='0') + self.btest(path_from_root('tests', 'webgl2.cpp'), args=['-s', 'USE_WEBGL2=1', '-lGL'] + opts, expected='0') def test_webgl2_objects(self): - self.btest(path_from_root('tests', 'webgl2_objects.cpp'), args=['-s', 'USE_WEBGL2=1'], expected='0') + self.btest(path_from_root('tests', 'webgl2_objects.cpp'), args=['-s', 'USE_WEBGL2=1', '-lGL'], expected='0') def test_webgl2_ubos(self): - self.btest(path_from_root('tests', 'webgl2_ubos.cpp'), args=['-s', 'USE_WEBGL2=1'], expected='0') + self.btest(path_from_root('tests', 'webgl2_ubos.cpp'), args=['-s', 'USE_WEBGL2=1', '-lGL'], expected='0') def test_webgl_with_closure(self): - self.btest(path_from_root('tests', 'webgl_with_closure.cpp'), args=['-O2', '-s', 'USE_WEBGL2=1', '--closure', '1'], expected='0') + self.btest(path_from_root('tests', 'webgl_with_closure.cpp'), args=['-O2', '-s', 'USE_WEBGL2=1', '--closure', '1', '-lGL'], expected='0') def test_sdl_touch(self): for opts in [[], ['-O2', '-g1', '--closure', '1']]: print opts - self.btest(path_from_root('tests', 'sdl_touch.c'), args=opts + ['-DAUTOMATE_SUCCESS=1'], expected='0') + self.btest(path_from_root('tests', 'sdl_touch.c'), args=opts + ['-DAUTOMATE_SUCCESS=1', '-lSDL', '-lGL'], expected='0') def test_html5_mouse(self): for opts in [[], ['-O2', '-g1', '--closure', '1']]: @@ -2197,7 +2197,7 @@ def test_html5_mouse(self): def test_sdl_mousewheel(self): for opts in [[], ['-O2', '-g1', '--closure', '1']]: print opts - self.btest(path_from_root('tests', 'test_sdl_mousewheel.c'), args=opts + ['-DAUTOMATE_SUCCESS=1'], expected='0') + self.btest(path_from_root('tests', 'test_sdl_mousewheel.c'), args=opts + ['-DAUTOMATE_SUCCESS=1', '-lSDL', '-lGL'], expected='0') def test_codemods(self): for opt_level in [0, 2]: @@ -2313,11 +2313,11 @@ def in_html(expected, args=[]): in_html('200', ['-s', 'FORCE_FILESYSTEM=1']) def test_glfw3(self): - self.btest(path_from_root('tests', 'glfw3.c'), args=['-s', 'LEGACY_GL_EMULATION=1', '-s', 'USE_GLFW=3'], expected='1') + self.btest(path_from_root('tests', 'glfw3.c'), args=['-s', 'LEGACY_GL_EMULATION=1', '-s', 'USE_GLFW=3', '-lglfw', '-lGL'], expected='1') def test_glfw_events(self): - self.btest(path_from_root('tests', 'glfw_events.c'), args=['-s', 'USE_GLFW=2', "-DUSE_GLFW=2"], expected='1') - self.btest(path_from_root('tests', 'glfw_events.c'), args=['-s', 'USE_GLFW=3', "-DUSE_GLFW=3"], expected='1') + self.btest(path_from_root('tests', 'glfw_events.c'), args=['-s', 'USE_GLFW=2', "-DUSE_GLFW=2", '-lglfw', '-lGL'], expected='1') + self.btest(path_from_root('tests', 'glfw_events.c'), args=['-s', 'USE_GLFW=3', "-DUSE_GLFW=3", '-lglfw', '-lGL'], expected='1') def test_asm_swapping(self): self.clear() @@ -2747,7 +2747,7 @@ def test_emterpreter_async_sleep2_safeheap(self): self.btest('emterpreter_async_sleep2_safeheap.cpp', '17', args=['-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-Oz', '-profiling', '-s', 'SAFE_HEAP=1', '-s', 'ASSERTIONS=1', '-s', 'EMTERPRETIFY_WHITELIST=["_main","_callback","_fix"]']) def test_sdl_audio_beep_sleep(self): - self.btest('sdl_audio_beep_sleep.cpp', '1', args=['-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-Os', '-s', 'ASSERTIONS=1', '-s', 'DISABLE_EXCEPTION_CATCHING=0', '-profiling', '-s', 'SAFE_HEAP=1'], timeout=60) + self.btest('sdl_audio_beep_sleep.cpp', '1', args=['-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-Os', '-s', 'ASSERTIONS=1', '-s', 'DISABLE_EXCEPTION_CATCHING=0', '-profiling', '-s', 'SAFE_HEAP=1', '-lSDL'], timeout=60) def test_mainloop_reschedule(self): self.btest('mainloop_reschedule.cpp', '1', args=['-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-Os'], timeout=30) @@ -2905,9 +2905,9 @@ def test_dynamic_link_glemu(self): return (const char *)glGetString(GL_EXTENSIONS); } ''') - Popen([PYTHON, EMCC, 'side.cpp', '-s', 'SIDE_MODULE=1', '-O2', '-o', 'side.js']).communicate() + Popen([PYTHON, EMCC, 'side.cpp', '-s', 'SIDE_MODULE=1', '-O2', '-o', 'side.js', '-lSDL']).communicate() - self.btest(self.in_dir('main.cpp'), '1', args=['-s', 'MAIN_MODULE=1', '-O2', '-s', 'LEGACY_GL_EMULATION=1', '--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']) def test_memory_growth_during_startup(self): open('data.dat', 'w').write('X' * (30*1024*1024)) @@ -3276,11 +3276,11 @@ def test_utf16_textdecoder(self): def test_webgl_offscreen_canvas_in_pthread(self): for args in [[], ['-DTEST_CHAINED_WEBGL_CONTEXT_PASSING']]: - self.btest('gl_in_pthread.cpp', expected='1', args=args + ['-s', 'USE_PTHREADS=1', '-s', 'PTHREAD_POOL_SIZE=2', '-s', 'OFFSCREENCANVAS_SUPPORT=1']) + self.btest('gl_in_pthread.cpp', expected='1', args=args + ['-s', 'USE_PTHREADS=1', '-s', 'PTHREAD_POOL_SIZE=2', '-s', 'OFFSCREENCANVAS_SUPPORT=1', '-lGL']) def test_webgl_offscreen_canvas_in_mainthread_after_pthread(self): for args in [[], ['-DTEST_MAIN_THREAD_EXPLICIT_COMMIT']]: - self.btest('gl_in_mainthread_after_pthread.cpp', expected='0', args=args+['-s', 'USE_PTHREADS=1', '-s', 'PTHREAD_POOL_SIZE=2', '-s', 'OFFSCREENCANVAS_SUPPORT=1']) + self.btest('gl_in_mainthread_after_pthread.cpp', expected='0', args=args+['-s', 'USE_PTHREADS=1', '-s', 'PTHREAD_POOL_SIZE=2', '-s', 'OFFSCREENCANVAS_SUPPORT=1', '-lGL']) # Tests the feature that shell html page can preallocate the typed array and place it to Module.buffer before loading the script page. # In this build mode, the -s TOTAL_MEMORY=xxx option will be ignored. diff --git a/tools/shared.py b/tools/shared.py index dcacdb1e6c426..84784a3efd7b3 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -474,7 +474,12 @@ def get_emscripten_version(path): # Returns true if Emscripten is running in 'strict' mode, in which deprecated compiler features are not supported. def is_emscripten_strict(): - return (os.environ.get('EMCC_STRICT') and int(os.environ.get('EMCC_STRICT')) != 0) or Settings.STRICT + if os.environ.get('EMCC_STRICT') and int(os.environ.get('EMCC_STRICT')) != 0: return True + try: + return Settings.STRICT + except: + pass + return False # Check that basic stuff we need (a JS engine to compile, Node.js, and Clang and LLVM) # exists. From 1b4e784c7bef6e07a5a521451299c04ee6753b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Sat, 19 Nov 2016 20:19:42 +0200 Subject: [PATCH 10/18] Move the deduction of which system JS libraries to link to class Building in tools/shared.py. --- emcc.py | 37 +------------------------------------ tools/shared.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 36 deletions(-) diff --git a/emcc.py b/emcc.py index 1f031e809cc9f..240c4ae5c98bb 100755 --- a/emcc.py +++ b/emcc.py @@ -940,42 +940,7 @@ def detect_fixed_language_mode(args): if found: break if found: break if not found: - # Some native libraries are implemented in Emscripten as system side JS libraries - js_system_libraries = { - 'c': '', - 'EGL': 'library_egl.js', - 'GL': 'library_gl.js', - 'GLESv2': 'library_gl.js', - 'GLEW': 'library_glew.js', - 'glfw': 'library_glfw.js', - 'glfw3': 'library_glfw.js', - 'GLU': '', - 'glut': 'library_glut.js', - 'm': '', - 'openal': 'library_openal.js', - 'pthread': '', - 'X11': 'library_xlib.js', - 'SDL': 'library_sdl.js', - 'stdc++': '', - 'uuid': 'library_uuid.js' - } - if lib in js_system_libraries: - if len(js_system_libraries[lib]) > 0: - system_js_libraries += [js_system_libraries[lib]] - - # TODO: This is unintentional due to historical reasons. Improve EGL to use HTML5 API to avoid depending on GLUT. - if lib == 'EGL': system_js_libraries += ['library_glut.js'] - - elif lib.endswith('.js') and os.path.isfile(shared.path_from_root('src', 'library_' + lib)): - system_js_libraries += ['library_' + lib] - else: - emscripten_strict_mode = shared.is_emscripten_strict() or 'STRICT=1' in settings_changes - error_on_missing_libraries = (emscripten_strict_mode and not 'ERROR_ON_MISSING_LIBRARIES=0' in settings_changes) or 'ERROR_ON_MISSING_LIBRARIES=1' in settings_changes - if error_on_missing_libraries: - logging.fatal('emcc: cannot find library "%s"', lib) - exit(1) - else: - logging.warning('emcc: cannot find library "%s"', lib) + system_js_libraries += shared.Building.path_to_system_js_libraries(lib) # Certain linker flags imply some link libraries to be pulled in by default. if 'EMTERPRETIFY_ASYNC=1' in settings_changes: system_js_libraries += ['library_async.js'] diff --git a/tools/shared.py b/tools/shared.py index 84784a3efd7b3..357c3efc0c8b3 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1999,6 +1999,50 @@ def ensure_struct_info(info_path): import gen_struct_info gen_struct_info.main(['-qo', info_path, path_from_root('src/struct_info.json')]) + @staticmethod + # Given the name of a special Emscripten-implemented system library, returns an array of absolute paths to JS library + # files inside emscripten/src/ that corresponds to the library name. + def path_to_system_js_libraries(library_name): + # Some native libraries are implemented in Emscripten as system side JS libraries + js_system_libraries = { + 'c': '', + 'EGL': 'library_egl.js', + 'GL': 'library_gl.js', + 'GLESv2': 'library_gl.js', + 'GLEW': 'library_glew.js', + 'glfw': 'library_glfw.js', + 'glfw3': 'library_glfw.js', + 'GLU': '', + 'glut': 'library_glut.js', + 'm': '', + 'openal': 'library_openal.js', + 'pthread': '', + 'X11': 'library_xlib.js', + 'SDL': 'library_sdl.js', + 'stdc++': '', + 'uuid': 'library_uuid.js' + } + library_files = [] + if library_name in js_system_libraries: + if len(js_system_libraries[library_name]) > 0: + library_files += [js_system_libraries[library_name]] + + # TODO: This is unintentional due to historical reasons. Improve EGL to use HTML5 API to avoid depending on GLUT. + if library_name == 'EGL': library_files += ['library_glut.js'] + + elif library_name.endswith('.js') and os.path.isfile(shared.path_from_root('src', 'library_' + library_name)): + library_files += ['library_' + library_name] + else: + emscripten_strict_mode = shared.is_emscripten_strict() or 'STRICT=1' in settings_changes + error_on_missing_libraries = (emscripten_strict_mode and not 'ERROR_ON_MISSING_LIBRARIES=0' in settings_changes) or 'ERROR_ON_MISSING_LIBRARIES=1' in settings_changes + if error_on_missing_libraries: + logging.fatal('emcc: cannot find library "%s"', library_name) + exit(1) + else: + logging.warning('emcc: cannot find library "%s"', library_name) + + return library_files + # compatibility with existing emcc, etc. scripts Cache = cache.Cache(debug=DEBUG_CACHE) chunkify = cache.chunkify From 11e463473f7541967539a5640edcafe23eeaef4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 22 Nov 2016 04:06:24 +0200 Subject: [PATCH 11/18] Apply the set of system JS libraries based on the link settings via a code path in shared.Building. --- emcc.py | 7 ++----- tools/shared.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/emcc.py b/emcc.py index 240c4ae5c98bb..fe8a824c50453 100755 --- a/emcc.py +++ b/emcc.py @@ -943,11 +943,8 @@ def detect_fixed_language_mode(args): system_js_libraries += shared.Building.path_to_system_js_libraries(lib) # Certain linker flags imply some link libraries to be pulled in by default. - if 'EMTERPRETIFY_ASYNC=1' in settings_changes: system_js_libraries += ['library_async.js'] - if 'ASYNCIFY=1' in settings_changes: system_js_libraries += ['library_async.js'] - if 'LZ4=1' in settings_changes: system_js_libraries += ['library_lz4.js'] - if 'USE_SDL=1' in settings_changes: system_js_libraries += ['library_sdl.js'] - if 'USE_SDL=2' in settings_changes: system_js_libraries += ['library_egl.js', 'library_glut.js', 'library_gl.js'] + system_js_libraries += shared.Building.path_to_system_js_libraries_for_settings(settings_changes) + settings_changes.append('SYSTEM_JS_LIBRARIES="' + ','.join(system_js_libraries) + '"') # If not compiling to JS, then we are compiling to an intermediate bitcode objects or library, so diff --git a/tools/shared.py b/tools/shared.py index 357c3efc0c8b3..0ea72f217341c 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -2043,6 +2043,18 @@ def path_to_system_js_libraries(library_name): return library_files + @staticmethod + # Given a list of Emscripten link settings, returns a list of paths to system JS libraries + # that should get linked automatically in to the build when those link settings are present. + def path_to_system_js_libraries_for_settings(link_settings): + system_js_libraries =[] + if 'EMTERPRETIFY_ASYNC=1' in link_settings: system_js_libraries += ['library_async.js'] + if 'ASYNCIFY=1' in link_settings: system_js_libraries += ['library_async.js'] + if 'LZ4=1' in link_settings: system_js_libraries += ['library_lz4.js'] + if 'USE_SDL=1' in link_settings: system_js_libraries += ['library_sdl.js'] + if 'USE_SDL=2' in link_settings: system_js_libraries += ['library_egl.js', 'library_glut.js', 'library_gl.js'] + return system_js_libraries + # compatibility with existing emcc, etc. scripts Cache = cache.Cache(debug=DEBUG_CACHE) chunkify = cache.chunkify From 12d47b086d139fbd7c5b21e1c30522e63366e3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 22 Nov 2016 04:07:44 +0200 Subject: [PATCH 12/18] Indentation fix in src/library_fs.js --- src/library_fs.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/library_fs.js b/src/library_fs.js index e581d93354fad..3aa3214485716 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -1,15 +1,15 @@ mergeInto(LibraryManager.library, { $FS__deps: ['$ERRNO_CODES', '$ERRNO_MESSAGES', '__setErrNo', '$PATH', '$TTY', '$MEMFS', #if __EMSCRIPTEN_HAS_idbfs_js__ - '$IDBFS', + '$IDBFS', #endif #if __EMSCRIPTEN_HAS_nodefs_js__ - '$NODEFS', + '$NODEFS', #endif #if __EMSCRIPTEN_HAS_workerfs_js__ - '$WORKERFS', + '$WORKERFS', #endif - 'stdin', 'stdout', 'stderr'], + 'stdin', 'stdout', 'stderr'], $FS__postset: 'FS.staticInit();' + '__ATINIT__.unshift(function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() });' + '__ATMAIN__.push(function() { FS.ignorePermissions = false });' + From 815a35bd149bd8c7d575cc9b97e0a57c54490bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 22 Nov 2016 05:11:30 +0200 Subject: [PATCH 13/18] Revise how EMCC_STRICT and -s STRICT=1 are read so that they are always visible. --- emcc.py | 28 +++++++++++++++++++++++++++- tests/test_other.py | 21 +++++++++++++++++++++ tools/shared.py | 28 +--------------------------- 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/emcc.py b/emcc.py index fe8a824c50453..3a722c92f4f4a 100755 --- a/emcc.py +++ b/emcc.py @@ -253,7 +253,8 @@ def filter_emscripten_options(argv): if not use_js: cmd += shared.EMSDK_OPTS + ['-D__EMSCRIPTEN__'] # The preprocessor define EMSCRIPTEN is deprecated. Don't pass it to code in strict mode. Code should use the define __EMSCRIPTEN__ instead. - if not shared.is_emscripten_strict(): cmd += ['-DEMSCRIPTEN'] + if not shared.Settings.STRICT: + cmd += ['-DEMSCRIPTEN'] if use_js: cmd += ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'] # configure tests should fail when an undefined symbol exists logging.debug('just configuring: ' + ' '.join(cmd)) @@ -921,6 +922,22 @@ def detect_fixed_language_mode(args): if separate_asm: shared.Settings.SEPARATE_ASM = os.path.basename(asm_target) + if 'EMCC_STRICT' in os.environ: + shared.Settings.STRICT = int(os.environ.get('EMCC_STRICT')) + + STRICT = ([None] + filter(lambda x: x.startswith('STRICT='), settings_changes))[-1] + if STRICT: + shared.Settings.STRICT = int(STRICT[len('STRICT='):]) + + if shared.Settings.STRICT: + shared.Settings.ERROR_ON_UNDEFINED_SYMBOLS = 1 + shared.Settings.ERROR_ON_MISSING_LIBRARIES = 1 + + # Libraries are searched before settings_changes are applied, so pull its value from the command line already here. + ERROR_ON_MISSING_LIBRARIES = ([None] + filter(lambda x: x.startswith('ERROR_ON_MISSING_LIBRARIES='), settings_changes))[-1] + if ERROR_ON_MISSING_LIBRARIES: + shared.Settings.ERROR_ON_MISSING_LIBRARIES = int(ERROR_ON_MISSING_LIBRARIES[len('ERROR_ON_MISSING_LIBRARIES='):]) + system_js_libraries = [] # Find library files @@ -1009,6 +1026,15 @@ def check(input_file): if shared.get_llvm_target() == shared.WASM_TARGET: shared.Settings.WASM_BACKEND = 1 + if not shared.Settings.STRICT: + # The preprocessor define EMSCRIPTEN is deprecated. Don't pass it to code in strict mode. Code should use the define __EMSCRIPTEN__ instead. + shared.COMPILER_OPTS += ['-DEMSCRIPTEN'] + + # The system include path system/include/emscripten/ is deprecated, i.e. instead of #include , one should pass in #include . + # This path is not available in Emscripten strict mode. + if shared.USE_EMSDK: + shared.C_INCLUDE_PATHS += [shared.path_from_root('system', 'include', 'emscripten')] + # Use settings try: diff --git a/tests/test_other.py b/tests/test_other.py index 1559a1d234746..269aaf1a13f53 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -7040,3 +7040,24 @@ def test_check_engine(self): except SystemExit as e: caught_exit = e.code self.assertEqual(1, caught_exit, 'Did not catch SystemExit with bogus JS engine') + + def test_error_on_missing_libraries(self): + env = os.environ.copy() + if 'EMCC_STRICT' in env: del env['EMCC_STRICT'] + + process = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-lsomenonexistingfile', '-s', 'STRICT=1'], stdout=PIPE, stderr=PIPE, env=env) + process.communicate() + assert process.returncode is not 0, '-llsomenonexistingfile is an error in strict mode' + + process = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-lsomenonexistingfile', '-s', 'ERROR_ON_MISSING_LIBRARIES=0'], stdout=PIPE, stderr=PIPE, env=env) + process.communicate() + assert process.returncode is 0, '-llsomenonexistingfile is not an error if -s ERROR_ON_MISSING_LIBRARIES=0 is passed' + + process = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-lsomenonexistingfile', '-s', 'STRICT=1', '-s', 'ERROR_ON_MISSING_LIBRARIES=0'], stdout=PIPE, stderr=PIPE, env=env) + process.communicate() + assert process.returncode is 0, '-s ERROR_ON_MISSING_LIBRARIES=0 should override -s STRICT=1' + + process = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-lsomenonexistingfile', '-s', 'STRICT=0'], stdout=PIPE, stderr=PIPE, env=env) + process.communicate() + # TODO: TEMPORARY: When -s ERROR_ON_MISSING_LIBRARIES=1 becomes the default, change the following line to expect failure instead of 0. + assert process.returncode is 0, '-llsomenonexistingfile is not yet an error in non-strict mode' diff --git a/tools/shared.py b/tools/shared.py index 0ea72f217341c..dea4cb92a61be 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -472,15 +472,6 @@ def find_temp_directory(): def get_emscripten_version(path): return open(path).read().strip().replace('"', '') -# Returns true if Emscripten is running in 'strict' mode, in which deprecated compiler features are not supported. -def is_emscripten_strict(): - if os.environ.get('EMCC_STRICT') and int(os.environ.get('EMCC_STRICT')) != 0: return True - try: - return Settings.STRICT - except: - pass - return False - # Check that basic stuff we need (a JS engine to compile, Node.js, and Clang and LLVM) # exists. # The test runner always does this check (through |force|). emcc does this less frequently, @@ -941,9 +932,6 @@ def get_llvm_target(): '-D__unix', '-D__unix__'] - # The preprocessor define EMSCRIPTEN is deprecated. Don't pass it to code in strict mode. Code should use the define __EMSCRIPTEN__ instead. - if not is_emscripten_strict(): COMPILER_OPTS += ['-DEMSCRIPTEN'] - # Changes to default clang behavior # Implicit functions can cause horribly confusing function pointer type errors, see #2175 @@ -967,11 +955,6 @@ def get_llvm_target(): path_from_root('system', 'local', 'include') ] - # The system include path system/include/emscripten/ is deprecated, i.e. instead of #include , one should pass in #include . - # This path is not available in Emscripten strict mode. - if not is_emscripten_strict(): - C_INCLUDE_PATHS += [path_from_root('system', 'include', 'emscripten')] - CXX_INCLUDE_PATHS = [ path_from_root('system', 'include', 'libcxx'), path_from_root('system', 'lib', 'libcxxabi', 'include') @@ -1111,13 +1094,6 @@ def load(self, args=[]): settings = re.sub(r'var ([\w\d]+)', r'self.attrs["\1"]', settings) exec settings - # Apply default values for settings that are configured from environment variables. - if is_emscripten_strict(): - # Specify default values for Emscripten strict mode. - self.attrs['STRICT'] = 1 - self.attrs['ERROR_ON_UNDEFINED_SYMBOLS'] = 1 - self.attrs['ERROR_ON_MISSING_LIBRARIES'] = 1 - # Apply additional settings. First -O, then -s for i in range(len(args)): if args[i].startswith('-O'): @@ -2033,9 +2009,7 @@ def path_to_system_js_libraries(library_name): elif library_name.endswith('.js') and os.path.isfile(shared.path_from_root('src', 'library_' + library_name)): library_files += ['library_' + library_name] else: - emscripten_strict_mode = shared.is_emscripten_strict() or 'STRICT=1' in settings_changes - error_on_missing_libraries = (emscripten_strict_mode and not 'ERROR_ON_MISSING_LIBRARIES=0' in settings_changes) or 'ERROR_ON_MISSING_LIBRARIES=1' in settings_changes - if error_on_missing_libraries: + if Settings.ERROR_ON_MISSING_LIBRARIES: logging.fatal('emcc: cannot find library "%s"', library_name) exit(1) else: From 022c4db2109c6cf581ce38fe3f432c634c055a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 22 Nov 2016 05:16:18 +0200 Subject: [PATCH 14/18] Add test for scenario when not explicitly linking to system JS libraries. --- tests/test_browser.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_browser.py b/tests/test_browser.py index 425831b0665f6..11e42c0b07110 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -61,6 +61,12 @@ def setUpClass(self): print 'Running the browser tests. Make sure the browser allows popups from localhost.' print + def test_sdl1_in_emscripten_nonstrict_mode(self): + if 'EMCC_STRICT' in os.environ and int(os.environ['EMCC_STRICT']): return self.skip('This test requires being run in non-strict mode (EMCC_STRICT env. variable unset)') + # TODO: This test is verifying behavior that will be deprecated at some point in the future, remove this test once + # system JS libraries are no longer automatically linked to anymore. + self.btest('hello_world_sdl.cpp', reference='htmltest.png') + def test_sdl1(self): self.btest('hello_world_sdl.cpp', reference='htmltest.png', args=['-lSDL', '-lGL']) self.btest('hello_world_sdl.cpp', reference='htmltest.png', args=['-s', 'USE_SDL=1', '-lGL']) # is the default anyhow From 08b70e5669995485bf0dbf57f10bfc70fd95dde1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 7 Dec 2016 03:01:22 +0200 Subject: [PATCH 15/18] Accept EMCC_STRICT=somethingotherthanzero as true for EMCC_STRICT --- emcc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emcc.py b/emcc.py index 3a722c92f4f4a..c12d4d71558d2 100755 --- a/emcc.py +++ b/emcc.py @@ -923,7 +923,7 @@ def detect_fixed_language_mode(args): shared.Settings.SEPARATE_ASM = os.path.basename(asm_target) if 'EMCC_STRICT' in os.environ: - shared.Settings.STRICT = int(os.environ.get('EMCC_STRICT')) + shared.Settings.STRICT = os.environ.get('EMCC_STRICT') != '0' STRICT = ([None] + filter(lambda x: x.startswith('STRICT='), settings_changes))[-1] if STRICT: From 267c4eee72bb3e9f48c03f94981778e2bbd7e11e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 7 Dec 2016 08:12:17 +0200 Subject: [PATCH 16/18] Add export of JS lib ifdefs for all libs, even when not in strict mode. --- src/modules.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules.js b/src/modules.js index c9238c3cf3e76..7cfa7235c0971 100644 --- a/src/modules.js +++ b/src/modules.js @@ -147,17 +147,17 @@ var LibraryManager = { // If there are any explicitly specified system JS libraries to link to, add those to link. if (SYSTEM_JS_LIBRARIES) { - SYSTEM_JS_LIBRARIES = SYSTEM_JS_LIBRARIES.split(','); - // For each system JS library library_xxx.js, add a preprocessor token __EMSCRIPTEN_HAS_xxx_js__ so that code can conditionally dead code eliminate out - // if a particular feature is not being linked in. - for (var i = 0; i < SYSTEM_JS_LIBRARIES.length; ++i) { - global['__EMSCRIPTEN_HAS_' + SYSTEM_JS_LIBRARIES[i].replace('.', '_').replace('library_', '') + '__'] = 1 - } libraries = libraries.concat(SYSTEM_JS_LIBRARIES); } libraries = libraries.concat(additionalLibraries); + // For each JS library library_xxx.js, add a preprocessor token __EMSCRIPTEN_HAS_xxx_js__ so that code can conditionally dead code eliminate out + // if a particular feature is not being linked in. + for (var i = 0; i < libraries.length; ++i) { + global['__EMSCRIPTEN_HAS_' + libraries[i].replace('.', '_').replace('library_', '') + '__'] = 1 + } + if (BOOTSTRAPPING_STRUCT_INFO) libraries = ['library_bootstrap_structInfo.js', 'library_formatString.js']; if (ONLY_MY_CODE) { libraries = []; From 8455fba3aab3e2b3384f51352f2a17c61f006064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 7 Dec 2016 08:12:37 +0200 Subject: [PATCH 17/18] Fix typo in looking up path_from_root() --- tools/shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/shared.py b/tools/shared.py index dea4cb92a61be..5037efa35fc7a 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -2006,7 +2006,7 @@ def path_to_system_js_libraries(library_name): # TODO: This is unintentional due to historical reasons. Improve EGL to use HTML5 API to avoid depending on GLUT. if library_name == 'EGL': library_files += ['library_glut.js'] - elif library_name.endswith('.js') and os.path.isfile(shared.path_from_root('src', 'library_' + library_name)): + elif library_name.endswith('.js') and os.path.isfile(path_from_root('src', 'library_' + library_name)): library_files += ['library_' + library_name] else: if Settings.ERROR_ON_MISSING_LIBRARIES: From 9b727e8fff5748fea1a3ee175fcc4ef97de7ea3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Sat, 17 Dec 2016 12:36:04 +0200 Subject: [PATCH 18/18] Apply code review to Emscripten strict mode. --- emcc.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/emcc.py b/emcc.py index c12d4d71558d2..ac093036f94c2 100755 --- a/emcc.py +++ b/emcc.py @@ -925,18 +925,23 @@ def detect_fixed_language_mode(args): if 'EMCC_STRICT' in os.environ: shared.Settings.STRICT = os.environ.get('EMCC_STRICT') != '0' - STRICT = ([None] + filter(lambda x: x.startswith('STRICT='), settings_changes))[-1] - if STRICT: - shared.Settings.STRICT = int(STRICT[len('STRICT='):]) + # Libraries are searched before settings_changes are applied, so apply the value for STRICT and ERROR_ON_MISSING_LIBRARIES from + # command line already now. + + def get_last_setting_change(setting): + return ([None] + filter(lambda x: x.startswith(setting + '='), settings_changes))[-1] + + strict_cmdline = get_last_setting_change('STRICT') + if strict_cmdline: + shared.Settings.STRICT = int(strict_cmdline[len('STRICT='):]) if shared.Settings.STRICT: shared.Settings.ERROR_ON_UNDEFINED_SYMBOLS = 1 shared.Settings.ERROR_ON_MISSING_LIBRARIES = 1 - # Libraries are searched before settings_changes are applied, so pull its value from the command line already here. - ERROR_ON_MISSING_LIBRARIES = ([None] + filter(lambda x: x.startswith('ERROR_ON_MISSING_LIBRARIES='), settings_changes))[-1] - if ERROR_ON_MISSING_LIBRARIES: - shared.Settings.ERROR_ON_MISSING_LIBRARIES = int(ERROR_ON_MISSING_LIBRARIES[len('ERROR_ON_MISSING_LIBRARIES='):]) + error_on_missing_libraries_cmdline = get_last_setting_change('ERROR_ON_MISSING_LIBRARIES') + if error_on_missing_libraries_cmdline: + shared.Settings.ERROR_ON_MISSING_LIBRARIES = int(error_on_missing_libraries_cmdline[len('ERROR_ON_MISSING_LIBRARIES='):]) system_js_libraries = []