summaryrefslogtreecommitdiff
path: root/emcc
diff options
context:
space:
mode:
Diffstat (limited to 'emcc')
-rwxr-xr-xemcc153
1 files changed, 94 insertions, 59 deletions
diff --git a/emcc b/emcc
index 726838af..621cb340 100755
--- a/emcc
+++ b/emcc
@@ -53,14 +53,17 @@ from tools import shared, jsrun
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename, WINDOWS
from tools.response_file import read_response_file
-C_SUFFIXES = ('.c', '.C')
-CXX_SUFFIXES = ('.cpp', '.cxx', '.cc', '.CPP', '.CXX', '.CC')
-SOURCE_SUFFIXES = C_SUFFIXES + CXX_SUFFIXES + ('.m', '.mm')
-BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
-DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
-STATICLIB_SUFFIXES = ('.a',)
-ASSEMBLY_SUFFIXES = ('.ll',)
+# endings = dot + a suffix, safe to test by filename.endswith(endings)
+C_ENDINGS = ('.c', '.C')
+CXX_ENDINGS = ('.cpp', '.cxx', '.cc', '.CPP', '.CXX', '.CC')
+SOURCE_ENDINGS = C_ENDINGS + CXX_ENDINGS + ('.m', '.mm')
+BITCODE_ENDINGS = ('.bc', '.o', '.obj')
+DYNAMICLIB_ENDINGS = ('.dylib', '.so', '.dll')
+STATICLIB_ENDINGS = ('.a',)
+ASSEMBLY_ENDINGS = ('.ll',)
+
LIB_PREFIXES = ('', 'lib')
+
JS_CONTAINING_SUFFIXES = ('js', 'html')
# Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt
@@ -345,7 +348,9 @@ Options that are modified or new in %s include:
--embed-file and --preload-file
wildcard is supported
- --compression <codec> Compress both the compiled code and embedded/
+ --compression <codec> **THIS OPTION IS DEPRECATED**
+
+ Compress both the compiled code and embedded/
preloaded files. <codec> should be a triple,
<native_encoder>,<js_decoder>,<js_name>
@@ -514,6 +519,13 @@ Options that are modified or new in %s include:
file, and if that is not set, the default location
~/.emscripten is assumed.
+ --default-obj-ext .ext Specifies the file suffix to generate if the location
+ of a directory name is passed to -o directive, e.g.
+ emcc -c a.c -o dir/
+ will by default generate an output name 'dir/a.o',
+ but this cmdline param can be passed to generate a
+ file with a custom suffix 'dir/a.ext'.
+
The target file, if specified (-o <target>), defines what will
be generated:
@@ -762,9 +774,13 @@ def in_temp(name):
def filename_type_suffix(filename):
for i in reversed(filename.split('.')[1:]):
if not i.isdigit():
- return '.' + i
+ return i
return ''
+def filename_type_ending(filename):
+ suffix = filename_type_suffix(filename)
+ return '' if not suffix else ('.' + suffix)
+
try:
call = CXX if use_cxx else CC
@@ -797,6 +813,7 @@ try:
use_preload_cache = False
no_heap_copy = False
proxy_to_worker = False
+ default_object_extension = '.o'
if use_cxx:
default_cxx_std = '-std=c++03' # Enforce a consistent C++ standard when compiling .cpp files, if user does not specify one on the cmdline.
@@ -907,6 +924,7 @@ try:
newargs[i] = ''
newargs[i+1] = ''
elif newargs[i].startswith('--compression'):
+ logging.warning('--compression is deprecated. Instead, it is recommended you use native gzip compression in your webserver')
check_bad_eq(newargs[i])
parts = newargs[i+1].split(',')
assert len(parts) == 3, '--compression requires specifying native_encoder,js_decoder,js_name - see emcc --help. got: %s' % newargs[i+1]
@@ -992,6 +1010,12 @@ try:
# This option is parsed in tools/shared.py, here only clean it up from being passed to clang.
newargs[i] = ''
newargs[i+1] = ''
+ elif newargs[i] == '--default-obj-ext':
+ newargs[i] = ''
+ default_object_extension = newargs[i+1]
+ if not default_object_extension.startswith('.'):
+ default_object_extension = '.' + default_object_extension
+ newargs[i+1] = ''
newargs = [ arg for arg in newargs if arg is not '' ]
@@ -1053,23 +1077,23 @@ 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_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES)):
+ if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS)):
arg = os.path.realpath(arg)
if not arg.startswith('-'):
if not os.path.exists(arg):
- logging.error(arg + ': No such file or directory')
+ logging.error('%s: No such file or directory ("%s" was expected to be an input file, based on the commandline arguments provided)' % (arg, arg))
exit(1)
- arg_suffix = filename_type_suffix(arg)
- if arg_suffix.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs
+ 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
newargs[i] = ''
- if arg_suffix.endswith(SOURCE_SUFFIXES):
+ if arg_ending.endswith(SOURCE_ENDINGS):
input_files.append(arg)
has_source_inputs = True
- elif arg_suffix.endswith(ASSEMBLY_SUFFIXES) or shared.Building.is_bitcode(arg): # this should be bitcode, make sure it is valid
+ 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_suffix.endswith(STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES):
+ elif arg_ending.endswith(STATICLIB_ENDINGS + DYNAMICLIB_ENDINGS):
# if it's not, and it's a library, just add it to libs to find later
l = unsuffixed_basename(arg)
for prefix in LIB_PREFIXES:
@@ -1081,10 +1105,10 @@ try:
newargs[i] = ''
else:
logging.warning(arg + ' is not valid LLVM bitcode')
- elif arg_suffix.endswith(STATICLIB_SUFFIXES):
+ elif arg_ending.endswith(STATICLIB_ENDINGS):
if not shared.Building.is_ar(arg):
if shared.Building.is_bitcode(arg):
- logging.error(arg + ': File has a suffix of a static library ' + str(STATICLIB_SUFFIXES) + ', but instead is an LLVM bitcode file! When linking LLVM bitcode files, use one of the suffixes ' + str(BITCODE_SUFFIXES))
+ logging.error(arg + ': File has a suffix of a static library ' + str(STATICLIB_ENDINGS) + ', but instead is an LLVM bitcode file! When linking LLVM bitcode files, use one of the suffixes ' + str(BITCODE_ENDINGS))
else:
logging.error(arg + ': Unknown format, not a static library!')
exit(1)
@@ -1109,17 +1133,12 @@ try:
target = target_basename + '.o'
final_suffix = 'o'
- # do not link in libs when just generating object code (not an 'executable', i.e. JS, or a library)
- if ('.' + final_suffix) in BITCODE_SUFFIXES and len(libs) > 0:
- logging.warning('not linking against libraries since only compiling to bitcode')
- libs = []
-
# Find library files
for lib in libs:
logging.debug('looking for library "%s"' % lib)
found = False
for prefix in LIB_PREFIXES:
- for suff in STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES:
+ for suff in STATICLIB_ENDINGS + DYNAMICLIB_ENDINGS:
name = prefix + lib + suff
for lib_dir in lib_dirs:
path = os.path.join(lib_dir, name)
@@ -1130,12 +1149,21 @@ try:
break
if found: break
if found: break
-
- if ignore_dynamic_linking:
- input_files = filter(lambda input_file: not input_file.endswith(DYNAMICLIB_SUFFIXES), input_files)
+ if not found: logging.warning('emcc: cannot find library "%s"' % lib)
+
+ # If not compiling to JS, then we are compiling to an intermediate bitcode objects or library, so
+ # ignore dynamic linking, since multiple dynamic linkings can interfere with each other
+ if not filename_type_suffix(target) in JS_CONTAINING_SUFFIXES or ignore_dynamic_linking:
+ def check(input_file):
+ if filename_type_ending(input_file) in DYNAMICLIB_ENDINGS:
+ if not ignore_dynamic_linking: logging.warning('ignoring dynamic library %s because not compiling to JS or HTML, remember to link it when compiling to JS or HTML at the end' % os.path.basename(input_file))
+ return False
+ else:
+ return True
+ 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_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + STATICLIB_SUFFIXES + ASSEMBLY_SUFFIXES))
+ 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))
exit(0)
newargs = CC_ADDITIONAL_ARGS + newargs
@@ -1162,7 +1190,9 @@ try:
logging.warning('disabling asm.js since embind is not ready for it yet')
shared.Settings.ASM_JS = 0
- if os.environ.get('EMCC_FAST_COMPILER'):
+ fastcomp = os.environ.get('EMCC_FAST_COMPILER') == '1'
+
+ if fastcomp:
shared.Settings.ASM_JS = 1
if shared.Settings.DISABLE_EXCEPTION_CATCHING == 0:
logging.warning('disabling exception catching since not supported in fastcomp yet')
@@ -1181,9 +1211,12 @@ try:
assert shared.Settings.PGO == 0, 'pgo not supported in fastcomp'
assert shared.Settings.TARGET_LE32 == 1, 'fastcomp requires le32'
assert not bind, 'embind not supported in fastcomp yet'
+ if jcache:
+ logging.warning('jcache is not supported in fastcomp (you should not need it anyhow), disabling')
+ jcache = False
if shared.Settings.ASM_JS:
- assert opt_level >= 1 or os.environ.get('EMCC_FAST_COMPILER'), 'asm.js requires -O1 or above'
+ assert opt_level >= 1 or fastcomp, 'asm.js requires -O1 or above'
if bind:
shared.Settings.RESERVED_FUNCTION_POINTERS = max(shared.Settings.RESERVED_FUNCTION_POINTERS, 10)
@@ -1195,16 +1228,6 @@ try:
shared.Settings.CORRECT_OVERFLOWS = 1
assert not shared.Settings.PGO, 'cannot run PGO in ASM_JS mode'
- heap = 4096
- while heap < shared.Settings.TOTAL_MEMORY:
- if heap < 16*1024*1024:
- heap *= 2
- else:
- heap += 16*1024*1024
- if heap != shared.Settings.TOTAL_MEMORY:
- logging.warning('increasing TOTAL_MEMORY to %d to be more reasonable for asm.js' % heap)
- shared.Settings.TOTAL_MEMORY = heap
-
if shared.Settings.CORRECT_SIGNS >= 2 or shared.Settings.CORRECT_OVERFLOWS >= 2 or shared.Settings.CORRECT_ROUNDINGS >= 2:
debug_level = 4 # must keep debug info to do line-by-line operations
@@ -1272,14 +1295,14 @@ try:
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
for input_file in input_files:
- file_suffix = filename_type_suffix(input_file)
- if file_suffix.endswith(SOURCE_SUFFIXES):
+ 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')
temp_files.append(output_file)
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
- if file_suffix.endswith(CXX_SUFFIXES):
+ if file_ending.endswith(CXX_ENDINGS):
args += shared.EMSDK_CXX_OPTS
logging.debug("running: " + call + ' ' + ' '.join(args))
execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
@@ -1287,17 +1310,17 @@ try:
logging.error('compiler frontend failed to generate LLVM bitcode, halting')
sys.exit(1)
else: # bitcode
- if file_suffix.endswith(BITCODE_SUFFIXES):
+ if file_ending.endswith(BITCODE_ENDINGS):
logging.debug('copying bitcode file: ' + input_file)
temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
shutil.copyfile(input_file, temp_file)
temp_files.append(temp_file)
- elif file_suffix.endswith(DYNAMICLIB_SUFFIXES) or shared.Building.is_ar(input_file):
+ elif file_ending.endswith(DYNAMICLIB_ENDINGS) or shared.Building.is_ar(input_file):
logging.debug('copying library file: ' + input_file)
temp_file = in_temp(uniquename(input_file))
shutil.copyfile(input_file, temp_file)
temp_files.append(temp_file)
- elif file_suffix.endswith(ASSEMBLY_SUFFIXES):
+ elif file_ending.endswith(ASSEMBLY_ENDINGS):
if not LEAVE_INPUTS_RAW:
# Note that by assembling the .ll file, then disassembling it later, we will
# remove annotations which is a good thing for compilation time
@@ -1315,8 +1338,8 @@ try:
# Optimize source files
if llvm_opts > 0:
for i, input_file in enumerate(input_files):
- file_suffix = filename_type_suffix(input_file)
- if file_suffix.endswith(SOURCE_SUFFIXES):
+ file_ending = filename_type_ending(input_file)
+ if file_ending.endswith(SOURCE_ENDINGS):
temp_file = temp_files[i]
logging.debug('optimizing %s with -O%s' % (input_file, llvm_opts))
shared.Building.llvm_opt(temp_file, llvm_opts)
@@ -1329,7 +1352,16 @@ try:
else:
if len(input_files) == 1:
temp_output_base = in_temp(unsuffixed(uniquename(input_files[0])))
- shutil.move(temp_output_base + '.o', specified_target)
+ 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)
+ 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)
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.
@@ -1661,11 +1693,11 @@ try:
# First, combine the bitcode files if there are several. We must also link if we have a singleton .a
if len(input_files) + len(extra_files_to_link) > 1 or \
- (not LEAVE_INPUTS_RAW and not (suffix(temp_files[0]) in BITCODE_SUFFIXES or suffix(temp_files[0]) in DYNAMICLIB_SUFFIXES) and shared.Building.is_ar(temp_files[0])):
+ (not LEAVE_INPUTS_RAW and not (suffix(temp_files[0]) in BITCODE_ENDINGS or suffix(temp_files[0]) in DYNAMICLIB_ENDINGS) and shared.Building.is_ar(temp_files[0])):
linker_inputs = temp_files + extra_files_to_link
logging.debug('linking: ' + str(linker_inputs))
t0 = time.time()
- shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'), force_archive_contents = len(filter(lambda temp: not temp.endswith(STATICLIB_SUFFIXES), temp_files)) == 0)
+ shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'), force_archive_contents = len(filter(lambda temp: not temp.endswith(STATICLIB_ENDINGS), temp_files)) == 0)
t1 = time.time()
logging.debug(' linking took %.2f seconds' % (t1 - t0))
final = in_temp(target_basename + '.bc')
@@ -1711,22 +1743,25 @@ try:
# At minimum remove dead functions etc., this potentially saves a lot in the size of the generated code (and the time to compile it)
link_opts += shared.Building.get_safe_internalize() + ['-globaldce']
- # Simplify LLVM bitcode for fastcomp
- if os.environ.get('EMCC_FAST_COMPILER') and not AUTODEBUG:
- link_opts += ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt']
- if (not save_bc and not os.environ.get('EMCC_FAST_COMPILER')) or AUTODEBUG:
+ if (not save_bc and not fastcomp) or AUTODEBUG:
# let llvm opt directly emit ll, to skip writing and reading all the bitcode
link_opts += ['-S']
shared.Building.llvm_opt(final, link_opts, final + '.link.ll')
final = final + '.link.ll'
if DEBUG: save_intermediate('linktime', 'll')
else:
+ if fastcomp and not save_bc:
+ # Simplify LLVM bitcode for fastcomp
+ link_opts += ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt']
shared.Building.llvm_opt(final, link_opts)
if DEBUG: save_intermediate('linktime', 'bc')
-
- if save_bc:
- shutil.copyfile(final, save_bc)
+ if save_bc:
+ shutil.copyfile(final, save_bc)
+ if fastcomp:
+ shared.Building.llvm_opt(final, ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt'], final + '.adsimp.bc')
+ final += '.adsimp.bc'
+ if DEBUG: save_intermediate('adsimp', 'bc')
# Prepare .ll for Emscripten
if not LEAVE_INPUTS_RAW:
@@ -1743,7 +1778,7 @@ try:
if DEBUG: save_intermediate('autodebug', 'll')
# Simplify bitcode after autodebug
- if os.environ.get('EMCC_FAST_COMPILER') and AUTODEBUG:
+ if fastcomp and (AUTODEBUG or LEAVE_INPUTS_RAW):
shared.Building.llvm_opt(final, ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt'], final + '.adsimp.bc')
final += '.adsimp.bc'
if DEBUG: save_intermediate('adsimp', 'bc')