diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/file_packager.py | 7 | ||||
-rw-r--r-- | tools/js-optimizer.js | 39 | ||||
-rw-r--r-- | tools/settings_template_readonly.py | 10 | ||||
-rw-r--r-- | tools/shared.py | 50 | ||||
-rwxr-xr-x | tools/split.py | 94 |
5 files changed, 168 insertions, 32 deletions
diff --git a/tools/file_packager.py b/tools/file_packager.py index e5a9025d..a764b746 100644 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -13,8 +13,6 @@ Usage: file_packager.py TARGET [--preload A [B..]] [--embed C [D..]] [--compress COMPRESSION_DATA] [--pre-run] [--crunch[=X]] -Notes: - --pre-run Will generate wrapper code that does preloading in Module.preRun. This is necessary if you add this code before the main file has been loading, which includes necessary components like addRunDependency. @@ -26,6 +24,11 @@ Notes: DDS files will not be crunched if the .crn is more recent than the .dds. This prevents a lot of unneeded computation. +Notes: + + * The file packager generates unix-style file paths. So if you are on windows and a file is accessed at + subdir\file, in JS it will be subdir/file. For simplicity we treat the web platform as a *NIX. + TODO: You can also provide .crn files yourself, pre-crunched. With this option, they will be decompressed to dds files in the browser, exactly the same as if this tool compressed them. ''' diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index e1cfbe65..5dac36f0 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -26,15 +26,30 @@ if (ENVIRONMENT_IS_NODE) { var nodeFS = require('fs'); var nodePath = require('path'); - read = function(filename) { - filename = nodePath['normalize'](filename); - var ret = nodeFS['readFileSync'](filename).toString(); - // The path is absolute if the normalized version is the same as the resolved. - if (!ret && filename != nodePath['resolve'](filename)) { - filename = path.join(__dirname, '..', 'src', filename); - ret = nodeFS['readFileSync'](filename).toString(); + if (!nodeFS.existsSync) { + nodeFS.existsSync = function(path) { + try { + return !!nodeFS.readFileSync(path); + } catch(e) { + return false; + } + } + } + + function find(filename) { + var prefixes = [nodePath.join(__dirname, '..', 'src'), process.cwd()]; + for (var i = 0; i < prefixes.length; ++i) { + var combined = nodePath.join(prefixes[i], filename); + if (nodeFS.existsSync(combined)) { + return combined; + } } - return ret; + return filename; + } + + read = function(filename) { + var absolute = find(filename); + return nodeFS['readFileSync'](absolute).toString(); }; load = function(f) { @@ -98,14 +113,6 @@ if (typeof print === 'undefined') { } // *** Environment setup code *** -// Fix read for our location -read = function(filename) { - // The path is absolute if the normalized version is the same as the resolved. - filename = path.normalize(filename); - if (filename != path.resolve(filename)) filename = path.join(__dirname, '..', 'src', filename); - return fs.readFileSync(filename).toString(); -} - var uglify = require('../tools/eliminator/node_modules/uglify-js'); var fs = require('fs'); var path = require('path'); diff --git a/tools/settings_template_readonly.py b/tools/settings_template_readonly.py index 45a30569..9102fe40 100644 --- a/tools/settings_template_readonly.py +++ b/tools/settings_template_readonly.py @@ -1,15 +1,15 @@ -# This file will be copied to ~/.emscripten if that file doesn't exist. Or, this is that copy. -# IMPORTANT: Edit the *copy* with the right paths! +# This file will be edited (the {{{ }}} things), and then ~/.emscripten created with the result, if ~/.emscripten doesn't exist. + # Note: If you put paths relative to the home directory, do not forget os.path.expanduser import os # this helps projects using emscripten find it -EMSCRIPTEN_ROOT = os.path.expanduser(os.getenv('EMSCRIPTEN') or '/opt/emscripten') -LLVM_ROOT = os.path.expanduser(os.getenv('LLVM') or '/usr/bin') +EMSCRIPTEN_ROOT = os.path.expanduser(os.getenv('EMSCRIPTEN') or '{{{ EMSCRIPTEN_ROOT }}}') +LLVM_ROOT = os.path.expanduser(os.getenv('LLVM') or '{{{ LLVM_ROOT }}}') # See below for notes on which JS engine(s) you need -NODE_JS = 'node' +NODE_JS = '{{{ NODE }}}' SPIDERMONKEY_ENGINE = [ os.path.expanduser(os.getenv('SPIDERMONKEY') or 'js'), '-m', '-n'] V8_ENGINE = os.path.expanduser(os.getenv('V8') or 'd8') diff --git a/tools/shared.py b/tools/shared.py index 700849e8..bdfec8ed 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -20,7 +20,26 @@ if '\n' in EM_CONFIG: else: CONFIG_FILE = os.path.expanduser(EM_CONFIG) if not os.path.exists(CONFIG_FILE): - shutil.copy(path_from_root('tools', 'settings_template_readonly.py'), CONFIG_FILE) + config_file = open(path_from_root('tools', 'settings_template_readonly.py')).read().split('\n') + config_file = config_file[1:] # remove "this file will be copied..." + config_file = '\n'.join(config_file) + # autodetect some default paths + config_file = config_file.replace('{{{ EMSCRIPTEN_ROOT }}}', __rootpath__) + llvm_root = '/usr/bin' + try: + llvm_root = os.path.dirname(Popen(['which', 'clang'], stdout=PIPE).communicate()[0].replace('\n', '')) + except: + pass + config_file = config_file.replace('{{{ LLVM_ROOT }}}', llvm_root) + node = 'node' + try: + node = Popen(['which', 'node'], stdout=PIPE).communicate()[0].replace('\n', '') + except: + pass + config_file = config_file.replace('{{{ NODE }}}', node) + + # write + open(CONFIG_FILE, 'w').write(config_file) print >> sys.stderr, ''' ============================================================================== Welcome to Emscripten! @@ -29,12 +48,17 @@ This is the first time any of the Emscripten tools has been run. A settings file has been copied to %s, at absolute path: %s -Please edit that file and change the paths to fit your system. Specifically, -make sure LLVM_ROOT and NODE_JS are correct. +It contains our best guesses for the important paths, which are: + + LLVM_ROOT = %s + NODE_JS = %s + EMSCRIPTEN_ROOT = %s + +Please edit the file if any of those are incorrect. This command will now exit. When you are done editing those paths, re-run it. ============================================================================== -''' % (EM_CONFIG, CONFIG_FILE) +''' % (EM_CONFIG, CONFIG_FILE, llvm_root, node, __rootpath__) sys.exit(0) try: config_text = open(CONFIG_FILE, 'r').read() if CONFIG_FILE else EM_CONFIG @@ -47,12 +71,19 @@ except Exception, e: EXPECTED_LLVM_VERSION = (3,1) +def check_clang_version(): + expected = 'clang version ' + '.'.join(map(str, EXPECTED_LLVM_VERSION)) + actual = Popen([CLANG, '-v'], stderr=PIPE).communicate()[1].split('\n')[0] + if expected in actual: + return True + + print >> sys.stderr, 'warning: LLVM version appears incorrect (seeing "%s", expected "%s")' % (actual, expected) + return False + + def check_llvm_version(): try: - expected = 'clang version ' + '.'.join(map(str, EXPECTED_LLVM_VERSION)) - actual = Popen([CLANG, '-v'], stderr=PIPE).communicate()[1].split('\n')[0][0:len(expected)] - if expected != actual: - print >> sys.stderr, 'warning: LLVM version appears incorrect (seeing "%s", expected "%s")' % (actual, expected) + check_clang_version(); except Exception, e: print >> sys.stderr, 'warning: Could not verify LLVM version: %s' % str(e) @@ -240,7 +271,8 @@ if USE_EMSDK: '-Xclang', '-isystem' + path_from_root('system', 'include', 'net'), '-Xclang', '-isystem' + path_from_root('system', 'include', 'SDL'), ] + [ - '-U__APPLE__', '-U__linux__' + '-U__APPLE__', '-U__linux__', + '-D_LIBCPP_HAS_NO_DELETED_FUNCTIONS' # otherwise libc++ has errors with --std=c++11 ] COMPILER_OPTS += EMSDK_OPTS else: diff --git a/tools/split.py b/tools/split.py new file mode 100755 index 00000000..ab1e97ca --- /dev/null +++ b/tools/split.py @@ -0,0 +1,94 @@ +import sys +import os + +def split_javascript_file(input_filename, output_filename_prefix, max_part_size_in_bytes): + + try: + # Contains the entire Emscripten generated Javascript code + input_file = open(input_filename,'r') + + # Javascript main file. On execution, this file needs to be loaded at last (!) + output_main_filename = output_filename_prefix + ".js" + output_main_file = open(output_main_filename,'w') + + # File with HTML script tags to load the Javascript files in HTML later on + output_html_include_file = open(output_filename_prefix + ".include.html",'w') + + # Variable will contain the source of a Javascript function if we find one during parsing + js_function = None + + # Dictionary with source file as key and an array of functions associated to that source file as value + function_buckets = {}; + + output_part_file = None + + # Iterate over Javascript source; write main file; parse function declarations. + for line in input_file: + if line == "//FUNCTION_BEGIN_MARKER\n": + js_function = "//Func\n" + elif line.startswith("//FUNCTION_END_MARKER_OF_SOURCE_FILE_"): + # At the end of the function marker we get the source file that is associated to that function. + associated_source_file_base = line[len("//FUNCTION_END_MARKER_OF_SOURCE_FILE_"):len(line)-1] + + if associated_source_file_base == "NO_SOURCE": + # Functions without associated source file are stored in a file in the base directory + associated_source_file_base = output_filename_prefix + "_functions"; + else: + # Functions with a known associated source file are stored in a file in the directory `output_filename_prefix` + associated_source_file_base = output_filename_prefix + os.path.realpath(associated_source_file_base) + + # Add the function to its respective file + if associated_source_file_base not in function_buckets: + function_buckets[associated_source_file_base] = [] + function_buckets[associated_source_file_base] += [js_function] + + # Clear the function read cache + js_function = None + else: + if js_function is None: + output_main_file.write(line) + else: + js_function += line + + # Iterate over all function buckets and write their functions to the associated files + # An associated file is split into chunks of `max_part_size_in_bytes` + for associated_source_file_base in function_buckets: + # At first we try to name the Javascript source file to match the assoicated source file + `.js` + js_source_file = associated_source_file_base + ".js" + + # Check if the directory of the Javascript source file exists + js_source_dir = os.path.dirname(js_source_file) + if len(js_source_dir) > 0 and not os.path.exists(js_source_dir): + os.makedirs(js_source_dir) + + output_part_file_counter = 0 + output_part_file = None + for js_function in function_buckets[associated_source_file_base]: + if output_part_file is None: + output_html_include_file.write("<script type=\"text/javascript\" src=\"" + js_source_file + "\"></script>") + output_part_file = open(js_source_file,'w') + + output_part_file.write(js_function) + + if output_part_file is not None and output_part_file.tell() > max_part_size_in_bytes: + output_part_file.close() + output_part_file = None + output_part_file_counter += 1 + js_source_file = associated_source_file_base + ".part" + str(output_part_file_counter) + ".js" + + if output_part_file is not None: + output_part_file.close() + output_part_file = None + + # Write the main Javascript file at last to the HTML includes because this file contains the code to start + # the execution of the generated Emscripten application and requires all the extracted functions. + output_html_include_file.write("<script type=\"text/javascript\" src=\"" + output_main_filename + "\"></script>") + + except Exception, e: + print >> sys.stderr, 'error: Splitting of Emscripten generated Javascript failed: %s' % str(e) + + finally: + if input_file is not None: input_file.close() + if output_main_file is not None: output_main_file.close() + if output_part_file is not None: output_part_file.close() + if output_html_include_file is not None: output_html_include_file.close()
\ No newline at end of file |