diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-01-26 19:23:13 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-01-26 19:25:17 -0800 |
commit | a5243b43651a44df897537f1ee4b45f4a7c6350e (patch) | |
tree | a591deeaada221d022e5893e874caf34e8c15317 | |
parent | a7c5795f3219450afe328d9da1445e661bd523db (diff) |
support precompiled headers; fixes #2045
-rwxr-xr-x | emcc | 34 | ||||
-rw-r--r-- | tests/test_other.py | 19 |
2 files changed, 37 insertions, 16 deletions
@@ -61,6 +61,7 @@ BITCODE_ENDINGS = ('.bc', '.o', '.obj') DYNAMICLIB_ENDINGS = ('.dylib', '.so', '.dll') STATICLIB_ENDINGS = ('.a',) ASSEMBLY_ENDINGS = ('.ll',) +HEADER_ENDINGS = ('.h', '.hxx', '.hpp', '.hh', '.H', '.HXX', '.HPP', '.HH') LIB_PREFIXES = ('', 'lib') @@ -695,15 +696,12 @@ if len(sys.argv) == 1 or sys.argv[1] in ['x', 't']: sys.exit(0) use_cxx = True -header = False # pre-compiled headers. We fake that by just copying the file for i in range(1, len(sys.argv)): arg = sys.argv[i] if not arg.startswith('-'): if arg.endswith(('.c','.m')): use_cxx = False - if arg.endswith('.h') and sys.argv[i-1] != '-include': - header = True if '-M' in sys.argv or '-MM' in sys.argv: # Just output dependencies, do not compile. Warning: clang and gcc behave differently with -MF! (clang seems to not recognize it) @@ -737,15 +735,6 @@ if '.' in target: else: final_suffix = '' -if header: # header or such - if len(sys.argv) >= 3: # if there is a source and a target, then copy, otherwise do nothing - sys.argv = filter(lambda arg: not arg.startswith('-I'), sys.argv) - logging.debug('Just copy:' + sys.argv[-1] + target) - shutil.copy(sys.argv[-1], target) - else: - logging.debug('No-op.') - exit(0) - if TEMP_DIR: temp_dir = TEMP_DIR if os.path.exists(temp_dir): @@ -1062,6 +1051,7 @@ try: input_files = [] has_source_inputs = False + has_header_inputs = False lib_dirs = [shared.path_from_root('system', 'local', 'lib'), shared.path_from_root('system', 'lib')] libs = [] @@ -1073,7 +1063,7 @@ try: prev = newargs[i-1] if prev in ['-MT', '-MF', '-MQ', '-D', '-U', '-o', '-x', '-Xpreprocessor', '-include', '-imacros', '-idirafter', '-iprefix', '-iwithprefix', '-iwithprefixbefore', '-isysroot', '-imultilib', '-A', '-isystem', '-iquote', '-install_name', '-compatibility_version', '-current_version', '-I', '-L']: continue # ignore this gcc-style argument - if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS)): + if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS)): arg = os.path.realpath(arg) if not arg.startswith('-'): @@ -1082,11 +1072,14 @@ try: exit(1) arg_ending = filename_type_ending(arg) - if arg_ending.endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs + if arg_ending.endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs newargs[i] = '' if arg_ending.endswith(SOURCE_ENDINGS): input_files.append(arg) has_source_inputs = True + elif arg_ending.endswith(HEADER_ENDINGS): + input_files.append(arg) + has_header_inputs = True elif arg_ending.endswith(ASSEMBLY_ENDINGS) or shared.Building.is_bitcode(arg): # this should be bitcode, make sure it is valid input_files.append(arg) elif arg_ending.endswith(STATICLIB_ENDINGS + DYNAMICLIB_ENDINGS): @@ -1125,7 +1118,7 @@ try: # -c means do not link in gcc, and for us, the parallel is to not go all the way to JS, but stop at bitcode has_dash_c = '-c' in newargs if has_dash_c: - assert has_source_inputs, 'Must have source code inputs to use -c' + assert has_source_inputs or has_header_inputs, 'Must have source code or header inputs to use -c' target = target_basename + '.o' final_suffix = 'o' @@ -1159,7 +1152,7 @@ try: input_files = filter(lambda input_file: check(input_file), input_files) if len(input_files) == 0: - logging.error('no input files\nnote that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + STATICLIB_ENDINGS + ASSEMBLY_ENDINGS)) + logging.error('no input files\nnote that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + STATICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS)) exit(0) newargs = CC_ADDITIONAL_ARGS + newargs @@ -1299,6 +1292,15 @@ try: log_time('parse arguments and setup') + # Precompiled headers support + if has_header_inputs: + for header in input_files: + assert header.endswith(HEADER_ENDINGS), 'if you have one header input, we assume you want to precompile headers, and cannot have source files or other inputs as well: ' + str(input_files) + ' : ' + header + args = newargs + shared.EMSDK_CXX_OPTS + input_files + logging.debug("running (for precompiled headers: " + call + ' ' + ' '.join(args)) + execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that) + sys.exit(1) + # 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) diff --git a/tests/test_other.py b/tests/test_other.py index 8895a911..74507c21 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -2324,3 +2324,22 @@ var Module = { print: function(x) { throw '<{(' + x + ')}>' } }; output = run_js(os.path.join(self.get_dir(), 'a.out.js'), stderr=PIPE, full_output=True, engine=NODE_JS) assert r'<{(123456789)}>' in output, output + def test_precompiled_headers(self): + self.clear() + + open('header.h', 'w').write('#define X 5\n') + Popen([PYTHON, EMCC, '-xc++-header', 'header.h', '-c']).communicate() + assert os.path.exists('header.h.gch') + + open('src.cpp', 'w').write(r''' +#include <stdio.h> +int main() { + printf("|%d|\n", X); + return 0; +} +''') + Popen([PYTHON, EMCC, 'src.cpp', '-include', 'header.h']).communicate() + + output = run_js(self.in_dir('a.out.js'), stderr=PIPE, full_output=True, engine=NODE_JS) + assert '|5|' in output, output + |