diff options
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) @@ -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 Binary files differnew file mode 100644 index 00000000..cc96acfd --- /dev/null +++ b/tests/sdl_canvas_proxy.png 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()) |