diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-03-25 17:55:34 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-03-25 17:55:34 -0700 |
commit | 78d5d9c1e1db669839cd17a0df01b69af67539f6 (patch) | |
tree | b9bc79913b512b37904f0748fe6730783b9d1387 | |
parent | 135a906d9996bd93e3aa6764943a754dd3668651 (diff) |
let emcc directly access bitcode files when possible, to emit proper .d files and avoid unnecessary copies
-rwxr-xr-x | emcc | 23 | ||||
-rw-r--r-- | tests/test_other.py | 17 | ||||
-rw-r--r-- | tools/shared.py | 33 |
3 files changed, 21 insertions, 52 deletions
@@ -50,7 +50,7 @@ emcc can be influenced by a few environment variables: import os, sys, shutil, tempfile, subprocess, shlex, time, re, logging from subprocess import PIPE from tools import shared, jsrun, system_libs -from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename, WINDOWS +from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename, WINDOWS, safe_move from tools.response_file import read_response_file # endings = dot + a suffix, safe to test by filename.endswith(endings) @@ -1352,13 +1352,22 @@ try: execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that) sys.exit(1) + def get_bitcode_file(input_file): + if final_suffix == 'o': + # no need for a temp file, just emit to the right place + if len(input_files) == 1: + # can just emit directly to the target + if specified_target: return specified_target + return unsuffixed(input_file) + '.' + final_suffix + return unsuffixed(input_file) + '.o' + return in_temp(unsuffixed(uniquename(input_file)) + '.o') + # First, generate LLVM bitcode. For each input file, we get base.o with bitcode for input_file in input_files: file_ending = filename_type_ending(input_file) if file_ending.endswith(SOURCE_ENDINGS): logging.debug('compiling source file: ' + input_file) - input_file = shared.Building.preprocess(input_file, in_temp(uniquename(input_file))) - output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o') + output_file = get_bitcode_file(input_file) temp_files.append(output_file) args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file] if file_ending.endswith(CXX_ENDINGS): @@ -1410,20 +1419,20 @@ try: if final_suffix not in JS_CONTAINING_SUFFIXES: if not specified_target: for input_file in input_files: - shutil.move(in_temp(unsuffixed(uniquename(input_file)) + '.o'), unsuffixed_basename(input_file) + '.' + final_suffix) + safe_move(get_bitcode_file(input_file), unsuffixed_basename(input_file) + '.' + final_suffix) else: if len(input_files) == 1: - temp_output_base = in_temp(unsuffixed(uniquename(input_files[0]))) + temp_output_base = unsuffixed(get_bitcode_file(input_files[0])) if specified_target.endswith('/') or specified_target.endswith('\\') or os.path.isdir(specified_target): # User passed '-o <directory' as the location to output to. obj_output_name = os.path.join(specified_target, os.path.splitext(os.path.basename(input_file))[0] + default_object_extension) logging.debug('User specified -o <directoryname> as the location of the output. Generating output file ' + obj_output_name) try: - shutil.move(temp_output_base + '.o', obj_output_name) + safe_move(temp_output_base + '.o', obj_output_name) except IOError, e: logging.error('Could not write to output file ' + obj_output_name + '. Perhaps the output directory does not exist?') exit(1) else: # User passed '-o <filename>' as the location to output to. - shutil.move(temp_output_base + '.o', specified_target) + safe_move(temp_output_base + '.o', specified_target) if os.path.exists(temp_output_base + '.d'): # There was a .d file generated, from -MD or -MMD and friends, save a copy of it to where the output resides, # adjusting the target name away from the temporary file name to the specified target. diff --git a/tests/test_other.py b/tests/test_other.py index 9146888c..93cd9796 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -1978,23 +1978,6 @@ seeked= file. code = open('a.out.js').read() assert 'SAFE_HEAP' in code, 'valid -s option had an effect' - def test_jcache_printf(self): - open(self.in_dir('src.cpp'), 'w').write(r''' - #include <stdio.h> - #include <stdint.h> - #include <emscripten.h> - int main() { - emscripten_jcache_printf("hello world\n"); - emscripten_jcache_printf("hello %d world\n", 5); - emscripten_jcache_printf("hello %.3f world\n", 123.456789123); - emscripten_jcache_printf("hello %llx world\n", 0x1234567811223344ULL); - return 0; - } - ''') - Popen([PYTHON, EMCC, self.in_dir('src.cpp')]).communicate() - output = run_js('a.out.js') - self.assertIdentical('hello world\nhello 5 world\nhello 123.457 world\nhello 1234567811223300 world\n', output) - def test_conftest_s_flag_passing(self): open(os.path.join(self.get_dir(), 'conftest.c'), 'w').write(r''' int main() { diff --git a/tools/shared.py b/tools/shared.py index 1adbdfaa..ac4b42ea 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1585,34 +1585,6 @@ class Building: import gen_struct_info gen_struct_info.main(['-qo', info_path, path_from_root('src/struct_info.json')]) - @staticmethod - def preprocess(infile, outfile): - ''' - Preprocess source C/C++ in some special ways that emscripten needs. Returns - a filename (potentially the same one if nothing was changed). - - Currently this only does emscripten_jcache_printf(..) rewriting. - ''' - src = open(infile).read() # stack warning on jcacheprintf! in docs # add jcache printf test separatrely, for content of printf - if 'emscripten_jcache_printf' not in src: return infile - def fix(m): - text = m.groups(0)[0] - assert text.count('(') == 1 and text.count(')') == 1, 'must have simple expressions in emscripten_jcache_printf calls, no parens' - assert text.count('"') == 2, 'must have simple expressions in emscripten_jcache_printf calls, no strings as varargs parameters' - if os.environ.get('EMCC_FAST_COMPILER') != '0': # fake it in fastcomp - return text.replace('emscripten_jcache_printf', 'printf') - start = text.index('(') - end = text.rindex(')') - args = text[start+1:end].split(',') - args = map(lambda x: x.strip(), args) - if args[0][0] == '"': - # flatten out - args = map(lambda x: str(ord(x)), args[0][1:len(args[0])-1]) + ['0'] + args[1:] - return 'emscripten_jcache_printf_(' + ','.join(args) + ')' - src = re.sub(r'(emscripten_jcache_printf\([^)]+\))', lambda m: fix(m), src) - open(outfile, 'w').write(src) - return outfile - # compatibility with existing emcc, etc. scripts Cache = cache.Cache(debug=DEBUG_CACHE) JCache = cache.JCache(Cache) @@ -1821,5 +1793,10 @@ def unsuffixed(name): def unsuffixed_basename(name): return os.path.basename(unsuffixed(name)) +def safe_move(src, dst): + if os.path.abspath(src) == os.path.abspath(dst): + return + shutil.move(src, dst) + import js_optimizer |