diff options
-rwxr-xr-x | emcc | 10 | ||||
-rw-r--r-- | src/runtime.js | 3 | ||||
-rw-r--r-- | tests/runner.py | 53 | ||||
-rw-r--r-- | tools/shared.py | 10 |
4 files changed, 61 insertions, 15 deletions
@@ -284,7 +284,7 @@ try: if closure is None: closure = 1 if opt_level >= 2 else 0 if closure: - assert os.path.exists(shared.CLOSURE_COMPILER), 'emcc: fatal: Closure compiler (%s) does not exist' % CLOSURE_COMPILER + assert os.path.exists(shared.CLOSURE_COMPILER), 'emcc: fatal: Closure compiler (%s) does not exist' % shared.CLOSURE_COMPILER settings_changes = [] for i in range(len(newargs)): @@ -363,9 +363,13 @@ try: # First, generate LLVM bitcode. For each input file, we get base.o with bitcode for input_file in input_files: if input_file.endswith(SOURCE_SUFFIXES): - args = newargs + ['-emit-llvm', '-c', input_file, '-o', in_temp(unsuffixed_basename(input_file) + '.o')] + output_file = in_temp(unsuffixed_basename(input_file) + '.o') + args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file] if DEBUG: print >> sys.stderr, "emcc running:", call, ' '.join(args) - Popen([call] + args).communicate() + Popen([call] + args).communicate() # let compiler frontend print directly, so colors are saved (PIPE kills that) + if not os.path.exists(output_file): + print >> sys.stderr, 'emcc: compiler frontend failed to generate LLVM bitcode, halting' + sys.exit(1) else: # bitcode if input_file.endswith(('.bc', '.o')): shutil.copyfile(input_file, in_temp(unsuffixed_basename(input_file) + '.o')) diff --git a/src/runtime.js b/src/runtime.js index e1a6db39..39f522a7 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -9,9 +9,6 @@ var RuntimeGenerator = { alloc: function(size, type, init) { var ret = type + 'TOP'; - if (ASSERTIONS) { - ret += '; assert(' + size + ' != 0, "Trying to allocate 0")'; - } if (init) { ret += '; _memset(' + type + 'TOP, 0, ' + size + ')'; } diff --git a/tests/runner.py b/tests/runner.py index f4cfe312..a2073af1 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -4925,6 +4925,19 @@ Options that are modified or new in %s include: assert os.path.exists('a.out.js'), '\n'.join(output) self.assertContained('hello, world!', run_js('a.out.js')) + # properly report source code errors, and stop there + clear() + assert not os.path.exists('a.out.js') + output = Popen([compiler, path_from_root('tests', 'hello_world_error' + suffix)], stdout=PIPE, stderr=PIPE).communicate() + assert not os.path.exists('a.out.js'), 'compilation failed, so no output file is expected' + assert len(output[0]) == 0, output[0] + self.assertNotContained('IOError', output[1]) # no python stack + self.assertNotContained('Traceback', output[1]) # no python stack + self.assertContained('error: invalid preprocessing directive', output[1]) + self.assertContained('''error: use of undeclared identifier 'cheez''', output[1]) + self.assertContained('2 errors generated', output[1]) + assert output[1].split('2 errors generated.')[1].replace('\n', '') == 'emcc: compiler frontend failed to generate LLVM bitcode, halting' + # emcc src.cpp -c and emcc src.cpp -o src.[o|bc] ==> should give a .bc file for args in [['-c'], ['-o', 'src.o'], ['-o', 'src.bc']]: target = args[1] if len(args) == 2 else 'hello_world.o' @@ -5370,15 +5383,17 @@ elif 'sanity' in str(sys.argv): return Popen(command, stdout=PIPE, stderr=STDOUT).communicate()[0] - def check_working(self, command): + def check_working(self, command, expected=None): if type(command) is not list: command = [command] + if expected is None: + if command[0] == EMCC: + expected = 'no input files' + else: + expected = "has no attribute 'blahblah'" output = self.do(command) - if command[0] == EMCC: - self.assertContained('no input files', output) - else: - self.assertContained("has no attribute 'blahblah'", output) + self.assertContained(expected, output) return output def test_aaa_normal(self): # this should be the very first thing that runs. if this fails, everything else is irrelevant! @@ -5413,6 +5428,34 @@ elif 'sanity' in str(sys.argv): else: self.assertContained('FATAL', output) # sanity check should fail + def test_closure_compiler(self): + CLOSURE_FATAL = 'fatal: Closure compiler' + CLOSURE_WARNING = 'WARNING: Closure compiler' + + # Sanity check should find closure + restore() + output = self.check_working(EMCC) + self.assertNotContained(CLOSURE_FATAL, output) + self.assertNotContained(CLOSURE_WARNING, output) + + # Append a bad path for closure, will warn + f = open(CONFIG_FILE, 'a') + f.write('CLOSURE_COMPILER = "/tmp/nowhere/nothingtoseehere/kjadsfkjwelkjsdfkqgas/nonexistent.txt"\n') + f.close() + output = self.check_working(EMCC, CLOSURE_WARNING) + + # And if you actually try to use the bad path, will be fatal + f = open(CONFIG_FILE, 'a') + f.write('CLOSURE_COMPILER = "/tmp/nowhere/nothingtoseehere/kjadsfkjwelkjsdfkqgas/nonexistent.txt"\n') + f.close() + output = self.check_working([EMCC, '-O2', 'tests/hello_world.cpp'], CLOSURE_FATAL) + + # With a working path, all is well + restore() + try_delete('a.out.js') + output = self.check_working([EMCC, '-O2', 'tests/hello_world.cpp'], 'The relooper optimization can be very slow') + assert os.path.exists('a.out.js') + def test_emcc(self): def mtime(filename): return os.stat(filename).st_mtime diff --git a/tools/shared.py b/tools/shared.py index 1366f6fd..5b238aa4 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -563,7 +563,8 @@ class Building: if type(passes) == str: passes = [passes] input = open(filename, 'r').read() - output = Popen([NODE_JS, JS_OPTIMIZER] + passes, stdin=PIPE, stdout=PIPE).communicate(input)[0] + output, err = Popen([NODE_JS, JS_OPTIMIZER] + passes, stdin=PIPE, stdout=PIPE, stderr=PIPE).communicate(input) + assert len(output) > 0, 'Error in js optimizer: ' + err + '\n\n' + output filename += '.jo.js' f = open(filename, 'w') f.write(output) @@ -578,7 +579,8 @@ class Building: coffee = path_from_root('tools', 'eliminator', 'node_modules', 'coffee-script', 'bin', 'coffee') eliminator = path_from_root('tools', 'eliminator', 'eliminator.coffee') input = open(filename, 'r').read() - output = Popen([coffee, eliminator], stdin=PIPE, stdout=PIPE, stderr=PIPE).communicate(input)[0] + output, err = Popen([coffee, eliminator], stdin=PIPE, stdout=PIPE, stderr=PIPE).communicate(input) + assert len(output) > 0, 'Error in eliminator: ' + err + '\n\n' + output filename += '.el.js' f = open(filename, 'w') f.write(output) @@ -597,8 +599,8 @@ class Building: #'--formatting', 'PRETTY_PRINT', #'--variable_map_output_file', filename + '.vars', '--js', filename, '--js_output_file', filename + '.cc.js'], stdout=PIPE, stderr=STDOUT).communicate()[0] - if 'ERROR' in cc_output: - raise Exception('Error in cc output: ' + cc_output) + if 'ERROR' in cc_output or not os.path.exists(filename + '.cc.js'): + raise Exception('closure compiler error: ' + cc_output) return filename + '.cc.js' |