summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/Platform/Emscripten.cmake110
-rw-r--r--cmake/Platform/Emscripten_unix.cmake24
-rwxr-xr-xemcc29
-rwxr-xr-xemscripten.py16
-rw-r--r--src/intertyper.js4
-rw-r--r--src/jsifier.js9
-rw-r--r--src/library_browser.js10
-rw-r--r--src/library_sdl.js39
-rw-r--r--src/modules.js7
-rw-r--r--src/postamble.js14
-rw-r--r--src/preamble.js72
-rw-r--r--src/proxyClient.js74
-rw-r--r--src/proxyWorker.js143
-rw-r--r--src/runtime.js6
-rw-r--r--src/settings.js3
-rwxr-xr-xsystem/bin/sdl-config13
-rw-r--r--tests/cmake/target_html/CMakeLists.txt13
-rw-r--r--tests/cmake/target_js/CMakeLists.txt24
-rw-r--r--tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj108
-rw-r--r--tests/msvc10/tests_msvc10.sln197
-rwxr-xr-xtests/runner.py6
-rw-r--r--tests/sdl_canvas_proxy.c34
-rw-r--r--tests/sdl_canvas_proxy.pngbin0 -> 4488 bytes
-rw-r--r--tests/sdl_key_proxy.c63
-rw-r--r--tests/test_browser.py68
-rw-r--r--tests/test_core.py102
-rw-r--r--tests/test_other.py119
-rw-r--r--tests/utf32.cpp53
-rw-r--r--tools/js-optimizer.js18
-rw-r--r--tools/shared.py112
-rw-r--r--tools/test-js-optimizer-asm-outline1-output.js133
-rw-r--r--tools/test-js-optimizer-asm-outline1.js40
-rw-r--r--tools/test-js-optimizer-regs-output.js16
-rw-r--r--tools/test-js-optimizer-regs.js2
-rw-r--r--tools/validate_asmjs.py82
35 files changed, 1391 insertions, 372 deletions
diff --git a/cmake/Platform/Emscripten.cmake b/cmake/Platform/Emscripten.cmake
index aafd38a8..ec3f5383 100644
--- a/cmake/Platform/Emscripten.cmake
+++ b/cmake/Platform/Emscripten.cmake
@@ -1,48 +1,124 @@
# This file is a 'toolchain description file' for CMake.
-# It teaches CMake about the Emscripten compiler, so that CMake can generate Unix Makefiles
+# It teaches CMake about the Emscripten compiler, so that CMake can generate makefiles
# from CMakeLists.txt that invoke emcc.
# To use this toolchain file with CMake, invoke CMake with the following command line parameters
-# cmake -DEMSCRIPTEN=1
-# -DCMAKE_TOOLCHAIN_FILE=<EmscriptenRoot>/cmake/Platform/Emscripten.cmake
-# -DCMAKE_MODULE_PATH=<EmscriptenRoot>/cmake
+# cmake -DCMAKE_TOOLCHAIN_FILE=<EmscriptenRoot>/cmake/Platform/Emscripten.cmake
# -DCMAKE_BUILD_TYPE=<Debug|RelWithDebInfo|Release|MinSizeRel>
-# -G "Unix Makefiles"
+# -G "Unix Makefiles" (Linux and OSX)
+# -G "MinGW Makefiles" (Windows)
# <path/to/CMakeLists.txt> # Note, pass in here ONLY the path to the file, not the filename 'CMakeLists.txt' itself.
# After that, build the generated Makefile with the command 'make'. On Windows, you may download and use 'mingw32-make' instead.
-# the name of the target operating system
-set(CMAKE_SYSTEM_NAME Emscripten)
+# The following variable describes the target OS we are building to.
+# Ideally, this could be 'Emscripten', but as Emscripten mimics the Linux platform, setting this to Linux will allow more of existing software to build.
+# Be sure to run Emscripten test_openjpeg if planning to change this.
+set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
+set(CMAKE_CROSSCOMPILING TRUE)
+
+# Do a no-op access on the CMAKE_TOOLCHAIN_FILE variable so that CMake will not issue a warning on it being unused.
+if (CMAKE_TOOLCHAIN_FILE)
+endif()
+
+# Locate where the Emscripten compiler resides in relative to this toolchain file.
+if ("${EMSCRIPTEN_ROOT_PATH}" STREQUAL "")
+ get_filename_component(GUESS_EMSCRIPTEN_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../" ABSOLUTE)
+ if (EXISTS "${GUESS_EMSCRIPTEN_ROOT_PATH}/emranlib")
+ set(EMSCRIPTEN_ROOT_PATH "${GUESS_EMSCRIPTEN_ROOT_PATH}")
+ endif()
+endif()
+
+# If not found by above search, locate using the EMSCRIPTEN environment variable.
+if ("${EMSCRIPTEN_ROOT_PATH}" STREQUAL "")
+ set(EMSCRIPTEN_ROOT_PATH "$ENV{EMSCRIPTEN}")
+endif()
+
+# Abort if not found.
if ("${EMSCRIPTEN_ROOT_PATH}" STREQUAL "")
- set(CMAKE_FIND_ROOT_PATH "$ENV{EMSCRIPTEN}")
+ message(FATAL_ERROR "Could not locate the Emscripten compiler toolchain directory! Either set the EMSCRIPTEN environment variable, or pass -DEMSCRIPTEN_ROOT_PATH=xxx to CMake to explicitly specify the location of the compiler!")
+endif()
+
+# Normalize, convert Windows backslashes to forward slashes or CMake will crash.
+get_filename_component(EMSCRIPTEN_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}" ABSOLUTE)
+
+if ("${CMAKE_MODULE_PATH}" STREQUAL "")
+ set(CMAKE_MODULE_PATH "${EMSCRIPTEN_ROOT_PATH}/cmake")
+endif()
+
+set(CMAKE_FIND_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}/cmake")
+
+if (CMAKE_HOST_WIN32)
+ set(EMCC_SUFFIX ".bat")
else()
- set(CMAKE_FIND_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}")
+ set(EMCC_SUFFIX "")
endif()
# Specify the compilers to use for C and C++
if ("${CMAKE_C_COMPILER}" STREQUAL "")
- set(CMAKE_C_COMPILER "emcc.bat")
- set(CMAKE_CXX_COMPILER "em++.bat")
- set(CMAKE_AR "emar.bat")
- set(CMAKE_RANLIB "emranlib.bat")
+ set(CMAKE_C_COMPILER "${EMSCRIPTEN_ROOT_PATH}/emcc${EMCC_SUFFIX}")
+endif()
+if ("${CMAKE_CXX_COMPILER}" STREQUAL "")
+ set(CMAKE_CXX_COMPILER "${EMSCRIPTEN_ROOT_PATH}/em++${EMCC_SUFFIX}")
+endif()
+
+if ("${CMAKE_AR}" STREQUAL "")
+ set(CMAKE_AR "${EMSCRIPTEN_ROOT_PATH}/emar${EMCC_SUFFIX}")
endif()
+if ("${CMAKE_RANLIB}" STREQUAL "")
+ set(CMAKE_RANLIB "${EMSCRIPTEN_ROOT_PATH}/emranlib${EMCC_SUFFIX}")
+endif()
+
+# Don't do compiler autodetection, since we are cross-compiling.
+include(CMakeForceCompiler)
+CMAKE_FORCE_C_COMPILER("${CMAKE_C_COMPILER}" Clang)
+CMAKE_FORCE_CXX_COMPILER("${CMAKE_CXX_COMPILER}" Clang)
+
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+# We would prefer to specify a standard set of Clang+Emscripten-friendly common convention for suffix files, especially for CMake executable files,
+# but if these are adjusted, ${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake will fail, since it depends on being able to compile output files with predefined names.
+#SET(CMAKE_LINK_LIBRARY_SUFFIX "")
+#SET(CMAKE_STATIC_LIBRARY_PREFIX "")
+#SET(CMAKE_STATIC_LIBRARY_SUFFIX ".bc")
+#SET(CMAKE_SHARED_LIBRARY_PREFIX "")
+#SET(CMAKE_SHARED_LIBRARY_SUFFIX ".bc")
+#IF (NOT CMAKE_EXECUTABLE_SUFFIX)
+# SET(CMAKE_EXECUTABLE_SUFFIX ".js")
+#endif()
+#SET(CMAKE_FIND_LIBRARY_PREFIXES "")
+#SET(CMAKE_FIND_LIBRARY_SUFFIXES ".bc")
+
+SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1)
+SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
+SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1)
+SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1)
+
+set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "@")
+set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "@")
+
# Specify the program to use when building static libraries. Force Emscripten-related command line options to clang.
-set(CMAKE_CXX_ARCHIVE_CREATE "${CMAKE_CXX_COMPILER} -o <TARGET> -emit-llvm <LINK_FLAGS> <OBJECTS>")
-set(CMAKE_C_ARCHIVE_CREATE "${CMAKE_C_COMPILER} -o <TARGET> -emit-llvm <LINK_FLAGS> <OBJECTS>")
+set(CMAKE_CXX_ARCHIVE_CREATE "${CMAKE_CXX_COMPILER} ${CMAKE_START_TEMP_FILE} -o <TARGET> -emit-llvm <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
+set(CMAKE_C_ARCHIVE_CREATE "${CMAKE_C_COMPILER} ${CMAKE_START_TEMP_FILE} -o <TARGET> -emit-llvm <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
# Set a global EMSCRIPTEN variable that can be used in client CMakeLists.txt to detect when building using Emscripten.
# There seems to be some kind of bug with CMake, so you might need to define this manually on the command line with "-DEMSCRIPTEN=1".
set(EMSCRIPTEN 1)
+# We are cross-compiling, so unset the common CMake variables that represent the target platform. Leave UNIX define enabled, since Emscripten
+# mimics a Linux environment.
+SET(WIN32)
+SET(APPLE)
+
+set(CMAKE_C_SIZEOF_DATA_PTR 4)
+set(CMAKE_CXX_SIZEOF_DATA_PTR 4)
+
set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELEASE")
set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_MINSIZEREL")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELWITHDEBINFO")
@@ -59,3 +135,7 @@ set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-over
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "-O2" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_RELEASE")
set(CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "-O2" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL")
set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO")
+
+function(em_validate_asmjs_after_build target)
+ add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo Validating build output for asm.js... COMMAND "python" ARGS "${EMSCRIPTEN_ROOT_PATH}/tools/validate_asmjs.py" "$<TARGET_FILE:${target}>")
+endfunction()
diff --git a/cmake/Platform/Emscripten_unix.cmake b/cmake/Platform/Emscripten_unix.cmake
deleted file mode 100644
index 92a21fd1..00000000
--- a/cmake/Platform/Emscripten_unix.cmake
+++ /dev/null
@@ -1,24 +0,0 @@
-# On Unix platforms, we must specify the absolute path to emcc for cmake, having emcc in PATH will cause cmake to fail finding it.
-# The user must set the EMSCRIPTEN variable to point to the Emscripten root folder.
-
-# Try locating Emscripten root directory based on the location of this toolchain file.
-get_filename_component(GUESS_EMSCRIPTEN_ROOT_PATH "${CMAKE_CURRENT_LIST_FILE}/../../.." ABSOLUTE)
-if (EXISTS "${GUESS_EMSCRIPTEN_ROOT_PATH}/emcc")
- set(EMSCRIPTEN_ROOT_PATH "${GUESS_EMSCRIPTEN_ROOT_PATH}")
-endif()
-
-# If not found, try if the environment variable Emscripten was set.
-if ("${EMSCRIPTEN_ROOT_PATH}" STREQUAL "")
- if ("$ENV{EMSCRIPTEN}" STREQUAL "")
- message(ERROR "Could not locate emcc and the environment variable EMSCRIPTEN has not been set! Please point it to Emscripten root directory!")
- else()
- set(EMSCRIPTEN_ROOT_PATH "$ENV{EMSCRIPTEN}")
- endif()
-endif()
-
-set(CMAKE_C_COMPILER "${EMSCRIPTEN_ROOT_PATH}/emcc")
-set(CMAKE_CXX_COMPILER "${EMSCRIPTEN_ROOT_PATH}/em++")
-set(CMAKE_AR "${EMSCRIPTEN_ROOT_PATH}/emar")
-set(CMAKE_RANLIB "${EMSCRIPTEN_ROOT_PATH}/emranlib")
-
-include(${EMSCRIPTEN_ROOT_PATH}/cmake/Platform/Emscripten.cmake)
diff --git a/emcc b/emcc
index 958ed7cd..4a49cc12 100755
--- a/emcc
+++ b/emcc
@@ -471,6 +471,9 @@ Options that are modified or new in %s include:
to hide these warnings and acknowledge that the
explicit use of absolute paths is intentional.
+ --proxy-to-worker Generates both html and js files. The main
+ program is in js, and the html proxies to/from it.
+
The target file, if specified (-o <target>), defines what will
be generated:
@@ -740,6 +743,7 @@ try:
save_bc = False
memory_init_file = False
use_preload_cache = False
+ proxy_to_worker = False
if use_cxx:
default_cxx_std = '-std=c++03' # Enforce a consistent C++ standard when compiling .cpp files, if user does not specify one on the cmdline.
@@ -903,6 +907,9 @@ try:
memory_init_file = int(newargs[i+1])
newargs[i] = ''
newargs[i+1] = ''
+ elif newargs[i] == '--proxy-to-worker':
+ proxy_to_worker = True
+ newargs[i] = ''
elif newargs[i].startswith(('-I', '-L')):
path_name = newargs[i][2:]
if not absolute_warning_shown and os.path.isabs(path_name):
@@ -1128,6 +1135,9 @@ try:
if shared.Settings.ASM_JS and shared.Settings.DLOPEN_SUPPORT:
assert shared.Settings.DISABLE_EXCEPTION_CATCHING, 'no exceptions support with dlopen in asm yet'
+ if proxy_to_worker:
+ shared.Settings.PROXY_TO_WORKER = 1
+
## Compile source code to bitcode
logging.debug('compiling to bitcode')
@@ -1144,7 +1154,7 @@ try:
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
if input_file.endswith(CXX_SUFFIXES):
args += shared.EMSDK_CXX_OPTS
- logging.debug("running:" + call + ' ' + ' '.join(args))
+ logging.debug("running: " + call + ' ' + ' '.join(args))
execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
if not os.path.exists(output_file):
logging.error('compiler frontend failed to generate LLVM bitcode, halting')
@@ -1709,7 +1719,11 @@ try:
logging.debug('generating HTML')
shell = open(shell_path).read()
html = open(target, 'w')
- if not Compression.on:
+ if proxy_to_worker:
+ html.write(shell.replace('{{{ SCRIPT_CODE }}}', open(shared.path_from_root('src', 'proxyClient.js')).read().replace('{{{ filename }}}', target_basename)))
+ js_target = unsuffixed(target) + '.js'
+ shutil.copyfile(final, js_target)
+ elif not Compression.on:
if debug_level >= 4:
match = re.match('.*?<script[^>]*>{{{ SCRIPT_CODE }}}</script>', shell,
re.DOTALL)
@@ -1783,13 +1797,12 @@ try:
html.close()
else:
if split_js_file:
- from tools.split import split_javascript_file
- split_javascript_file(final, unsuffixed(target), split_js_file)
+ from tools.split import split_javascript_file
+ split_javascript_file(final, unsuffixed(target), split_js_file)
else:
- if debug_level >= 4: generate_source_map(target)
-
- # copy final JS to output
- shutil.move(final, target)
+ if debug_level >= 4: generate_source_map(target)
+ # copy final JS to output
+ shutil.move(final, target)
if DEBUG: logging.debug('total time: %.2f seconds' % (time.time() - start_time))
diff --git a/emscripten.py b/emscripten.py
index 257527fe..4d744fdd 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -43,6 +43,12 @@ NUM_CHUNKS_PER_CORE = 1.25
MIN_CHUNK_SIZE = 1024*1024
MAX_CHUNK_SIZE = float(os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or 'inf') # configuring this is just for debugging purposes
+STDERR_FILE = os.environ.get('EMCC_STDERR_FILE')
+if STDERR_FILE:
+ STDERR_FILE = os.path.abspath(STDERR_FILE)
+ print >> sys.stderr, 'logging stderr in js compiler phase into %s' % STDERR_FILE
+ STDERR_FILE = open(STDERR_FILE, 'w')
+
def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files, DEBUG)):
try:
funcs_file = temp_files.get('.func_%d.ll' % i).name
@@ -57,6 +63,7 @@ def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libr
engine=compiler_engine,
args=[settings_file, funcs_file, 'funcs', forwarded_file] + libraries,
stdout=subprocess.PIPE,
+ stderr=STDERR_FILE,
cwd=path_from_root('src'))
except KeyboardInterrupt:
# Python 2.7 seems to lock up when a child process throws KeyboardInterrupt
@@ -179,7 +186,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if out and DEBUG: print >> sys.stderr, ' loading pre from jcache'
if not out:
open(pre_file, 'w').write(pre_input)
- out = jsrun.run_js(compiler, compiler_engine, [settings_file, pre_file, 'pre'] + libraries, stdout=subprocess.PIPE,
+ out = jsrun.run_js(compiler, compiler_engine, [settings_file, pre_file, 'pre'] + libraries, stdout=subprocess.PIPE, stderr=STDERR_FILE,
cwd=path_from_root('src'))
assert '//FORWARDED_DATA:' in out, 'Did not receive forwarded data in pre output - process failed?'
if jcache:
@@ -287,6 +294,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
exported_implemented_functions = set()
for func_js, curr_forwarded_data in outputs:
curr_forwarded_json = json.loads(curr_forwarded_data)
+ forwarded_json['Types']['hasInlineJS'] = forwarded_json['Types']['hasInlineJS'] or curr_forwarded_json['Types']['hasInlineJS']
forwarded_json['Types']['preciseI64MathUsed'] = forwarded_json['Types']['preciseI64MathUsed'] or curr_forwarded_json['Types']['preciseI64MathUsed']
for key, value in curr_forwarded_json['Functions']['blockAddresses'].iteritems():
forwarded_json['Functions']['blockAddresses'][key] = value
@@ -376,7 +384,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if DEBUG: t = time.time()
post_file = temp_files.get('.post.ll').name
open(post_file, 'w').write('\n') # no input, just processing of forwarded data
- out = jsrun.run_js(compiler, compiler_engine, [settings_file, post_file, 'post', forwarded_file] + libraries, stdout=subprocess.PIPE,
+ out = jsrun.run_js(compiler, compiler_engine, [settings_file, post_file, 'post', forwarded_file] + libraries, stdout=subprocess.PIPE, stderr=STDERR_FILE,
cwd=path_from_root('src'))
post, last_forwarded_data = out.split('//FORWARDED_DATA:') # if this fails, perhaps the process failed prior to printing forwarded data?
last_forwarded_json = json.loads(last_forwarded_data)
@@ -543,7 +551,7 @@ function asmPrintFloat(x, y) {
}
// EMSCRIPTEN_START_ASM
var asm = (function(global, env, buffer) {
- 'use asm';
+ %s
var HEAP8 = new global.Int8Array(buffer);
var HEAP16 = new global.Int16Array(buffer);
var HEAP32 = new global.Int32Array(buffer);
@@ -552,7 +560,7 @@ var asm = (function(global, env, buffer) {
var HEAPU32 = new global.Uint32Array(buffer);
var HEAPF32 = new global.Float32Array(buffer);
var HEAPF64 = new global.Float64Array(buffer);
-''' % (asm_setup,) + '\n' + asm_global_vars + '''
+''' % (asm_setup, "'use asm';" if not forwarded_json['Types']['hasInlineJS'] and not settings['SIDE_MODULE'] else "'almost asm';") + '\n' + asm_global_vars + '''
var __THREW__ = 0;
var threwValue = 0;
var setjmpId = 0;
diff --git a/src/intertyper.js b/src/intertyper.js
index ddb93d71..082fd993 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -708,13 +708,15 @@ function intertyper(data, sidePass, baseLineNums) {
item.ident = eatLLVMIdent(tokensLeft);
if (item.ident == 'asm') {
if (ASM_JS) {
- warnOnce('inline JS in asm.js mode can cause the code to no longer fall in the asm.js subset of JavaScript');
+ Types.hasInlineJS = true;
+ warnOnce('inline JavaScript (asm, EM_ASM) will cause the code to no longer fall in the asm.js subset of JavaScript, which can reduce performance - consider using emscripten_run_script');
}
assert(TARGET_LE32, 'inline js is only supported in le32');
// Inline assembly is just JavaScript that we paste into the code
item.intertype = 'value';
if (tokensLeft[0].text == 'sideeffect') tokensLeft.splice(0, 1);
item.ident = tokensLeft[0].text.substr(1, tokensLeft[0].text.length-2) || ';'; // use ; for empty inline assembly
+ assert((item.tokens[5].text.match(/=/g) || []).length <= 1, 'we only support at most 1 exported variable from inline js: ' + item.ident);
var i = 0;
var params = [], args = [];
splitTokenList(tokensLeft[3].item.tokens).map(function(element) {
diff --git a/src/jsifier.js b/src/jsifier.js
index 38f3bd5e..49f2c564 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -324,11 +324,13 @@ function JSify(data, functionsOnly, givenFunctions) {
assert(typeof constant === 'object');//, [typeof constant, JSON.stringify(constant), item.external]);
// This is a flattened object. We need to find its idents, so they can be assigned to later
+ var structTypes = null;
constant.forEach(function(value, i) {
if (needsPostSet(value)) { // ident, or expression containing an ident
+ if (!structTypes) structTypes = generateStructTypes(item.type);
ret.push({
intertype: 'GlobalVariablePostSet',
- JS: makeSetValue(makeGlobalUse(item.ident), i, value, 'i32', false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors
+ JS: makeSetValue(makeGlobalUse(item.ident), i, value, structTypes[i], false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors
});
constant[i] = '0';
}
@@ -1831,7 +1833,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
if (CORRUPTION_CHECK) {
- assert(!ASM_JS); // cannot monkeypatch asm!
+ assert(!ASM_JS, 'corruption checker is not compatible with asm.js');
print(processMacros(read('corruptionCheck.js')));
}
if (HEADLESS) {
@@ -1841,6 +1843,9 @@ function JSify(data, functionsOnly, givenFunctions) {
print(read('headless.js').replace("'%s'", "'http://emscripten.org'").replace("'?%s'", "''").replace("'?%s'", "'/'").replace('%s,', 'null,').replace('%d', '0'));
print('}');
}
+ if (PROXY_TO_WORKER) {
+ print(read('proxyWorker.js'));
+ }
if (RUNTIME_TYPE_INFO) {
Types.cleanForRuntime();
print('Runtime.typeInfo = ' + JSON.stringify(Types.types));
diff --git a/src/library_browser.js b/src/library_browser.js
index 235ccc78..e4966e15 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -724,7 +724,15 @@ mergeInto(LibraryManager.library, {
Module['preMainLoop']();
}
- Runtime.dynCall('v', func);
+ try {
+ Runtime.dynCall('v', func);
+ } catch (e) {
+ if (e instanceof ExitStatus) {
+ return;
+ } else {
+ throw e;
+ }
+ }
if (Module['postMainLoop']) {
Module['postMainLoop']();
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 9231f41b..9383834f 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -442,6 +442,14 @@ var LibrarySDL = {
}
// fall through
case 'keydown': case 'keyup': case 'keypress': case 'mousedown': case 'mouseup': case 'DOMMouseScroll': case 'mousewheel':
+ // If we preventDefault on keydown events, the subsequent keypress events
+ // won't fire. However, it's fine (and in some cases necessary) to
+ // preventDefault for keys that don't generate a character. Otherwise,
+ // preventDefault is the right thing to do in general.
+ if (event.type !== 'keydown' || (event.keyCode === 8 /* backspace */ || event.keyCode === 9 /* tab */)) {
+ event.preventDefault();
+ }
+
if (event.type == 'DOMMouseScroll' || event.type == 'mousewheel') {
var button = (event.type == 'DOMMouseScroll' ? event.detail : -event.wheelDelta) > 0 ? 4 : 3;
var event2 = {
@@ -463,7 +471,6 @@ var LibrarySDL = {
// ignore extra ups, can happen if we leave the canvas while pressing down, then return,
// since we add a mouseup in that case
if (!SDL.DOMButtons[event.button]) {
- event.preventDefault();
return;
}
@@ -499,13 +506,6 @@ var LibrarySDL = {
SDL.savedKeydown = event;
}
- // If we preventDefault on keydown events, the subsequent keypress events
- // won't fire. However, it's fine (and in some cases necessary) to
- // preventDefault for keys that don't generate a character.
- if (event.type !== 'keydown' || (event.keyCode === 8 /* backspace */ || event.keyCode === 9 /* tab */)) {
- event.preventDefault();
- }
-
// Don't push keypress events unless SDL_StartTextInput has been called.
if (event.type !== 'keypress' || SDL.textInput) {
SDL.events.push(event);
@@ -755,7 +755,7 @@ var LibrarySDL = {
document.addEventListener("keydown", SDL.receiveEvent);
document.addEventListener("keyup", SDL.receiveEvent);
document.addEventListener("keypress", SDL.receiveEvent);
- document.addEventListener("blur", SDL.receiveEvent);
+ window.addEventListener("blur", SDL.receiveEvent);
document.addEventListener("visibilitychange", SDL.receiveEvent);
}
window.addEventListener("unload", SDL.receiveEvent);
@@ -883,6 +883,14 @@ var LibrarySDL = {
surfData.locked++;
if (surfData.locked > 1) return 0;
+ // Mark in C/C++-accessible SDL structure
+ // SDL_Surface has the following fields: Uint32 flags, SDL_PixelFormat *format; int w, h; Uint16 pitch; void *pixels; ...
+ // So we have fields all of the same size, and 5 of them before us.
+ // TODO: Use macros like in library.js
+ {{{ makeSetValue('surf', '5*Runtime.QUANTUM_SIZE', 'surfData.buffer', 'void*') }}};
+
+ if (surf == SDL.screen && Module.screenIsReadOnly && surfData.image) return 0;
+
surfData.image = surfData.ctx.getImageData(0, 0, surfData.width, surfData.height);
if (surf == SDL.screen) {
var data = surfData.image.data;
@@ -925,12 +933,6 @@ var LibrarySDL = {
}
}
- // Mark in C/C++-accessible SDL structure
- // SDL_Surface has the following fields: Uint32 flags, SDL_PixelFormat *format; int w, h; Uint16 pitch; void *pixels; ...
- // So we have fields all of the same size, and 5 of them before us.
- // TODO: Use macros like in library.js
- {{{ makeSetValue('surf', '5*Runtime.QUANTUM_SIZE', 'surfData.buffer', 'void*') }}};
-
return 0;
},
@@ -1271,6 +1273,11 @@ var LibrarySDL = {
return 1;
},
+ SDL_SetPalette__deps: ['SDL_SetColors'],
+ SDL_SetPalette: function(surf, flags, colors, firstColor, nColors) {
+ return _SDL_SetColors(surf, colors, firstColor, nColors);
+ },
+
SDL_MapRGB: function(fmt, r, g, b) {
// Canvas screens are always RGBA. We assume the machine is little-endian.
return r&0xff|(g&0xff)<<8|(b&0xff)<<16|0xff000000;
@@ -2276,7 +2283,7 @@ var LibrarySDL = {
SDL_CondWaitTimeout: function() { throw 'SDL_CondWaitTimeout: TODO' },
SDL_WM_IconifyWindow: function() { throw 'SDL_WM_IconifyWindow TODO' },
- Mix_SetPostMix: function() { throw 'Mix_SetPostMix: TODO' },
+ Mix_SetPostMix: function() { Runtime.warnOnce('Mix_SetPostMix: TODO') },
Mix_QuerySpec: function() { throw 'Mix_QuerySpec: TODO' },
Mix_FadeInChannelTimed: function() { throw 'Mix_FadeInChannelTimed' },
Mix_FadeOutChannel: function() { throw 'Mix_FadeOutChannel' },
diff --git a/src/modules.js b/src/modules.js
index 373e60d9..1a931572 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -227,6 +227,8 @@ var Types = {
needAnalysis: {}, // Types noticed during parsing, that need analysis
+ hasInlineJS: false, // whether the program has inline JS anywhere
+
// Set to true if we actually use precise i64 math: If PRECISE_I64_MATH is set, and also such math is actually
// needed (+,-,*,/,% - we do not need it for bitops), or PRECISE_I64_MATH is 2 (forced)
preciseI64MathUsed: (PRECISE_I64_MATH == 2)
@@ -467,7 +469,10 @@ var PassManager = {
}));
} else if (phase == 'funcs') {
print('\n//FORWARDED_DATA:' + JSON.stringify({
- Types: { preciseI64MathUsed: Types.preciseI64MathUsed },
+ Types: {
+ hasInlineJS: Types.hasInlineJS,
+ preciseI64MathUsed: Types.preciseI64MathUsed
+ },
Functions: {
blockAddresses: Functions.blockAddresses,
indexedFunctions: Functions.indexedFunctions,
diff --git a/src/postamble.js b/src/postamble.js
index df844121..94b60288 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -10,8 +10,8 @@ ExitStatus.prototype = new Error();
ExitStatus.prototype.constructor = ExitStatus;
var initialStackTop;
-
var preloadStartTime = null;
+var calledMain = false;
Module['callMain'] = Module.callMain = function callMain(args) {
assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)');
@@ -70,6 +70,8 @@ Module['callMain'] = Module.callMain = function callMain(args) {
} else {
throw e;
}
+ } finally {
+ calledMain = true;
}
}
@@ -126,7 +128,15 @@ function exit(status) {
// exit the runtime
exitRuntime();
-
+
+ // TODO We should handle this differently based on environment.
+ // In the browser, the best we can do is throw an exception
+ // to halt execution, but in node we could process.exit and
+ // I'd imagine SM shell would have something equivalent.
+ // This would let us set a proper exit status (which
+ // would be great for checking test exit statuses).
+ // https://github.com/kripken/emscripten/issues/1371
+
// throw an exception to halt the current execution
throw new ExitStatus(status);
}
diff --git a/src/preamble.js b/src/preamble.js
index 227b3043..abcd1c67 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -569,6 +569,78 @@ function Pointer_stringify(ptr, /* optional */ length) {
}
Module['Pointer_stringify'] = Pointer_stringify;
+// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns
+// a copy of that string as a Javascript String object.
+function UTF16ToString(ptr) {
+ var i = 0;
+
+ var str = '';
+ while (1) {
+ var codeUnit = {{{ makeGetValue('ptr', 'i*2', 'i16') }}};
+ if (codeUnit == 0)
+ return str;
+ ++i;
+ // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through.
+ str += String.fromCharCode(codeUnit);
+ }
+}
+Module['UTF16ToString'] = UTF16ToString;
+
+// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
+// null-terminated and encoded in UTF16LE form. The copy will require at most (str.length*2+1)*2 bytes of space in the HEAP.
+function stringToUTF16(str, outPtr) {
+ for(var i = 0; i < str.length; ++i) {
+ // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
+ var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
+ {{{ makeSetValue('outPtr', 'i*2', 'codeUnit', 'i16') }}}
+ }
+ // Null-terminate the pointer to the HEAP.
+ {{{ makeSetValue('outPtr', 'str.length*2', 0, 'i16') }}}
+}
+Module['stringToUTF16'] = stringToUTF16;
+
+// Given a pointer 'ptr' to a null-terminated UTF32LE-encoded string in the emscripten HEAP, returns
+// a copy of that string as a Javascript String object.
+function UTF32ToString(ptr) {
+ var i = 0;
+
+ var str = '';
+ while (1) {
+ var utf32 = {{{ makeGetValue('ptr', 'i*4', 'i32') }}};
+ if (utf32 == 0)
+ return str;
+ ++i;
+ // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing.
+ if (utf32 >= 0x10000) {
+ var ch = utf32 - 0x10000;
+ str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
+ } else {
+ str += String.fromCharCode(utf32);
+ }
+ }
+}
+Module['UTF32ToString'] = UTF32ToString;
+
+// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
+// null-terminated and encoded in UTF32LE form. The copy will require at most (str.length+1)*4 bytes of space in the HEAP,
+// but can use less, since str.length does not return the number of characters in the string, but the number of UTF-16 code units in the string.
+function stringToUTF32(str, outPtr) {
+ var iChar = 0;
+ for(var iCodeUnit = 0; iCodeUnit < str.length; ++iCodeUnit) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
+ var codeUnit = str.charCodeAt(iCodeUnit); // possibly a lead surrogate
+ if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) {
+ var trailSurrogate = str.charCodeAt(++iCodeUnit);
+ codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF);
+ }
+ {{{ makeSetValue('outPtr', 'iChar*4', 'codeUnit', 'i32') }}}
+ ++iChar;
+ }
+ // Null-terminate the pointer to the HEAP.
+ {{{ makeSetValue('outPtr', 'iChar*4', 0, 'i32') }}}
+}
+Module['stringToUTF32'] = stringToUTF32;
+
// Memory management
var PAGE_SIZE = 4096;
diff --git a/src/proxyClient.js b/src/proxyClient.js
new file mode 100644
index 00000000..04f7ed11
--- /dev/null
+++ b/src/proxyClient.js
@@ -0,0 +1,74 @@
+
+// proxy to/from worker
+
+Module.ctx = Module.canvas.getContext('2d');
+
+var worker = new Worker('{{{ filename }}}.js');
+
+worker.onmessage = function(event) {
+ var data = event.data;
+ switch (data.target) {
+ case 'stdout': {
+ Module.print(data.content);
+ break;
+ }
+ case 'stderr': {
+ Module.printErr(data.content);
+ break;
+ }
+ case 'window': {
+ window[data.method]();
+ break;
+ }
+ case 'canvas': {
+ switch (data.op) {
+ case 'resize': {
+ Module.canvas.width = data.width;
+ Module.canvas.height = data.height;
+ Module.canvasData = Module.ctx.getImageData(0, 0, data.width, data.height);
+ postMessage({ target: 'canvas', boundingClientRect: Module.canvas.getBoundingClientRect() });
+ break;
+ }
+ case 'render': {
+ Module.canvasData.data.set(data.image.data);
+ Module.ctx.putImageData(Module.canvasData, 0, 0);
+ break;
+ }
+ default: throw 'eh?';
+ }
+ break;
+ }
+ default: throw 'what?';
+ }
+};
+
+function cloneEvent(event) {
+ var ret = {};
+ for (var x in event) {
+ if (x == x.toUpperCase()) continue;
+ var prop = event[x];
+ if (typeof prop === 'number' || typeof prop === 'string') ret[x] = prop;
+ }
+ return ret;
+};
+
+['keydown', 'keyup', 'keypress', 'blur', 'visibilitychange'].forEach(function(event) {
+ document.addEventListener(event, function(event) {
+ worker.postMessage({ target: 'document', event: cloneEvent(event) });
+ event.preventDefault();
+ });
+});
+
+['unload'].forEach(function(event) {
+ window.addEventListener(event, function(event) {
+ worker.postMessage({ target: 'window', event: cloneEvent(event) });
+ });
+});
+
+['mousedown', 'mouseup', 'mousemove', 'DOMMouseScroll', 'mousewheel', 'mouseout'].forEach(function(event) {
+ Module.canvas.addEventListener(event, function(event) {
+ worker.postMessage({ target: 'canvas', event: cloneEvent(event) });
+ event.preventDefault();
+ }, true);
+});
+
diff --git a/src/proxyWorker.js b/src/proxyWorker.js
new file mode 100644
index 00000000..29b2528d
--- /dev/null
+++ b/src/proxyWorker.js
@@ -0,0 +1,143 @@
+
+function EventListener() {
+ this.listeners = {};
+
+ this.addEventListener = function(event, func) {
+ if (!this.listeners[event]) this.listeners[event] = [];
+ this.listeners[event].push(func);
+ };
+
+ this.fireEvent = function(event) {
+ event.preventDefault = function(){};
+
+ if (event.type in this.listeners) {
+ this.listeners[event.type].forEach(function(listener) {
+ listener(event);
+ });
+ }
+ };
+};
+
+var window = this;
+var windowExtra = new EventListener();
+for (var x in windowExtra) window[x] = windowExtra[x];
+
+window.close = function() {
+ postMessage({ target: 'window', method: 'close' });
+};
+
+var document = new EventListener();
+
+document.createElement = function(what) {
+ switch(what) {
+ case 'canvas': {
+ var canvas = new EventListener();
+ canvas.ensureData = function() {
+ if (!canvas.data || canvas.data.width !== canvas.width || canvas.data.height !== canvas.height) {
+ canvas.data = {
+ width: canvas.width,
+ height: canvas.height,
+ data: new Uint8Array(canvas.width*canvas.height*4)
+ };
+ postMessage({ target: 'canvas', op: 'resize', width: canvas.width, height: canvas.height });
+ }
+ };
+ canvas.getContext = function(type) {
+ assert(type == '2d');
+ return {
+ getImageData: function(x, y, w, h) {
+ assert(x == 0 && y == 0 && w == canvas.width && h == canvas.height);
+ canvas.ensureData();
+ return {
+ width: canvas.data.width,
+ height: canvas.data.height,
+ data: new Uint8Array(canvas.data.data) // TODO: can we avoid this copy?
+ };
+ },
+ putImageData: function(image, x, y) {
+ canvas.ensureData();
+ assert(x == 0 && y == 0 && image.width == canvas.width && image.height == canvas.height);
+ canvas.data.data.set(image.data); // TODO: can we avoid this copy?
+ postMessage({ target: 'canvas', op: 'render', image: canvas.data });
+ }
+ };
+ };
+ canvas.boundingClientRect = {};
+ canvas.getBoundingClientRect = function() {
+ return {
+ width: canvas.boundingClientRect.width,
+ height: canvas.boundingClientRect.height,
+ top: canvas.boundingClientRect.top,
+ left: canvas.boundingClientRect.left,
+ bottom: canvas.boundingClientRect.bottom,
+ right: canvas.boundingClientRect.right
+ };
+ };
+ return canvas;
+ }
+ default: throw 'document.createElement ' + what;
+ }
+};
+
+var console = {
+ log: function(x) {
+ Module.printErr(x);
+ }
+};
+
+Module.canvas = document.createElement('canvas');
+
+Module.setStatus = function(){};
+
+Module.print = function(x) {
+ postMessage({ target: 'stdout', content: x });
+};
+Module.printErr = function(x) {
+ postMessage({ target: 'stderr', content: x });
+};
+
+// buffer messages until the program starts to run
+
+var messageBuffer = null;
+
+function messageResender() {
+ if (calledMain) {
+ assert(messageBuffer && messageBuffer.length > 0);
+ messageBuffer.forEach(function(message) {
+ onmessage(message);
+ });
+ messageBuffer = null;
+ } else {
+ setTimeout(messageResender, 100);
+ }
+}
+
+onmessage = function(message) {
+ if (!calledMain) {
+ if (!messageBuffer) {
+ messageBuffer = [];
+ setTimeout(messageResender, 100);
+ }
+ messageBuffer.push(message);
+ }
+ switch (message.data.target) {
+ case 'document': {
+ document.fireEvent(message.data.event);
+ break;
+ }
+ case 'window': {
+ window.fireEvent(message.data.event);
+ break;
+ }
+ case 'canvas': {
+ if (message.data.event) {
+ Module.canvas.fireEvent(message.data.event);
+ } else if (message.data.boundingClientRect) {
+ Module.canvas.boundingClientRect = message.data.boundingClientRect;
+ } else throw 'ey?';
+ break;
+ }
+ default: throw 'wha? ' + message.data.target;
+ }
+};
+
diff --git a/src/runtime.js b/src/runtime.js
index 33088ad9..6b1afd80 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -214,7 +214,11 @@ var Runtime = {
// and it adds no size
// XXX this happens in java-nbody for example... assert(index === type.fields.length, 'zero-length in the middle!');
size = 0;
- alignSize = type.alignSize || QUANTUM_SIZE;
+ if (Types.types[field]) {
+ alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize);
+ } else {
+ alignSize = type.alignSize || QUANTUM_SIZE;
+ }
} else {
size = Types.types[field].flatSize;
alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize);
diff --git a/src/settings.js b/src/settings.js
index 79c54c2b..1ef0cd58 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -343,6 +343,9 @@ var RUNTIME_LINKED_LIBS = []; // If this is a main file (BUILD_AS_SHARED_LIB ==
// linked libraries can break things.
var BUILD_AS_WORKER = 0; // If set to 1, this is a worker library, a special kind of library
// that is run in a worker. See emscripten.h
+var PROXY_TO_WORKER = 0; // If set to 1, we build the project into a js file that will run
+ // in a worker, and generate an html file that proxies input and
+ // output to/from it.
var LINKABLE = 0; // If set to 1, this file can be linked with others, either as a shared
// library or as the main file that calls a shared library. To enable that,
// we will not internalize all symbols and cull the unused ones, in other
diff --git a/system/bin/sdl-config b/system/bin/sdl-config
new file mode 100755
index 00000000..51dff31d
--- /dev/null
+++ b/system/bin/sdl-config
@@ -0,0 +1,13 @@
+#!/usr/bin/env python2
+
+import sys
+
+print >> sys.stderr, 'emscripten sdl-config called with', sys.argv
+
+args = sys.argv[1:]
+
+if args[0] == '--cflags':
+ print ''
+elif '--version' in args:
+ print '1.3.0'
+
diff --git a/tests/cmake/target_html/CMakeLists.txt b/tests/cmake/target_html/CMakeLists.txt
index 9f891e71..b5c69417 100644
--- a/tests/cmake/target_html/CMakeLists.txt
+++ b/tests/cmake/target_html/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.8)
-project(hello_world_gles.html)
+project(hello_world_gles)
file(GLOB sourceFiles ../../hello_world_gles.c)
@@ -10,5 +10,12 @@ else() # Either MinSizeRel, RelWithDebInfo or Release, all which run with optimi
SET(linkFlags "-O2")
endif()
-add_executable(hello_world_gles.html ${sourceFiles})
-set_target_properties(hello_world_gles.html PROPERTIES LINK_FLAGS "${linkFlags}")
+SET(CMAKE_EXECUTABLE_SUFFIX ".html")
+
+add_executable(hello_world_gles ${sourceFiles})
+set_target_properties(hello_world_gles PROPERTIES LINK_FLAGS "${linkFlags}")
+
+# Validating asm.js requires SpiderMonkey JS VM - detect its presence via the SPIDERMONKEY environment variable.
+if (DEFINED ENV{SPIDERMONKEY} AND CMAKE_BUILD_TYPE STREQUAL Release)
+ em_validate_asmjs_after_build(hello_world_gles)
+endif()
diff --git a/tests/cmake/target_js/CMakeLists.txt b/tests/cmake/target_js/CMakeLists.txt
index 860b70a9..cee5fc42 100644
--- a/tests/cmake/target_js/CMakeLists.txt
+++ b/tests/cmake/target_js/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.8)
-project(hello_world.js)
+project(hello_world)
file(GLOB sourceFiles ../../hello_world.cpp)
@@ -10,5 +10,23 @@ else() # Either MinSizeRel, RelWithDebInfo or Release, all which run with optimi
SET(linkFlags "-O2")
endif()
-add_executable(hello_world.js ${sourceFiles})
-set_target_properties(hello_world.js PROPERTIES LINK_FLAGS "${linkFlags}")
+SET(CMAKE_EXECUTABLE_SUFFIX ".js")
+
+if (WIN32)
+ message(FATAL_ERROR "WIN32 should not be defined when cross-compiling!")
+endif()
+
+if (APPLE)
+ message(FATAL_ERROR "APPLE should not be defined when cross-compiling!")
+endif()
+
+if (NOT EMSCRIPTEN)
+ message(FATAL_ERROR "EMSCRIPTEN should be defined when cross-compiling!")
+endif()
+
+if (NOT CMAKE_C_SIZEOF_DATA_PTR)
+ message(FATAL_ERROR "CMAKE_C_SIZEOF_DATA_PTR was not defined!")
+endif()
+
+add_executable(hello_world ${sourceFiles})
+set_target_properties(hello_world PROPERTIES LINK_FLAGS "${linkFlags}")
diff --git a/tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj b/tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj
deleted file mode 100644
index 5d3026a2..00000000
--- a/tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Emscripten">
- <Configuration>Debug</Configuration>
- <Platform>Emscripten</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Emscripten">
- <Configuration>Release</Configuration>
- <Platform>Emscripten</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{A971FFED-3417-452B-B488-6D4F9F257847}</ProjectGuid>
- <RootNamespace>glbook_15_Hello_Triangle_KD</RootNamespace>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
- <PlatformToolset>emcc</PlatformToolset>
- <ConfigurationType>HTMLPage</ConfigurationType>
- </PropertyGroup>
- <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
- <PlatformToolset>emcc</PlatformToolset>
- <ConfigurationType>HTMLPage</ConfigurationType>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
- <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
- <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>Disabled</Optimization>
- </ClCompile>
- <Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- </ClCompile>
- <Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
- <ClCompile>
- <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
- <DisableWarnings>pointer-sign</DisableWarnings>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
- <ClCompile>
- <AdditionalIncludeDirectories>../glbook/Common</AdditionalIncludeDirectories>
- <DisableWarnings>pointer-sign</DisableWarnings>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="..\glbook\Chapter_15\Hello_Triangle_KD\Hello_Triangle_KD.c" />
- <ClCompile Include="..\glbook\Common\esShader.c" />
- <ClCompile Include="..\glbook\Common\esShapes.c" />
- <ClCompile Include="..\glbook\Common\esTransform.c" />
- <ClCompile Include="..\glbook\Common\esUtil.c" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="..\glbook\Common\esUtil.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/tests/msvc10/tests_msvc10.sln b/tests/msvc10/tests_msvc10.sln
index e606469b..6f879060 100644
--- a/tests/msvc10/tests_msvc10.sln
+++ b/tests/msvc10/tests_msvc10.sln
@@ -21,8 +21,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_11_Stencil_Test", "g
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_13_ParticleSystem", "glbook_13_ParticleSystem.vcxproj", "{3E62931D-2795-4BD1-8AA7-55F5440AD293}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_15_Hello_Triangle_KD", "glbook_15_Hello_Triangle_KD.vcxproj", "{A971FFED-3417-452B-B488-6D4F9F257847}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_8_Simple_VertexShader", "glbook_8_Simple_VertexShader.vcxproj", "{2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_9_MipMap2D", "glbook_9_MipMap2D.vcxproj", "{9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}"
@@ -73,207 +71,296 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "twopart", "twopart.vcxproj"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_2_Hello_Triangle", "glbook_2_Hello_Triangle.vcxproj", "{FA655211-CC00-4827-BBCB-B8749BB7671D}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gles", "gles", "{9DCFC12B-65CB-4965-9F16-C63B467E2E9E}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sdl", "sdl", "{70A8D326-5CBD-4C8A-BE84-39B0528C2479}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "other", "other", "{8E55380B-7067-47FF-8B6B-6D656B8D8CC3}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "README", "README", "{AFB0F421-9B24-495D-B961-EA94780F36E5}"
- ProjectSection(SolutionItems) = preProject
- README.txt = README.txt
- EndProjectSection
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Emscripten = Debug|Emscripten
+ Debug|Win32 = Debug|Win32
Release|Emscripten = Release|Emscripten
+ Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Debug|Win32.Build.0 = Debug|Win32
{6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Release|Emscripten.ActiveCfg = Release|Emscripten
{6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Release|Emscripten.Build.0 = Release|Emscripten
+ {6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Release|Win32.ActiveCfg = Release|Win32
+ {6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Release|Win32.Build.0 = Release|Win32
{C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Debug|Win32.Build.0 = Debug|Win32
{C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Release|Emscripten.ActiveCfg = Release|Emscripten
{C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Release|Emscripten.Build.0 = Release|Emscripten
+ {C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Release|Win32.ActiveCfg = Release|Win32
+ {C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Release|Win32.Build.0 = Release|Win32
{DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Debug|Win32.Build.0 = Debug|Win32
{DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Release|Emscripten.ActiveCfg = Release|Emscripten
{DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Release|Emscripten.Build.0 = Release|Emscripten
+ {DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Release|Win32.ActiveCfg = Release|Win32
+ {DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Release|Win32.Build.0 = Release|Win32
{A7C445F9-FCE6-48D5-9343-734071A59185}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{A7C445F9-FCE6-48D5-9343-734071A59185}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {A7C445F9-FCE6-48D5-9343-734071A59185}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A7C445F9-FCE6-48D5-9343-734071A59185}.Debug|Win32.Build.0 = Debug|Win32
{A7C445F9-FCE6-48D5-9343-734071A59185}.Release|Emscripten.ActiveCfg = Release|Emscripten
{A7C445F9-FCE6-48D5-9343-734071A59185}.Release|Emscripten.Build.0 = Release|Emscripten
+ {A7C445F9-FCE6-48D5-9343-734071A59185}.Release|Win32.ActiveCfg = Release|Win32
+ {A7C445F9-FCE6-48D5-9343-734071A59185}.Release|Win32.Build.0 = Release|Win32
{C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Debug|Win32.Build.0 = Debug|Win32
{C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Release|Emscripten.ActiveCfg = Release|Emscripten
{C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Release|Emscripten.Build.0 = Release|Emscripten
+ {C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Release|Win32.ActiveCfg = Release|Win32
+ {C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Release|Win32.Build.0 = Release|Win32
{982D6A44-9080-4A89-911E-BC1E495267D1}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{982D6A44-9080-4A89-911E-BC1E495267D1}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {982D6A44-9080-4A89-911E-BC1E495267D1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {982D6A44-9080-4A89-911E-BC1E495267D1}.Debug|Win32.Build.0 = Debug|Win32
{982D6A44-9080-4A89-911E-BC1E495267D1}.Release|Emscripten.ActiveCfg = Release|Emscripten
{982D6A44-9080-4A89-911E-BC1E495267D1}.Release|Emscripten.Build.0 = Release|Emscripten
+ {982D6A44-9080-4A89-911E-BC1E495267D1}.Release|Win32.ActiveCfg = Release|Win32
+ {982D6A44-9080-4A89-911E-BC1E495267D1}.Release|Win32.Build.0 = Release|Win32
{A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Debug|Win32.Build.0 = Debug|Win32
{A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Release|Emscripten.ActiveCfg = Release|Emscripten
{A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Release|Emscripten.Build.0 = Release|Emscripten
+ {A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Release|Win32.ActiveCfg = Release|Win32
+ {A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Release|Win32.Build.0 = Release|Win32
{AD9E59DF-1628-4081-8672-212A7103FAAD}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{AD9E59DF-1628-4081-8672-212A7103FAAD}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {AD9E59DF-1628-4081-8672-212A7103FAAD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {AD9E59DF-1628-4081-8672-212A7103FAAD}.Debug|Win32.Build.0 = Debug|Win32
{AD9E59DF-1628-4081-8672-212A7103FAAD}.Release|Emscripten.ActiveCfg = Release|Emscripten
{AD9E59DF-1628-4081-8672-212A7103FAAD}.Release|Emscripten.Build.0 = Release|Emscripten
+ {AD9E59DF-1628-4081-8672-212A7103FAAD}.Release|Win32.ActiveCfg = Release|Win32
+ {AD9E59DF-1628-4081-8672-212A7103FAAD}.Release|Win32.Build.0 = Release|Win32
{2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Debug|Win32.Build.0 = Debug|Win32
{2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Release|Emscripten.ActiveCfg = Release|Emscripten
{2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Release|Emscripten.Build.0 = Release|Emscripten
+ {2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Release|Win32.ActiveCfg = Release|Win32
+ {2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Release|Win32.Build.0 = Release|Win32
{3E62931D-2795-4BD1-8AA7-55F5440AD293}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{3E62931D-2795-4BD1-8AA7-55F5440AD293}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {3E62931D-2795-4BD1-8AA7-55F5440AD293}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3E62931D-2795-4BD1-8AA7-55F5440AD293}.Debug|Win32.Build.0 = Debug|Win32
{3E62931D-2795-4BD1-8AA7-55F5440AD293}.Release|Emscripten.ActiveCfg = Release|Emscripten
{3E62931D-2795-4BD1-8AA7-55F5440AD293}.Release|Emscripten.Build.0 = Release|Emscripten
- {A971FFED-3417-452B-B488-6D4F9F257847}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
- {A971FFED-3417-452B-B488-6D4F9F257847}.Debug|Emscripten.Build.0 = Debug|Emscripten
- {A971FFED-3417-452B-B488-6D4F9F257847}.Release|Emscripten.ActiveCfg = Release|Emscripten
- {A971FFED-3417-452B-B488-6D4F9F257847}.Release|Emscripten.Build.0 = Release|Emscripten
+ {3E62931D-2795-4BD1-8AA7-55F5440AD293}.Release|Win32.ActiveCfg = Release|Win32
+ {3E62931D-2795-4BD1-8AA7-55F5440AD293}.Release|Win32.Build.0 = Release|Win32
{2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Debug|Win32.Build.0 = Debug|Win32
{2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Release|Emscripten.ActiveCfg = Release|Emscripten
{2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Release|Emscripten.Build.0 = Release|Emscripten
+ {2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Release|Win32.ActiveCfg = Release|Win32
+ {2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Release|Win32.Build.0 = Release|Win32
{9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Debug|Win32.Build.0 = Debug|Win32
{9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Release|Emscripten.ActiveCfg = Release|Emscripten
{9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Release|Emscripten.Build.0 = Release|Emscripten
+ {9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Release|Win32.ActiveCfg = Release|Win32
+ {9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Release|Win32.Build.0 = Release|Win32
{2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Debug|Win32.Build.0 = Debug|Win32
{2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Release|Emscripten.ActiveCfg = Release|Emscripten
{2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Release|Emscripten.Build.0 = Release|Emscripten
+ {2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Release|Win32.ActiveCfg = Release|Win32
+ {2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Release|Win32.Build.0 = Release|Win32
{660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Debug|Win32.Build.0 = Debug|Win32
{660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Release|Emscripten.ActiveCfg = Release|Emscripten
{660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Release|Emscripten.Build.0 = Release|Emscripten
+ {660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Release|Win32.ActiveCfg = Release|Win32
+ {660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Release|Win32.Build.0 = Release|Win32
{5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Debug|Win32.Build.0 = Debug|Win32
{5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Release|Emscripten.ActiveCfg = Release|Emscripten
{5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Release|Emscripten.Build.0 = Release|Emscripten
+ {5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Release|Win32.ActiveCfg = Release|Win32
+ {5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Release|Win32.Build.0 = Release|Win32
{EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Debug|Win32.Build.0 = Debug|Win32
{EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Release|Emscripten.ActiveCfg = Release|Emscripten
{EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Release|Emscripten.Build.0 = Release|Emscripten
+ {EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Release|Win32.ActiveCfg = Release|Win32
+ {EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Release|Win32.Build.0 = Release|Win32
{DFBD530C-9163-4558-B607-2A226BCC8DC0}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{DFBD530C-9163-4558-B607-2A226BCC8DC0}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {DFBD530C-9163-4558-B607-2A226BCC8DC0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DFBD530C-9163-4558-B607-2A226BCC8DC0}.Debug|Win32.Build.0 = Debug|Win32
{DFBD530C-9163-4558-B607-2A226BCC8DC0}.Release|Emscripten.ActiveCfg = Release|Emscripten
{DFBD530C-9163-4558-B607-2A226BCC8DC0}.Release|Emscripten.Build.0 = Release|Emscripten
+ {DFBD530C-9163-4558-B607-2A226BCC8DC0}.Release|Win32.ActiveCfg = Release|Win32
+ {DFBD530C-9163-4558-B607-2A226BCC8DC0}.Release|Win32.Build.0 = Release|Win32
{19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Debug|Win32.ActiveCfg = Debug|Win32
+ {19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Debug|Win32.Build.0 = Debug|Win32
{19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Release|Emscripten.ActiveCfg = Release|Emscripten
{19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Release|Emscripten.Build.0 = Release|Emscripten
+ {19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Release|Win32.ActiveCfg = Release|Win32
+ {19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Release|Win32.Build.0 = Release|Win32
{DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Debug|Win32.Build.0 = Debug|Win32
{DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Release|Emscripten.ActiveCfg = Release|Emscripten
{DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Release|Emscripten.Build.0 = Release|Emscripten
+ {DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Release|Win32.ActiveCfg = Release|Win32
+ {DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Release|Win32.Build.0 = Release|Win32
{5C72F8EA-B852-49F6-A979-DE5011957BC7}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{5C72F8EA-B852-49F6-A979-DE5011957BC7}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {5C72F8EA-B852-49F6-A979-DE5011957BC7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {5C72F8EA-B852-49F6-A979-DE5011957BC7}.Debug|Win32.Build.0 = Debug|Win32
{5C72F8EA-B852-49F6-A979-DE5011957BC7}.Release|Emscripten.ActiveCfg = Release|Emscripten
{5C72F8EA-B852-49F6-A979-DE5011957BC7}.Release|Emscripten.Build.0 = Release|Emscripten
+ {5C72F8EA-B852-49F6-A979-DE5011957BC7}.Release|Win32.ActiveCfg = Release|Win32
+ {5C72F8EA-B852-49F6-A979-DE5011957BC7}.Release|Win32.Build.0 = Release|Win32
{DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Debug|Win32.Build.0 = Debug|Win32
{DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Release|Emscripten.ActiveCfg = Release|Emscripten
{DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Release|Emscripten.Build.0 = Release|Emscripten
+ {DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Release|Win32.ActiveCfg = Release|Win32
+ {DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Release|Win32.Build.0 = Release|Win32
{A44C4C27-F173-47D0-8626-59A21D86AC1E}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{A44C4C27-F173-47D0-8626-59A21D86AC1E}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {A44C4C27-F173-47D0-8626-59A21D86AC1E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A44C4C27-F173-47D0-8626-59A21D86AC1E}.Debug|Win32.Build.0 = Debug|Win32
{A44C4C27-F173-47D0-8626-59A21D86AC1E}.Release|Emscripten.ActiveCfg = Release|Emscripten
{A44C4C27-F173-47D0-8626-59A21D86AC1E}.Release|Emscripten.Build.0 = Release|Emscripten
+ {A44C4C27-F173-47D0-8626-59A21D86AC1E}.Release|Win32.ActiveCfg = Release|Win32
+ {A44C4C27-F173-47D0-8626-59A21D86AC1E}.Release|Win32.Build.0 = Release|Win32
{65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Debug|Win32.Build.0 = Debug|Win32
{65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Release|Emscripten.ActiveCfg = Release|Emscripten
{65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Release|Emscripten.Build.0 = Release|Emscripten
+ {65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Release|Win32.ActiveCfg = Release|Win32
+ {65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Release|Win32.Build.0 = Release|Win32
{BE6A123E-9729-44A3-976F-3C06A3724894}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{BE6A123E-9729-44A3-976F-3C06A3724894}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {BE6A123E-9729-44A3-976F-3C06A3724894}.Debug|Win32.ActiveCfg = Debug|Win32
+ {BE6A123E-9729-44A3-976F-3C06A3724894}.Debug|Win32.Build.0 = Debug|Win32
{BE6A123E-9729-44A3-976F-3C06A3724894}.Release|Emscripten.ActiveCfg = Release|Emscripten
{BE6A123E-9729-44A3-976F-3C06A3724894}.Release|Emscripten.Build.0 = Release|Emscripten
+ {BE6A123E-9729-44A3-976F-3C06A3724894}.Release|Win32.ActiveCfg = Release|Win32
+ {BE6A123E-9729-44A3-976F-3C06A3724894}.Release|Win32.Build.0 = Release|Win32
{61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Debug|Win32.Build.0 = Debug|Win32
{61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Release|Emscripten.ActiveCfg = Release|Emscripten
{61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Release|Emscripten.Build.0 = Release|Emscripten
+ {61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Release|Win32.ActiveCfg = Release|Win32
+ {61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Release|Win32.Build.0 = Release|Win32
{F28A1DE1-5949-4AF5-8901-A37871C2514E}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{F28A1DE1-5949-4AF5-8901-A37871C2514E}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {F28A1DE1-5949-4AF5-8901-A37871C2514E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F28A1DE1-5949-4AF5-8901-A37871C2514E}.Debug|Win32.Build.0 = Debug|Win32
{F28A1DE1-5949-4AF5-8901-A37871C2514E}.Release|Emscripten.ActiveCfg = Release|Emscripten
{F28A1DE1-5949-4AF5-8901-A37871C2514E}.Release|Emscripten.Build.0 = Release|Emscripten
+ {F28A1DE1-5949-4AF5-8901-A37871C2514E}.Release|Win32.ActiveCfg = Release|Win32
+ {F28A1DE1-5949-4AF5-8901-A37871C2514E}.Release|Win32.Build.0 = Release|Win32
{CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Debug|Win32.Build.0 = Debug|Win32
{CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Release|Emscripten.ActiveCfg = Release|Emscripten
{CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Release|Emscripten.Build.0 = Release|Emscripten
+ {CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Release|Win32.ActiveCfg = Release|Win32
+ {CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Release|Win32.Build.0 = Release|Win32
{3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Debug|Win32.Build.0 = Debug|Win32
{3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Release|Emscripten.ActiveCfg = Release|Emscripten
{3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Release|Emscripten.Build.0 = Release|Emscripten
+ {3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Release|Win32.ActiveCfg = Release|Win32
+ {3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Release|Win32.Build.0 = Release|Win32
{5CE874BD-2F32-4579-B682-4B74E5764F13}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{5CE874BD-2F32-4579-B682-4B74E5764F13}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {5CE874BD-2F32-4579-B682-4B74E5764F13}.Debug|Win32.ActiveCfg = Debug|Win32
+ {5CE874BD-2F32-4579-B682-4B74E5764F13}.Debug|Win32.Build.0 = Debug|Win32
{5CE874BD-2F32-4579-B682-4B74E5764F13}.Release|Emscripten.ActiveCfg = Release|Emscripten
{5CE874BD-2F32-4579-B682-4B74E5764F13}.Release|Emscripten.Build.0 = Release|Emscripten
+ {5CE874BD-2F32-4579-B682-4B74E5764F13}.Release|Win32.ActiveCfg = Release|Win32
+ {5CE874BD-2F32-4579-B682-4B74E5764F13}.Release|Win32.Build.0 = Release|Win32
{1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Debug|Win32.Build.0 = Debug|Win32
{1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Release|Emscripten.ActiveCfg = Release|Emscripten
{1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Release|Emscripten.Build.0 = Release|Emscripten
+ {1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Release|Win32.ActiveCfg = Release|Win32
+ {1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Release|Win32.Build.0 = Release|Win32
{D3295E36-57BB-4C42-92D8-2AA150024256}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{D3295E36-57BB-4C42-92D8-2AA150024256}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {D3295E36-57BB-4C42-92D8-2AA150024256}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D3295E36-57BB-4C42-92D8-2AA150024256}.Debug|Win32.Build.0 = Debug|Win32
{D3295E36-57BB-4C42-92D8-2AA150024256}.Release|Emscripten.ActiveCfg = Release|Emscripten
{D3295E36-57BB-4C42-92D8-2AA150024256}.Release|Emscripten.Build.0 = Release|Emscripten
+ {D3295E36-57BB-4C42-92D8-2AA150024256}.Release|Win32.ActiveCfg = Release|Win32
+ {D3295E36-57BB-4C42-92D8-2AA150024256}.Release|Win32.Build.0 = Release|Win32
{670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Debug|Win32.Build.0 = Debug|Win32
{670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Release|Emscripten.ActiveCfg = Release|Emscripten
{670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Release|Emscripten.Build.0 = Release|Emscripten
+ {670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Release|Win32.ActiveCfg = Release|Win32
+ {670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Release|Win32.Build.0 = Release|Win32
{678A07B3-3A25-40E4-8A36-7A399056188A}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{678A07B3-3A25-40E4-8A36-7A399056188A}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {678A07B3-3A25-40E4-8A36-7A399056188A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {678A07B3-3A25-40E4-8A36-7A399056188A}.Debug|Win32.Build.0 = Debug|Win32
{678A07B3-3A25-40E4-8A36-7A399056188A}.Release|Emscripten.ActiveCfg = Release|Emscripten
{678A07B3-3A25-40E4-8A36-7A399056188A}.Release|Emscripten.Build.0 = Release|Emscripten
+ {678A07B3-3A25-40E4-8A36-7A399056188A}.Release|Win32.ActiveCfg = Release|Win32
+ {678A07B3-3A25-40E4-8A36-7A399056188A}.Release|Win32.Build.0 = Release|Win32
{C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Debug|Win32.Build.0 = Debug|Win32
{C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Release|Emscripten.ActiveCfg = Release|Emscripten
{C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Release|Emscripten.Build.0 = Release|Emscripten
+ {C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Release|Win32.ActiveCfg = Release|Win32
+ {C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Release|Win32.Build.0 = Release|Win32
{FA655211-CC00-4827-BBCB-B8749BB7671D}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
{FA655211-CC00-4827-BBCB-B8749BB7671D}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {FA655211-CC00-4827-BBCB-B8749BB7671D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FA655211-CC00-4827-BBCB-B8749BB7671D}.Debug|Win32.Build.0 = Debug|Win32
{FA655211-CC00-4827-BBCB-B8749BB7671D}.Release|Emscripten.ActiveCfg = Release|Emscripten
{FA655211-CC00-4827-BBCB-B8749BB7671D}.Release|Emscripten.Build.0 = Release|Emscripten
+ {FA655211-CC00-4827-BBCB-B8749BB7671D}.Release|Win32.ActiveCfg = Release|Win32
+ {FA655211-CC00-4827-BBCB-B8749BB7671D}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {A7C445F9-FCE6-48D5-9343-734071A59185} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {C5500D5B-9489-4109-A6E4-CF8F7E1518E7} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {982D6A44-9080-4A89-911E-BC1E495267D1} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {AD9E59DF-1628-4081-8672-212A7103FAAD} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {2D60F3E0-B83A-4442-94D3-AB4B2F068476} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {3E62931D-2795-4BD1-8AA7-55F5440AD293} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {A971FFED-3417-452B-B488-6D4F9F257847} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {FA655211-CC00-4827-BBCB-B8749BB7671D} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {6A41CB2E-0022-47E1-89C5-FB2B558BEB91} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
- {DDB7FF8E-EC42-4406-832C-F2B043D8760E} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {660E83C1-82AC-487C-BF5E-CFB6B82196BC} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {5970CDD4-FB0A-4E66-B7C9-DAD9E580628D} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {EB0B52B6-0177-4CEE-955D-3C7F052E5F5B} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {DFBD530C-9163-4558-B607-2A226BCC8DC0} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {19DB739D-7EEB-4B99-BB6D-C12F086B5F24} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {DB3B6C01-8CF9-4397-843E-403D5063F2DE} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {5C72F8EA-B852-49F6-A979-DE5011957BC7} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {A44C4C27-F173-47D0-8626-59A21D86AC1E} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {65E0ED61-A813-4AEB-8DB0-A58657858EE2} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {BE6A123E-9729-44A3-976F-3C06A3724894} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {61D7F11F-25EE-4C2C-9D73-8601F68B055E} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {678A07B3-3A25-40E4-8A36-7A399056188A} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {C896D890-9132-4A2D-8BA8-0EB6888FEAC2} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {C29BBEE3-02D1-459A-B8BA-832A3439F12D} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
- {F28A1DE1-5949-4AF5-8901-A37871C2514E} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
- {CE360D01-4362-4FE4-A77E-8EF6E3F623CF} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
- {3EA4E5F5-67B6-4F83-95D7-E041FFF787B0} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
- {5CE874BD-2F32-4579-B682-4B74E5764F13} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
- {1C5338A3-7020-4086-AE99-BC79EA3D42C1} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
- {D3295E36-57BB-4C42-92D8-2AA150024256} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
- {670EA36B-AD2B-4BFC-8DD3-AE024736AFB2} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
- {DA2F2979-2902-42BC-B8DA-6B18FE2AF444} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
- EndGlobalSection
EndGlobal
diff --git a/tests/runner.py b/tests/runner.py
index 8747c340..ddc97ea4 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -646,7 +646,7 @@ class BrowserCore(RunnerCore):
});
''' % basename)
- def btest(self, filename, expected=None, reference=None, force_c=False, reference_slack=0,
+ def btest(self, filename, expected=None, reference=None, force_c=False, reference_slack=0, manual_reference=False, post_build=None,
args=[], outfile='test.html', message='.'): # TODO: use in all other tests
# if we are provided the source and not a path, use that
filename_is_src = '\n' in filename
@@ -663,9 +663,11 @@ class BrowserCore(RunnerCore):
expected = [str(i) for i in range(0, reference_slack+1)]
shutil.copyfile(filepath, temp_filepath)
self.reftest(path_from_root('tests', reference))
- args = args + ['--pre-js', 'reftest.js', '-s', 'GL_TESTING=1']
+ if not manual_reference:
+ args = args + ['--pre-js', 'reftest.js', '-s', 'GL_TESTING=1']
Popen([PYTHON, EMCC, temp_filepath, '-o', outfile] + args).communicate()
assert os.path.exists(outfile)
+ if post_build: post_build()
if type(expected) is str: expected = [expected]
self.run_browser(outfile, message, ['/report_result?' + e for e in expected])
diff --git a/tests/sdl_canvas_proxy.c b/tests/sdl_canvas_proxy.c
new file mode 100644
index 00000000..27ef3bb4
--- /dev/null
+++ b/tests/sdl_canvas_proxy.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <SDL/SDL.h>
+#include <assert.h>
+#include <emscripten.h>
+
+int main(int argc, char **argv) {
+ FILE *f = fopen("data.txt", "rb");
+ assert(f);
+ assert(fgetc(f) == 'd');
+ assert(fgetc(f) == 'a');
+ assert(fgetc(f) == 't');
+ assert(fgetc(f) == 'u');
+ assert(fgetc(f) == 'm');
+ fclose(f);
+
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE);
+
+ SDL_LockSurface(screen);
+ unsigned int *pixels = (unsigned int *)screen->pixels;
+ for (int x = 0; x < screen->w; x++) {
+ for (int y = 0; y < screen->h; y++) {
+ pixels[x + y*screen->h] = x < 300 ? (y < 200 ? 0x3377AA88 : 0xAA3377CC) : (y < 200 ? 0x0066AA77 : 0xAA006699);
+ }
+ }
+ SDL_UnlockSurface(screen);
+
+ SDL_Quit();
+
+ EM_ASM(window.close());
+ return 0;
+}
+
diff --git a/tests/sdl_canvas_proxy.png b/tests/sdl_canvas_proxy.png
new file mode 100644
index 00000000..cc96acfd
--- /dev/null
+++ b/tests/sdl_canvas_proxy.png
Binary files differ
diff --git a/tests/sdl_key_proxy.c b/tests/sdl_key_proxy.c
new file mode 100644
index 00000000..bc233f29
--- /dev/null
+++ b/tests/sdl_key_proxy.c
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_ttf.h>
+#include <emscripten.h>
+
+int result = 1;
+
+void one() {
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ printf("got event %d\n", event.type);
+ switch(event.type) {
+ case SDL_KEYDOWN:
+ break;
+ case SDL_KEYUP:
+ // don't handle the modifier key events
+ if (event.key.keysym.sym == SDLK_LCTRL ||
+ event.key.keysym.sym == SDLK_LSHIFT ||
+ event.key.keysym.sym == SDLK_LALT) {
+ return;
+ }
+ if ((event.key.keysym.mod & KMOD_LCTRL) || (event.key.keysym.mod & KMOD_RCTRL)) {
+ result *= 2;
+ }
+ if ((event.key.keysym.mod & KMOD_LSHIFT) || (event.key.keysym.mod & KMOD_RSHIFT)) {
+ result *= 3;
+ }
+ if ((event.key.keysym.mod & KMOD_LALT) || (event.key.keysym.mod & KMOD_RALT)) {
+ result *= 5;
+ }
+ switch (event.key.keysym.sym) {
+ case SDLK_RIGHT: printf("right\n"); result *= 7; break;
+ case SDLK_LEFT: printf("left\n"); result *= 11; break;
+ case SDLK_DOWN: printf("down\n"); result *= 13; break;
+ case SDLK_UP: printf("up\n"); result *= 17; break;
+ case SDLK_a: printf("a\n"); result *= 19; break;
+ default: {
+ if (event.key.keysym.scancode == SDL_SCANCODE_B) {
+ printf("b scancode\n"); result *= 23; break;
+ }
+ printf("unknown key: sym %d scancode %d\n", event.key.keysym.sym, event.key.keysym.scancode);
+ REPORT_RESULT();
+ emscripten_run_script("throw 'done'"); // comment this out to leave event handling active. Use the following to log DOM keys:
+ // addEventListener('keyup', function(event) { console.log(event.keyCode) }, true)
+ }
+ }
+ break;
+ default: /* Report an unhandled event */
+ printf("I don't know what this event is!\n");
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ printf("main\n");
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE);
+
+ if (argc == 1337) one(); // keep it alive
+
+ return 0;
+}
+
diff --git a/tests/test_browser.py b/tests/test_browser.py
index 3ac640f1..e6fd6544 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -627,6 +627,28 @@ If manually bisecting:
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_canvas.c'), '-o', 'page.html', '-s', 'LEGACY_GL_EMULATION=1']).communicate()
self.run_browser('page.html', '', '/report_result?1')
+ def test_sdl_canvas_proxy(self):
+ def post():
+ html = open('test.html').read()
+ html = html.replace('</body>', '''
+<script>
+function assert(x, y) { if (!x) throw 'assertion failed ' + y }
+
+%s
+
+var windowClose = window.close;
+window.close = function() {
+ doReftest();
+ setTimeout(windowClose, 1000);
+};
+</script>
+</body>''' % open('reftest.js').read())
+ open('test.html', 'w').write(html)
+
+ 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=post)
+
def test_sdl_key(self):
open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
Module.postRun = function() {
@@ -658,6 +680,52 @@ If manually bisecting:
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_key.c'), '-o', 'page.html', '--pre-js', 'pre.js', '-s', '''EXPORTED_FUNCTIONS=['_main', '_one']''']).communicate()
self.run_browser('page.html', '', '/report_result?223092870')
+ def test_sdl_key_proxy(self):
+ open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
+ var Module = {};
+ Module.postRun = function() {
+ function doOne() {
+ Module._one();
+ setTimeout(doOne, 1000/60);
+ }
+ setTimeout(doOne, 1000/60);
+ }
+ ''')
+
+ def post():
+ html = open('test.html').read()
+ html = html.replace('</body>', '''
+<script>
+function keydown(c) {
+ var event = document.createEvent("KeyboardEvent");
+ event.initKeyEvent("keydown", true, true, window,
+ 0, 0, 0, 0,
+ c, c);
+ document.dispatchEvent(event);
+}
+
+function keyup(c) {
+ var event = document.createEvent("KeyboardEvent");
+ event.initKeyEvent("keyup", true, true, window,
+ 0, 0, 0, 0,
+ c, c);
+ document.dispatchEvent(event);
+}
+
+keydown(1250);keydown(38);keyup(38);keyup(1250); // alt, up
+keydown(1248);keydown(1249);keydown(40);keyup(40);keyup(1249);keyup(1248); // ctrl, shift, down
+keydown(37);keyup(37); // left
+keydown(39);keyup(39); // right
+keydown(65);keyup(65); // a
+keydown(66);keyup(66); // b
+keydown(100);keyup(100); // trigger the end
+
+</script>
+</body>''')
+ 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']'''], manual_reference=True, post_build=post)
+
def test_sdl_text(self):
open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
Module.postRun = function() {
diff --git a/tests/test_core.py b/tests/test_core.py
index 5d4f35e8..d02e6778 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -3756,11 +3756,18 @@ def process(filename):
int main() {
asm("Module.print('Inline JS is very cool')");
printf("%.2f\n", get());
+
+ // Test that passing multiple input and output variables works.
+ int src1 = 1, src2 = 2, src3 = 3;
+ int dst1 = 0, dst2 = 0, dst3 = 0;
+ // TODO asm("Module.print(%3); Module.print(%4); Module.print(%5); %0 = %3; %1 = %4; %2 = %5;" : "=r"(dst1),"=r"(dst2),"=r"(dst3): "r"(src1),"r"(src2),"r"(src3));
+ // TODO printf("%d\n%d\n%d\n", dst1, dst2, dst3);
+
return 0;
}
'''
- self.do_run(src, 'Inline JS is very cool\n3.64\n')
+ self.do_run(src, 'Inline JS is very cool\n3.64\n') # TODO 1\n2\n3\n1\n2\n3\n')
def test_inlinejs2(self):
if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
@@ -5432,6 +5439,34 @@ The current type of b is: 9
'''
self.do_run(src, 'memmove can be very useful....!')
+ def test_flexarray_struct(self):
+ src = r'''
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+typedef struct
+{
+ uint16_t length;
+ struct
+ {
+ int32_t int32;
+ } value[];
+} Tuple;
+
+int main() {
+ Tuple T[10];
+ Tuple *t = &T[0];
+
+ t->length = 4;
+ t->value->int32 = 100;
+
+ printf("(%d, %d)\n", t->length, t->value->int32);
+ return 0;
+}
+'''
+ self.do_run(src, '(4, 100)')
+
def test_bsearch(self):
if Settings.QUANTUM_SIZE == 1: return self.skip('Test cannot work with q1')
@@ -7525,6 +7560,12 @@ def process(filename):
'''
self.do_run(src, '206 188 226 128 μ†ℱ ╋ℯ╳╋ 😇\nμ†ℱ ╋ℯ╳╋ 😇,206,188,226,128\n');
+ def test_utf32(self):
+ if self.emcc_args is None: return self.skip('need libc for wcslen()')
+ if not self.is_le32(): return self.skip('this test uses inline js, which requires le32')
+ self.do_run(open(path_from_root('tests', 'utf32.cpp')).read(), 'OK.')
+ self.do_run(open(path_from_root('tests', 'utf32.cpp')).read(), 'OK.', args=['-fshort-wchar'])
+
def test_direct_string_constant_usage(self):
if self.emcc_args is None: return self.skip('requires libcxx')
@@ -8607,29 +8648,44 @@ def process(filename):
Settings.SAFE_HEAP_LINES = ['btVoronoiSimplexSolver.h:40', 'btVoronoiSimplexSolver.h:41',
'btVoronoiSimplexSolver.h:42', 'btVoronoiSimplexSolver.h:43']
- def test():
- self.do_run(open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(),
- [open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings
- open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read(),
- open(path_from_root('tests', 'bullet', 'output3.txt'), 'r').read()],
- libraries=self.get_library('bullet', [os.path.join('src', '.libs', 'libBulletDynamics.a'),
- os.path.join('src', '.libs', 'libBulletCollision.a'),
- os.path.join('src', '.libs', 'libLinearMath.a')],
- configure_args=['--disable-demos','--disable-dependency-tracking']),
- includes=[path_from_root('tests', 'bullet', 'src')])
- test()
-
- assert 'asm2g' in test_modes
- if self.run_name == 'asm2g':
- # Test forced alignment
- print >> sys.stderr, 'testing FORCE_ALIGNED_MEMORY'
- old = open('src.cpp.o.js').read()
- Settings.FORCE_ALIGNED_MEMORY = 1
+ configure_commands = [['sh', './configure'], ['cmake', '.']]
+ configure_args = [['--disable-demos','--disable-dependency-tracking'], ['-DBUILD_DEMOS=OFF', '-DBUILD_EXTRAS=OFF']]
+ for c in range(0,2):
+ configure = configure_commands[c]
+ # Windows cannot run configure sh scripts.
+ if WINDOWS and configure[0] == 'sh':
+ continue
+
+ # Depending on whether 'configure' or 'cmake' is used to build, Bullet places output files in different directory structures.
+ if configure[0] == 'sh':
+ generated_libs = [os.path.join('src', '.libs', 'libBulletDynamics.a'),
+ os.path.join('src', '.libs', 'libBulletCollision.a'),
+ os.path.join('src', '.libs', 'libLinearMath.a')]
+ else:
+ generated_libs = [os.path.join('src', 'BulletDynamics', 'libBulletDynamics.a'),
+ os.path.join('src', 'BulletCollision', 'libBulletCollision.a'),
+ os.path.join('src', 'LinearMath', 'libLinearMath.a')]
+
+ def test():
+ self.do_run(open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(),
+ [open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings
+ open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read(),
+ open(path_from_root('tests', 'bullet', 'output3.txt'), 'r').read()],
+ libraries=self.get_library('bullet', generated_libs, configure=configure, configure_args=configure_args[c], cache_name_extra=configure[0]),
+ includes=[path_from_root('tests', 'bullet', 'src')])
test()
- new = open('src.cpp.o.js').read()
- print len(old), len(new), old.count('tempBigInt'), new.count('tempBigInt')
- assert len(old) > len(new)
- assert old.count('tempBigInt') > new.count('tempBigInt')
+
+ assert 'asm2g' in test_modes
+ if self.run_name == 'asm2g' and configure[0] == 'sh':
+ # Test forced alignment
+ print >> sys.stderr, 'testing FORCE_ALIGNED_MEMORY'
+ old = open('src.cpp.o.js').read()
+ Settings.FORCE_ALIGNED_MEMORY = 1
+ test()
+ new = open('src.cpp.o.js').read()
+ print len(old), len(new), old.count('tempBigInt'), new.count('tempBigInt')
+ assert len(old) > len(new)
+ assert old.count('tempBigInt') > new.count('tempBigInt')
def test_poppler(self):
if self.emcc_args is None: return self.skip('very slow, we only do this in emcc runs')
diff --git a/tests/test_other.py b/tests/test_other.py
index c6f5c333..64be60fa 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -275,60 +275,77 @@ f.close()
# TODO: deprecate llvm optimizations, dlmalloc, etc. in emscripten.py.
def test_cmake(self):
- # On Windows, we want to build cmake-generated Makefiles with mingw32-make instead of e.g. cygwin make, since mingw32-make
- # understands Windows paths, and cygwin make additionally produces a cryptic 'not valid bitcode file' errors on files that
- # *are* valid bitcode files.
-
- if os.name == 'nt':
- make_command = 'mingw32-make'
- emscriptencmaketoolchain = path_from_root('cmake', 'Platform', 'Emscripten.cmake')
+ # Test all supported generators.
+ if WINDOWS:
+ generators = ['MinGW Makefiles', 'NMake Makefiles']
else:
- make_command = 'make'
- emscriptencmaketoolchain = path_from_root('cmake', 'Platform', 'Emscripten_unix.cmake')
+ generators = ['Unix Makefiles']
- cmake_cases = ['target_js', 'target_html']
- cmake_outputs = ['hello_world.js', 'hello_world_gles.html']
- for i in range(0, 2):
- for configuration in ['Debug', 'Release']:
+ make_commands = { 'MinGW Makefiles': ['mingw32-make'], 'NMake Makefiles': ['nmake', '/NOLOGO'], 'Unix Makefiles': ['make'] }
- # Create a temp workspace folder
- cmakelistsdir = path_from_root('tests', 'cmake', cmake_cases[i])
- tempdirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR)
- try:
- os.chdir(tempdirname)
-
- # Run Cmake
- cmd = ['cmake', '-DCMAKE_TOOLCHAIN_FILE='+emscriptencmaketoolchain,
- '-DCMAKE_BUILD_TYPE=' + configuration,
- '-DCMAKE_MODULE_PATH=' + path_from_root('cmake').replace('\\', '/'),
- '-G' 'Unix Makefiles', cmakelistsdir]
- ret = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate()
- if ret[1] != None and len(ret[1].strip()) > 0:
- print >> sys.stderr, ret[1] # If there were any errors, print them directly to console for diagnostics.
- if 'error' in ret[1].lower():
- print >> sys.stderr, 'Failed command: ' + ' '.join(cmd)
- print >> sys.stderr, 'Result:\n' + ret[1]
- raise Exception('cmake call failed!')
- assert os.path.exists(tempdirname + '/Makefile'), 'CMake call did not produce a Makefile!'
-
- # Build
- cmd = [make_command]
- ret = Popen(cmd, stdout=PIPE).communicate()
- if ret[1] != None and len(ret[1].strip()) > 0:
- print >> sys.stderr, ret[1] # If there were any errors, print them directly to console for diagnostics.
- if 'error' in ret[0].lower() and not '0 error(s)' in ret[0].lower():
- print >> sys.stderr, 'Failed command: ' + ' '.join(cmd)
- print >> sys.stderr, 'Result:\n' + ret[0]
- raise Exception('make failed!')
- assert os.path.exists(tempdirname + '/' + cmake_outputs[i]), 'Building a cmake-generated Makefile failed to produce an output file %s!' % tempdirname + '/' + cmake_outputs[i]
-
- # Run through node, if CMake produced a .js file.
- if cmake_outputs[i].endswith('.js'):
- ret = Popen(listify(NODE_JS) + [tempdirname + '/' + cmake_outputs[i]], stdout=PIPE).communicate()[0]
- assert 'hello, world!' in ret, 'Running cmake-based .js application failed!'
- finally:
- os.chdir(path_from_root('tests')) # Move away from the directory we are about to remove.
- shutil.rmtree(tempdirname)
+ if os.name == 'nt':
+ emconfigure = path_from_root('emconfigure.bat')
+ else:
+ emconfigure = path_from_root('emconfigure')
+
+ for generator in generators:
+ if generator == 'NMake Makefiles' and not Building.which('nmake'):
+ print >> sys.stderr, 'Skipping NMake test for CMake support, since nmake was not found in PATH. Run this test in Visual Studio command prompt to easily access nmake.'
+ continue
+
+ make = make_commands[generator]
+ cmake_cases = ['target_js', 'target_html']
+ cmake_outputs = ['hello_world.js', 'hello_world_gles.html']
+ for i in range(0, 2):
+ for configuration in ['Debug', 'Release']:
+ # CMake can be invoked in two ways, using 'emconfigure cmake', or by directly running 'cmake'.
+ # Test both methods.
+ for invoke_method in ['cmake', 'emconfigure']:
+
+ # Create a temp workspace folder
+ cmakelistsdir = path_from_root('tests', 'cmake', cmake_cases[i])
+ tempdirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR)
+ try:
+ os.chdir(tempdirname)
+
+ verbose_level = int(os.getenv('EM_BUILD_VERBOSE')) if os.getenv('EM_BUILD_VERBOSE') != None else 0
+
+ # Run Cmake
+ if invoke_method == 'cmake':
+ # Test invoking cmake directly.
+ cmd = ['cmake', '-DCMAKE_TOOLCHAIN_FILE='+path_from_root('cmake', 'Platform', 'Emscripten.cmake'),
+ '-DCMAKE_BUILD_TYPE=' + configuration, '-G', generator, cmakelistsdir]
+ else:
+ # Test invoking via 'emconfigure cmake'
+ cmd = [emconfigure, 'cmake', '-DCMAKE_BUILD_TYPE=' + configuration, '-G', generator, cmakelistsdir]
+
+ ret = Popen(cmd, stdout=None if verbose_level >= 2 else PIPE, stderr=None if verbose_level >= 1 else PIPE).communicate()
+ if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
+ logging.error(ret[1]) # If there were any errors, print them directly to console for diagnostics.
+ if len(ret) > 1 and ret[1] != None and 'error' in ret[1].lower():
+ logging.error('Failed command: ' + ' '.join(cmd))
+ logging.error('Result:\n' + ret[1])
+ raise Exception('cmake call failed!')
+ assert os.path.exists(tempdirname + '/Makefile'), 'CMake call did not produce a Makefile!'
+
+ # Build
+ cmd = make + (['VERBOSE=1'] if verbose_level >= 3 else [])
+ ret = Popen(cmd, stdout=None if verbose_level >= 2 else PIPE).communicate()
+ if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
+ logging.error(ret[1]) # If there were any errors, print them directly to console for diagnostics.
+ if len(ret) > 0 and ret[0] != None and 'error' in ret[0].lower() and not '0 error(s)' in ret[0].lower():
+ logging.error('Failed command: ' + ' '.join(cmd))
+ logging.error('Result:\n' + ret[0])
+ raise Exception('make failed!')
+ assert os.path.exists(tempdirname + '/' + cmake_outputs[i]), 'Building a cmake-generated Makefile failed to produce an output file %s!' % tempdirname + '/' + cmake_outputs[i]
+
+ # Run through node, if CMake produced a .js file.
+ if cmake_outputs[i].endswith('.js'):
+ ret = Popen(listify(NODE_JS) + [tempdirname + '/' + cmake_outputs[i]], stdout=PIPE).communicate()[0]
+ assert 'hello, world!' in ret, 'Running cmake-based .js application failed!'
+ finally:
+ os.chdir(path_from_root('tests')) # Move away from the directory we are about to remove.
+ shutil.rmtree(tempdirname)
def test_failure_error_code(self):
for compiler in [EMCC, EMXX]:
diff --git a/tests/utf32.cpp b/tests/utf32.cpp
new file mode 100644
index 00000000..6b75b244
--- /dev/null
+++ b/tests/utf32.cpp
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <string>
+#include <emscripten.h>
+#include <cassert>
+#include <wchar.h>
+
+typedef unsigned int utf32;
+typedef unsigned short utf16;
+
+// This code tests that Unicode std::wstrings can be marshalled between C++ and JS.
+int main() {
+ std::wstring wstr = L"abc\u2603\u20AC\U0002007C123 --- abc\u2603\u20AC\U0002007C123"; // U+2603 is snowman, U+20AC is the Euro sign, U+2007C is a Chinese Han character that looks like three raindrops.
+
+ printf("sizeof(wchar_t): %d.\n", (int)sizeof(wchar_t));
+
+ if (sizeof(wchar_t) == 4) {
+ utf32 *memory = new utf32[wstr.length()+1];
+
+ asm("var str = Module.UTF32ToString(%0);"
+ "Module.print(str);"
+ "Module.stringToUTF32(str, %1);"
+ :
+ : "r"(wstr.c_str()), "r"(memory));
+
+ // Compare memory to confirm that the string is intact after taking a route through JS side.
+ const utf32 *srcPtr = reinterpret_cast<const utf32 *>(wstr.c_str());
+ for(int i = 0;; ++i) {
+ assert(memory[i] == srcPtr[i]);
+ if (srcPtr[i] == 0)
+ break;
+ }
+ delete[] memory;
+ } else { // sizeof(wchar_t) == 2, and we're building with -fshort-wchar.
+ utf16 *memory = new utf16[2*wstr.length()+1];
+
+ asm("var str = Module.UTF16ToString(%0);"
+ "Module.print(str);"
+ "Module.stringToUTF16(str, %1);"
+ :
+ : "r"(wstr.c_str()), "r"(memory));
+
+ // Compare memory to confirm that the string is intact after taking a route through JS side.
+ const utf16 *srcPtr = reinterpret_cast<const utf16 *>(wstr.c_str());
+ for(int i = 0;; ++i) {
+ assert(memory[i] == srcPtr[i]);
+ if (srcPtr[i] == 0)
+ break;
+ }
+ delete[] memory;
+ }
+
+ printf("OK.\n");
+}
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 788a76ed..e567ebff 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -1728,6 +1728,15 @@ function getStackBumpSize(ast) {
function registerize(ast) {
traverseGeneratedFunctions(ast, function(fun) {
if (asm) var asmData = normalizeAsm(fun);
+ if (!asm) {
+ var hasFunction = false;
+ traverse(fun, function(node, type) {
+ if (type === 'function') hasFunction = true;
+ });
+ if (hasFunction) {
+ return; // inline assembly, and not asm (where we protect it in normalize/denormalize), so abort registerize pass
+ }
+ }
// Add parameters as a first (fake) var (with assignment), so they get taken into consideration
var params = {}; // note: params are special, they can never share a register between them (see later)
if (fun[2] && fun[2].length) {
@@ -3032,6 +3041,9 @@ function outline(ast) {
}
var ignore = [];
traverse(func, function(node) {
+ if (node[0] === 'while' && node[2][0] !== 'block') {
+ node[2] = ['block', [node[2]]]; // so we have a list of statements and can flatten while(1) switch
+ }
var stats = getStatements(node);
if (stats) {
for (var i = 0; i < stats.length; i++) {
@@ -3708,8 +3720,10 @@ function outline(ast) {
}
}
}
- ret.push(func);
- printErr('... resulting sizes of ' + func[1] + ' is ' + ret.map(measureSize) + '\n');
+ if (ret) {
+ ret.push(func);
+ printErr('... resulting sizes of ' + func[1] + ' is ' + ret.map(measureSize) + '\n');
+ }
}
denormalizeAsm(func, asmData);
});
diff --git a/tools/shared.py b/tools/shared.py
index 2e11d736..94daadae 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -546,15 +546,13 @@ def get_llvm_target():
return os.environ.get('EMCC_LLVM_TARGET') or 'le32-unknown-nacl' # 'i386-pc-linux-gnu'
LLVM_TARGET = get_llvm_target()
+# COMPILER_OPTS: options passed to clang when generating bitcode for us
try:
COMPILER_OPTS # Can be set in EM_CONFIG, optionally
except:
COMPILER_OPTS = []
-# Force a simple, standard target as much as possible: target 32-bit linux, and disable various flags that hint at other platforms
-COMPILER_OPTS = COMPILER_OPTS + ['-m32', '-U__i386__', '-U__i386', '-Ui386',
- '-U__SSE__', '-U__SSE_MATH__', '-U__SSE2__', '-U__SSE2_MATH__', '-U__MMX__',
- '-DEMSCRIPTEN', '-D__EMSCRIPTEN__', '-U__STRICT_ANSI__',
- '-D__IEEE_LITTLE_ENDIAN', '-fno-math-errno',
+COMPILER_OPTS = COMPILER_OPTS + ['-m32', '-DEMSCRIPTEN', '-D__EMSCRIPTEN__',
+ '-fno-math-errno',
#'-fno-threadsafe-statics', # disabled due to issue 1289
'-target', LLVM_TARGET]
@@ -562,6 +560,11 @@ if LLVM_TARGET == 'le32-unknown-nacl':
COMPILER_OPTS = filter(lambda opt: opt != '-m32', COMPILER_OPTS) # le32 target is 32-bit anyhow, no need for -m32
COMPILER_OPTS += ['-U__native_client__', '-U__pnacl__', '-U__ELF__'] # The nacl target is originally used for Google Native Client. Emscripten is not NaCl, so remove the platform #define, when using their triple.
+# Remove various platform specific defines, and set little endian
+COMPILER_STANDARDIZATION_OPTS = ['-U__i386__', '-U__i386', '-Ui386', '-U__STRICT_ANSI__', '-D__IEEE_LITTLE_ENDIAN',
+ '-U__SSE__', '-U__SSE_MATH__', '-U__SSE2__', '-U__SSE2_MATH__', '-U__MMX__',
+ '-U__APPLE__', '-U__linux__']
+
USE_EMSDK = not os.environ.get('EMMAKEN_NO_SDK')
if USE_EMSDK:
@@ -578,9 +581,8 @@ if USE_EMSDK:
'-Xclang', '-isystem' + path_from_root('system', 'include', 'gfx'),
'-Xclang', '-isystem' + path_from_root('system', 'include', 'net'),
'-Xclang', '-isystem' + path_from_root('system', 'include', 'SDL'),
- ] + [
- '-U__APPLE__', '-U__linux__'
]
+ EMSDK_OPTS += COMPILER_STANDARDIZATION_OPTS
if LLVM_TARGET != 'le32-unknown-nacl':
EMSDK_CXX_OPTS = ['-nostdinc++'] # le32 target does not need -nostdinc++
else:
@@ -589,6 +591,7 @@ if USE_EMSDK:
else:
EMSDK_OPTS = []
EMSDK_CXX_OPTS = []
+ COMPILER_OPTS += COMPILER_STANDARDIZATION_OPTS
#print >> sys.stderr, 'SDK opts', ' '.join(EMSDK_OPTS)
#print >> sys.stderr, 'Compiler opts', ' '.join(COMPILER_OPTS)
@@ -817,35 +820,52 @@ class Building:
env['EMSCRIPTEN'] = path_from_root()
return env
+ # Finds the given executable 'program' in PATH. Operates like the Unix tool 'which'.
+ @staticmethod
+ def which(program):
+ import os
+ def is_exe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+ fpath, fname = os.path.split(program)
+ if fpath:
+ if is_exe(program):
+ return program
+ else:
+ for path in os.environ["PATH"].split(os.pathsep):
+ path = path.strip('"')
+ exe_file = os.path.join(path, program)
+ if is_exe(exe_file):
+ return exe_file
+
+ if WINDOWS and not '.' in fname:
+ if is_exe(exe_file + '.exe'):
+ return exe_file + '.exe'
+ if is_exe(exe_file + '.cmd'):
+ return exe_file + '.cmd'
+ if is_exe(exe_file + '.bat'):
+ return exe_file + '.bat'
+
+ return None
+
@staticmethod
def handle_CMake_toolchain(args, env):
- CMakeToolchain = ('''# the name of the target operating system
-SET(CMAKE_SYSTEM_NAME Linux)
-
-# which C and C++ compiler to use
-SET(CMAKE_C_COMPILER %(winfix)s$EMSCRIPTEN_ROOT/emcc)
-SET(CMAKE_CXX_COMPILER %(winfix)s$EMSCRIPTEN_ROOT/em++)
-SET(CMAKE_AR %(winfix)s$EMSCRIPTEN_ROOT/emar)
-SET(CMAKE_RANLIB %(winfix)s$EMSCRIPTEN_ROOT/emranlib)
-SET(CMAKE_C_FLAGS $CFLAGS)
-SET(CMAKE_CXX_FLAGS $CXXFLAGS)
-
-# here is the target environment located
-SET(CMAKE_FIND_ROOT_PATH $EMSCRIPTEN_ROOT/system/include )
-
-# adjust the default behaviour of the FIND_XXX() commands:
-# search headers and libraries in the target environment, search
-# programs in the host environment
-set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
-set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS else 'python ' }) \
- .replace('$EMSCRIPTEN_ROOT', path_from_root('').replace('\\', '/')) \
- .replace('$CFLAGS', env['CFLAGS']) \
- .replace('$CXXFLAGS', env['CFLAGS'])
- toolchainFile = mkstemp(suffix='.cmaketoolchain.txt', dir=configuration.TEMP_DIR)[1]
- open(toolchainFile, 'w').write(CMakeToolchain)
- args.append('-DCMAKE_TOOLCHAIN_FILE=%s' % os.path.abspath(toolchainFile))
+
+ def has_substr(array, substr):
+ for arg in array:
+ if substr in arg:
+ return True
+ return False
+
+ # Append the Emscripten toolchain file if the user didn't specify one.
+ if not has_substr(args, '-DCMAKE_TOOLCHAIN_FILE'):
+ args.append('-DCMAKE_TOOLCHAIN_FILE=' + path_from_root('cmake', 'Platform', 'Emscripten.cmake'))
+
+ # On Windows specify MinGW Makefiles if we have MinGW and no other toolchain was specified, to avoid CMake
+ # pulling in a native Visual Studio, or Unix Makefiles.
+ if WINDOWS and not '-G' in args and Building.which('mingw32-make'):
+ args += ['-G', 'MinGW Makefiles']
+
return args
@staticmethod
@@ -876,6 +896,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
logging.error('Executable to run not specified.')
sys.exit(1)
#args += ['VERBOSE=1']
+
+ # On Windows prefer building with mingw32-make instead of make, if it exists.
+ if WINDOWS and args[0] == 'make':
+ mingw32_make = Building.which('mingw32-make')
+ if mingw32_make:
+ args[0] = mingw32_make
+
try:
process = Popen(args, stdout=stdout, stderr=stderr, env=env)
process.communicate()
@@ -916,13 +943,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
# except:
# pass
env = Building.get_building_env(native)
- log_to_file = os.getenv('EM_BUILD_VERBOSE') == None or int(os.getenv('EM_BUILD_VERBOSE')) == 0
+ verbose_level = int(os.getenv('EM_BUILD_VERBOSE')) if os.getenv('EM_BUILD_VERBOSE') != None else 0
for k, v in env_init.iteritems():
env[k] = v
if configure: # Useful in debugging sometimes to comment this out (and the lines below up to and including the |link| call)
try:
- Building.configure(configure + configure_args, env=env, stdout=open(os.path.join(project_dir, 'configure_'), 'w') if log_to_file else None,
- stderr=open(os.path.join(project_dir, 'configure_err'), 'w') if log_to_file else None)
+ Building.configure(configure + configure_args, env=env, stdout=open(os.path.join(project_dir, 'configure_'), 'w') if verbose_level < 2 else None,
+ stderr=open(os.path.join(project_dir, 'configure_err'), 'w') if verbose_level < 1 else None)
except subprocess.CalledProcessError, e:
pass # Ignore exit code != 0
def open_make_out(i, mode='r'):
@@ -930,13 +957,16 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
def open_make_err(i, mode='r'):
return open(os.path.join(project_dir, 'make_err' + str(i)), mode)
-
+
+ if verbose_level >= 3:
+ make_args += ['VERBOSE=1']
+
for i in range(2): # FIXME: Sad workaround for some build systems that need to be run twice to succeed (e.g. poppler)
with open_make_out(i, 'w') as make_out:
with open_make_err(i, 'w') as make_err:
try:
- Building.make(make + make_args, stdout=make_out if log_to_file else None,
- stderr=make_err if log_to_file else None, env=env)
+ Building.make(make + make_args, stdout=make_out if verbose_level < 2 else None,
+ stderr=make_err if verbose_level < 1 else None, env=env)
except subprocess.CalledProcessError, e:
pass # Ignore exit code != 0
try:
@@ -948,7 +978,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
break
except Exception, e:
if i > 0:
- if log_to_file:
+ if verbose_level == 0:
# Due to the ugly hack above our best guess is to output the first run
with open_make_err(0) as ferr:
for line in ferr:
diff --git a/tools/test-js-optimizer-asm-outline1-output.js b/tools/test-js-optimizer-asm-outline1-output.js
index 612da16a..27f93d8a 100644
--- a/tools/test-js-optimizer-asm-outline1-output.js
+++ b/tools/test-js-optimizer-asm-outline1-output.js
@@ -372,6 +372,57 @@ function switchh() {
}
STACKTOP = sp;
}
+function switchh2() {
+ var helper$0 = 0, helper$1 = 0, sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 280 | 0;
+ while (1) {
+ helper$0 = 1;
+ helper$1 = x;
+ if (helper$0) {
+ helper$0 = 0;
+ switch (helper$1 | 0) {
+ case 0:
+ f(0);
+ g();
+ break;
+ default:
+ {
+ helper$0 = 1;
+ }
+ }
+ }
+ HEAP32[sp + 8 >> 2] = helper$0;
+ HEAP32[sp + 16 >> 2] = helper$1;
+ HEAP32[sp + 40 >> 2] = 0;
+ HEAP32[sp + 44 >> 2] = 0;
+ switchh2$2(sp);
+ helper$0 = HEAP32[sp + 8 >> 2] | 0;
+ tempValue = HEAP32[sp + 40 >> 2] | 0;
+ tempInt = HEAP32[sp + 44 >> 2] | 0;
+ tempDouble = +HEAPF32[sp + 44 >> 2];
+ HEAP32[sp + 40 >> 2] = 0;
+ HEAP32[sp + 44 >> 2] = 0;
+ if ((tempValue | 0) == 5) {
+ STACKTOP = sp;
+ return;
+ }
+ HEAP32[sp + 8 >> 2] = helper$0;
+ HEAP32[sp + 16 >> 2] = helper$1;
+ HEAP32[sp + 32 >> 2] = 0;
+ HEAP32[sp + 36 >> 2] = 0;
+ switchh2$1(sp);
+ helper$0 = HEAP32[sp + 8 >> 2] | 0;
+ if (helper$0) {
+ helper$0 = 0;
+ HEAP32[sp + 16 >> 2] = helper$1;
+ HEAP32[sp + 24 >> 2] = 0;
+ HEAP32[sp + 28 >> 2] = 0;
+ switchh2$0(sp);
+ }
+ }
+ STACKTOP = sp;
+}
function lin$0(sp) {
sp = sp | 0;
c(14);
@@ -793,4 +844,86 @@ function switchh$2(sp) {
} while (0);
HEAP32[sp + 8 >> 2] = helper$0;
}
+function switchh2$0(sp) {
+ sp = sp | 0;
+ var helper$1 = 0;
+ helper$1 = HEAP32[sp + 16 >> 2] | 0;
+ switch (helper$1 | 0) {
+ case 4:
+ f(4);
+ g();
+ case 5:
+ f(5);
+ g();
+ case 6:
+ f(6);
+ g();
+ default:
+ print(9);
+ }
+}
+function switchh2$1(sp) {
+ sp = sp | 0;
+ var helper$0 = 0, helper$1 = 0;
+ helper$0 = HEAP32[sp + 8 >> 2] | 0;
+ helper$1 = HEAP32[sp + 16 >> 2] | 0;
+ if (helper$0) {
+ helper$0 = 0;
+ switch (helper$1 | 0) {
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 3:
+ f(3);
+ g();
+ break;
+ default:
+ {
+ helper$0 = 1;
+ }
+ }
+ }
+ HEAP32[sp + 8 >> 2] = helper$0;
+}
+function switchh2$2(sp) {
+ sp = sp | 0;
+ var helper$0 = 0, helper$1 = 0;
+ helper$0 = HEAP32[sp + 8 >> 2] | 0;
+ helper$1 = HEAP32[sp + 16 >> 2] | 0;
+ OL : do {
+ if (helper$0) {
+ helper$0 = 0;
+ switch (helper$1 | 0) {
+ case 1:
+ f(1);
+ g();
+ return;
+ default:
+ {
+ helper$0 = 1;
+ }
+ }
+ }
+ if (helper$0) {
+ helper$0 = 0;
+ switch (helper$1 | 0) {
+ case 2:
+ f(2);
+ g();
+ break;
+ default:
+ {
+ helper$0 = 1;
+ }
+ }
+ }
+ } while (0);
+ HEAP32[sp + 8 >> 2] = helper$0;
+}
diff --git a/tools/test-js-optimizer-asm-outline1.js b/tools/test-js-optimizer-asm-outline1.js
index 4282ec8e..b7ec9011 100644
--- a/tools/test-js-optimizer-asm-outline1.js
+++ b/tools/test-js-optimizer-asm-outline1.js
@@ -307,5 +307,45 @@ function switchh() {
}
}
}
+function switchh2() {
+ while (1) switch (x) {
+ case 0:
+ f(0);
+ g();
+ break;
+ case 1:
+ f(1);
+ g();
+ return;
+ case 2:
+ f(2);
+ g();
+ break;
+ case 21: // gotta keem em unseparated
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 3: // these too
+ f(3);
+ g();
+ break;
+ case 4:
+ f(4);
+ g();
+ case 5:
+ f(5);
+ g();
+ case 6:
+ f(6);
+ g();
+ default:
+ print(9);
+ }
+}
// EMSCRIPTEN_GENERATED_FUNCTIONS
// EXTRA_INFO: { "sizeToOutline": 30, "allowCostlyOutlines": 1 }
diff --git a/tools/test-js-optimizer-regs-output.js b/tools/test-js-optimizer-regs-output.js
index 149ca984..6f67bcec 100644
--- a/tools/test-js-optimizer-regs-output.js
+++ b/tools/test-js-optimizer-regs-output.js
@@ -175,19 +175,19 @@ function fcntl_open() {
return null;
}
function ex() {
- var r1, r2;
- r1 = STACKTOP;
+ var __stackBase__ = STACKTOP;
STACKTOP += 4;
- r2 = r1;
- r1 = _puts(STRING_TABLE._str17 | 0);
- r1 = r2 | 0;
- r2 = 0;
+ var $e1 = __stackBase__;
+ var $puts = _puts(STRING_TABLE._str17 | 0);
+ var $x41 = $e1 | 0;
+ var $i_04 = 0;
while (1) {
- r1 = _printf(STRING_TABLE.__str15 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r2, tempInt));
+ var $i_04;
+ var $call1 = _printf(STRING_TABLE.__str15 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $i_04, tempInt));
((function() {
try {
__THREW__ = false;
- return __Z5magici(r2);
+ return __Z5magici($i_04);
} catch (e) {
if (typeof e != "number") throw e;
if (ABORT) throw e;
diff --git a/tools/test-js-optimizer-regs.js b/tools/test-js-optimizer-regs.js
index 00303786..bc0ebb5a 100644
--- a/tools/test-js-optimizer-regs.js
+++ b/tools/test-js-optimizer-regs.js
@@ -190,7 +190,7 @@ function ex() {
while (1) {
var $i_04;
var $call1 = _printf(STRING_TABLE.__str15 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $i_04, tempInt));
- ((function() {
+ ((function() { // prevents registerize, looks like inline asm
try {
__THREW__ = false;
return __Z5magici($i_04);
diff --git a/tools/validate_asmjs.py b/tools/validate_asmjs.py
new file mode 100644
index 00000000..ea909fbd
--- /dev/null
+++ b/tools/validate_asmjs.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+
+# This is a helper script to validate a file for asm.js.
+
+# cmdline usage: 'python validate_asmjs.py filename.{html/js}'
+# Prints a line starting with 'OK: ' on success, and returns process exit code 0.
+# On failure, prints a line starting with 'FAIL: ', and returns a nonzero process exit code.
+
+# python usage: 'validate_asmjs("filename.{html/js}", muteOutput=True/False)'
+# Returns True/False depending on whether the file was valid asm.js.
+
+# This script depends on the SpiderMonkey JS engine, which must be present in PATH in order for this script to function.
+
+import subprocess, sys, re, tempfile, os, time
+import shared
+
+# Looks up SpiderMonkey engine using the variable SPIDERMONKEY_ENGINE in ~/.emscripten, and if not set up there, via PATH.
+def find_spidermonkey_engine():
+ sm_engine = shared.SPIDERMONKEY_ENGINE if hasattr(shared, 'SPIDERMONKEY_ENGINE') else ['']
+ if not sm_engine or len(sm_engine[0]) == 0 or not os.path.exists(sm_engine[0]):
+ sm_engine[0] = shared.Building.which('js')
+ if sm_engine[0] == None:
+ return ['js-not-found']
+ return sm_engine
+
+# Given a .js file, returns True/False depending on if that file is valid asm.js
+def validate_asmjs_jsfile(filename, muteOutput):
+ process = subprocess.Popen(find_spidermonkey_engine() + ['-c', filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
+ (stdout, stderr) = process.communicate()
+ if not muteOutput:
+ if len(stdout.strip()) > 0:
+ print stdout.strip()
+ if len(stderr.strip()) > 0:
+ # Pretty-print the output not to contain a spurious warning.
+ stderr = stderr.replace('warning: successfully compiled asm.js', ' successfully compiled asm.js')
+
+ print >> sys.stderr, stderr.strip()
+ if 'successfully compiled asm.js' in stderr:
+ return True
+ else:
+ return False
+
+# This tool takes as input a file built with Emscripten (either .html or .js) and validates it for asm.js.
+# Returns True/False denoting whether the file was valid asm.js. In case of a .html file, all <script>content</script> tags are searched,
+# and the ones containing a "use asm" section are validated.
+def validate_asmjs(filename, muteOutput):
+ if filename.endswith('.html'):
+ html = open(filename, 'r').read()
+ matches = re.findall('''<\w*script\w*.*?>(.*?)<\w*/script\w*>''', html, re.DOTALL | re.MULTILINE)
+ numAsmJsBlocks = 0
+ for match in matches:
+ if '"use asm"' in match:
+ numAsmJsBlocks = numAsmJsBlocks + 1
+ tmp_js = tempfile.mkstemp(suffix='.js')
+ os.write(tmp_js[0], match)
+ os.close(tmp_js[0])
+ valid_asmjs = validate_asmjs_jsfile(tmp_js[1], muteOutput)
+ os.remove(tmp_js[1])
+ if not valid_asmjs:
+ return False
+ if numAsmJsBlocks == 0:
+ if not muteOutput:
+ print >> sys.stderr, 'Error: the file does not contain any "use asm" modules.'
+ return False
+ else:
+ return True
+ else:
+ return validate_asmjs_jsfile(filename, muteOutput)
+
+def main():
+ if len(sys.argv) < 2:
+ print 'Usage: validate_asmjs <filename>'
+ return 2
+ if validate_asmjs(sys.argv[1], muteOutput=False):
+ print "OK: File '" + sys.argv[1] + "' validates as asm.js"
+ return 0
+ else:
+ print "FAIL: File '" + sys.argv[1] + "' is not valid asm.js"
+ return 1
+
+if __name__ == '__main__':
+ sys.exit(main())