refactor emcc in preparation for compiling multiple files at once
This commit is contained in:
Родитель
27578df126
Коммит
394bbcf08e
43
emcc
43
emcc
|
@ -267,6 +267,7 @@ elif use_compiler:
|
|||
elif newargs[i].startswith('--llvm-opts'):
|
||||
assert '=' not in newargs[i], 'Invalid llvm opts parameter (do not use "=")'
|
||||
llvm_opt_level = eval(newargs[i+1])
|
||||
assert 0 <= llvm_opt_level <= 1, 'Only two levels of LLVM optimizations are supported so far, 0 (none) and 1 (safe)'
|
||||
newargs[i] = ''
|
||||
newargs[i+1] = ''
|
||||
newargs = [ arg for arg in newargs if arg is not '' ]
|
||||
|
@ -283,13 +284,25 @@ elif use_compiler:
|
|||
newargs[i+1] = ''
|
||||
newargs = [ arg for arg in newargs if arg is not '' ]
|
||||
|
||||
def unsuffixed_basename(name):
|
||||
return os.path.basename('.'.join(name.split('.')[:-1]))
|
||||
|
||||
input_files = []
|
||||
for i in range(len(newargs)): # find input files XXX this a simple heuristic. we should really analyze based on a full understanding of gcc params,
|
||||
# right now we just assume that what is left contains no more |-x OPT| things
|
||||
arg = newargs[i]
|
||||
if arg.endswith(('.c', '.cpp', '.cxx')):
|
||||
input_files.append(unsuffixed_basename(arg))
|
||||
|
||||
assert len(input_files) > 0, 'emcc: no input files specified'
|
||||
|
||||
newargs += CC_ADDITIONAL_ARGS
|
||||
|
||||
if target is None:
|
||||
# No explicit -o specified, so do the most natural thing, compile to .js
|
||||
target = 'a.out.js'
|
||||
specified_target = target
|
||||
target = specified_target if specified_target is not None else 'a.out.js' # specified_target is the user-specified one, target is what we will generate
|
||||
if specified_target: assert len(input_files) == 1, 'If a target is specified, there should be exactly one input file'
|
||||
|
||||
target_basename = '.'.join(target.split('.')[:-1])
|
||||
target_basename = unsuffixed_basename(target)
|
||||
|
||||
if '-c' in newargs: # -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
|
||||
target = target_basename + '.bc'
|
||||
|
@ -313,24 +326,36 @@ elif use_compiler:
|
|||
|
||||
## Compile
|
||||
|
||||
# First, generate LLVM bitcode TODO: handle |emcc a.cpp b.cpp -c| which generate *two* bitcode files
|
||||
newargs = newargs + ['-emit-llvm', '-c', '-o', target_basename + '.bc']
|
||||
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
|
||||
newargs = newargs + ['-emit-llvm', '-c']
|
||||
|
||||
if DEBUG: print >> sys.stderr, "Running:", call, ' '.join(newargs)
|
||||
Popen([call] + newargs).communicate()
|
||||
|
||||
# Optimize, if asked to
|
||||
if llvm_opt_level > 0:
|
||||
shared.Building.llvm_opt(target_basename + '.bc', 2, safe=llvm_opt_level < 2)
|
||||
for input_file in input_files:
|
||||
shared.Building.llvm_opt(input_file + '.o', 2, safe=llvm_opt_level < 2)
|
||||
|
||||
# If we were just asked to generate bitcode, stop there
|
||||
if final_suffix in ['o', 'bc']:
|
||||
if final_suffix == 'o':
|
||||
shutil.move(target_basename + '.bc', target_basename + '.o')
|
||||
if final_suffix == 'bc':
|
||||
for input_file in input_files:
|
||||
shutil.move(input_file + '.o', input_file + '.bc')
|
||||
|
||||
if specified_target:
|
||||
shutil.move(input_files[0] + '.' + final_suffix, unsuffixed_basename(specified_target) + '.' + final_suffix)
|
||||
|
||||
exit(0)
|
||||
|
||||
## Continue on to create JavaScript
|
||||
|
||||
# First, combine the bitcode files if there are several
|
||||
if len(input_files) > 1:
|
||||
shared.Building.link(map(lambda input_file: input_file + '.o', input_files), target_basename + '.bc')
|
||||
else:
|
||||
shutil.move(input_files[0] + '.o', target_basename + '.bc')
|
||||
|
||||
# Apply -s settings in newargs here (after -Ox, so they can override it)
|
||||
|
||||
for change in settings_changes:
|
||||
|
|
|
@ -4904,16 +4904,16 @@ Options that are modified or new in %s include:
|
|||
output = Popen([compiler, path_from_root('tests', 'hello_world' + suffix)], stdout=PIPE, stderr=PIPE).communicate()
|
||||
assert len(output[0]) == 0, output[0]
|
||||
#assert len(output[1]) == 0, output[1] # we have some debug warnings there now, FIXME
|
||||
assert os.path.exists('a.out.js'), output
|
||||
assert os.path.exists('a.out.js'), output[1]
|
||||
self.assertContained('hello, world!', run_js('a.out.js'))
|
||||
|
||||
# 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 'a.out.bc'
|
||||
target = args[1] if len(args) == 2 else 'hello_world.bc'
|
||||
clear()
|
||||
output = Popen([compiler, path_from_root('tests', 'hello_world' + suffix)] + args, stdout=PIPE, stderr=PIPE).communicate()
|
||||
assert len(output[0]) == 0, output[0]
|
||||
assert os.path.exists(target), output
|
||||
assert os.path.exists(target), 'Expected %s to exist since args are %s : %s' % (target, str(args), output)
|
||||
self.assertContained('hello, world!', self.run_llvm_interpreter([target]))
|
||||
|
||||
# emcc src.cpp -o something.js [-Ox]. -O0 is the same as not specifying any optimization setting
|
||||
|
@ -4962,9 +4962,17 @@ Options that are modified or new in %s include:
|
|||
self.assertContained('hello, world!', run_js('a.out.js'))
|
||||
assert test(open('a.out.js').read()), text
|
||||
|
||||
## Compiling two source files TODO: with -o
|
||||
#clear()
|
||||
#output = Popen([compiler, path_from_root('tests', 'twopart_main.cpp'), path_from_root('tests', 'twopart_side.cpp')],
|
||||
# stdout=PIPE, stderr=PIPE).communicate()
|
||||
#assert len(output[0]) == 0, output[0]
|
||||
#assert os.path.exists('a.out.js'), '\n'.join(output)
|
||||
#self.assertContained('side got: hello from main, over', run_js('a.out.js'))
|
||||
##assert os.path.exists('twopart_main.bc'), '\n'.join(output)
|
||||
##assert os.path.exists('twopart_side.bc'), '\n'.join(output)
|
||||
##output = Popen([compiler, 'twopart_main.bc', 'twopart_side.bc', '-o', 'something.js'], stdout=PIPE, stderr=PIPE).communicate() # combine them
|
||||
|
||||
# emcc --llvm-opts=x .. ==> pick level of LLVM optimizations (default is 0, to be safe?)
|
||||
# We can run safe opts at each emcc invocation, now we are a gcc replacement. Removes the entire need for llvm opts only at the end.
|
||||
# linking - TODO. in particular, test normal project linking, static and dynamic: get_library should not need to be told what to link!
|
||||
# emcc a.cpp b.cpp => one .js
|
||||
# emcc a.cpp b.cpp -c => two .o files
|
||||
|
|
Загрузка…
Ссылка в новой задаче