50
50
import os, sys, shutil, tempfile, subprocess, shlex, time, re, logging
51
51
from subprocess import PIPE, STDOUT
52
52
from tools import shared, jsrun
53
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename
53
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename, WINDOWS
54
54
from tools.response_file import read_response_file
56
CXX_SUFFIXES = ('.cpp', '.cxx', '.cc')
57
SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc', '.m', '.mm')
58
BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
59
DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
60
STATICLIB_SUFFIXES = ('.a',)
61
ASSEMBLY_SUFFIXES = ('.ll',)
56
# endings = dot + a suffix, safe to test by filename.endswith(endings)
57
C_ENDINGS = ('.c', '.C')
58
CXX_ENDINGS = ('.cpp', '.cxx', '.cc', '.CPP', '.CXX', '.CC')
59
SOURCE_ENDINGS = C_ENDINGS + CXX_ENDINGS + ('.m', '.mm')
60
BITCODE_ENDINGS = ('.bc', '.o', '.obj')
61
DYNAMICLIB_ENDINGS = ('.dylib', '.so', '.dll')
62
STATICLIB_ENDINGS = ('.a',)
63
ASSEMBLY_ENDINGS = ('.ll',)
62
65
LIB_PREFIXES = ('', 'lib')
63
67
JS_CONTAINING_SUFFIXES = ('js', 'html')
65
69
# Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt
127
131
--version Display compiler version information
129
133
Options that are modified or new in %s include:
130
-O0 No optimizations (default)
135
-O0 No optimizations (default). This is the recommended
136
setting for starting to port a project, as it
137
includes various assertions.
131
139
-O1 Simple optimizations, including asm.js, LLVM -O1
132
optimizations, and no runtime assertions
140
optimizations, relooping, and no runtime assertions
133
141
or C++ exception catching (to re-enable
134
142
C++ exception catching, use
135
-s DISABLE_EXCEPTION_CATCHING=0 ).
136
(For details on the affects of different
143
-s DISABLE_EXCEPTION_CATCHING=0 ), and enables
145
-s ALIASING_FUNCTION_POINTERS=1
147
This is the recommended setting when you want a
148
reasonably optimized build that is generated as
149
quickly as possible (it is much faster than -O2).
151
(Note: for details on the affects of different
137
152
opt levels, see apply_opt_level() in
138
153
tools/shared.py and also src/settings.js.)
139
-O2 As -O1, plus the relooper (loop recreation),
140
LLVM -O3 optimizations, and
142
-s ALIASING_FUNCTION_POINTERS=1
155
-O2 As -O1, plus various js-level optimizations and
156
LLVM -O3 optimizations. This is the recommended
157
setting for a release build: slower compilation
158
time in return for the smallest and fastest
144
161
-O3 As -O2, plus dangerous optimizations that may
145
162
break the generated code! This adds
317
344
For more docs on the options --preload-file
318
345
accepts, see https://github.com/kripken/emscripten/wiki/Filesystem-Guide
320
--compression <codec> Compress both the compiled code and embedded/
347
--exclude-file <name> Files and directories to be excluded from
348
--embed-file and --preload-file
349
wildcard is supported
351
--compression <codec> **THIS OPTION IS DEPRECATED**
353
Compress both the compiled code and embedded/
321
354
preloaded files. <codec> should be a triple,
323
356
<native_encoder>,<js_decoder>,<js_name>
474
508
--proxy-to-worker Generates both html and js files. The main
475
509
program is in js, and the html proxies to/from it.
511
--emrun Enables the generated output to be aware of the
512
emrun command line tool. This allows stdout, stderr
513
and exit(returncode) capture when running the
514
generated application through emrun.
516
--em-config Specifies the location of the .emscripten configuration
517
file for the current compiler run. If not specified,
518
the environment variable EM_CONFIG is read for this
519
file, and if that is not set, the default location
520
~/.emscripten is assumed.
522
--default-obj-ext .ext Specifies the file suffix to generate if the location
523
of a directory name is passed to -o directive, e.g.
525
will by default generate an output name 'dir/a.o',
526
but this cmdline param can be passed to generate a
527
file with a custom suffix 'dir/a.ext'.
477
529
The target file, if specified (-o <target>), defines what will
480
532
<name>.js JavaScript
481
<name>.html HTML with embedded JavaScript
533
<name>.html HTML + side JavaScript file (<name>.js)
534
(JS on the side improves page load time)
482
535
<name>.bc LLVM bitcode (default)
483
536
<name>.o LLVM bitcode (same as .bc)
848
918
preload_files.append(newargs[i+1])
850
920
newargs[i+1] = ''
921
elif newargs[i].startswith('--exclude-file'):
922
check_bad_eq(newargs[i])
923
exclude_files.append(newargs[i+1])
851
926
elif newargs[i].startswith('--compression'):
927
logging.warning('--compression is deprecated. Instead, it is recommended you use native gzip compression in your webserver')
852
928
check_bad_eq(newargs[i])
853
929
parts = newargs[i+1].split(',')
854
930
assert len(parts) == 3, '--compression requires specifying native_encoder,js_decoder,js_name - see emcc --help. got: %s' % newargs[i+1]
855
Compression.encoder = parts[0]
856
Compression.decoder = parts[1]
933
if os.path.exists(tool+'.exe'):
935
if os.path.exists(tool+'.bat'):
937
if os.path.exists(tool+'.cmd'):
940
Compression.encoder = locate(parts[0])
941
Compression.decoder = locate(parts[1])
857
942
Compression.js_name = parts[2]
858
943
assert os.path.exists(Compression.encoder), 'native encoder %s does not exist' % Compression.encoder
859
944
assert os.path.exists(Compression.decoder), 'js decoder %s does not exist' % Compression.decoder
915
1003
if not absolute_warning_shown and os.path.isabs(path_name):
916
1004
logging.warning ('-I or -L of an absolute path "' + newargs[i] + '" encountered. If this is to a local system header/library, it may cause problems (local system files make sense for compiling natively on your system, but not necessarily to JavaScript). Pass \'-Wno-warn-absolute-paths\' to emcc to hide this warning.') # Of course an absolute path to a non-system-specific library or header is fine, and you can ignore this warning. The danger are system headers that are e.g. x86 specific and nonportable. The emscripten bundled headers are modified to be portable, local system ones are generally not
917
1005
absolute_warning_shown = True
1006
elif newargs[i] == '--emrun':
1009
elif newargs[i] == '--em-config':
1010
# This option is parsed in tools/shared.py, here only clean it up from being passed to clang.
1013
elif newargs[i] == '--default-obj-ext':
1015
default_object_extension = newargs[i+1]
1016
if not default_object_extension.startswith('.'):
1017
default_object_extension = '.' + default_object_extension
918
1020
newargs = [ arg for arg in newargs if arg is not '' ]
920
1022
# If user did not specify a default -std for C++ code, specify the emscripten default.
921
1023
if default_cxx_std:
922
1024
newargs = newargs + [default_cxx_std]
924
if js_opts is None: js_opts = True
1027
pre_js += open(shared.path_from_root('src', 'emrun_prejs.js')).read() + '\n'
1028
post_js += open(shared.path_from_root('src', 'emrun_postjs.js')).read() + '\n'
1030
if js_opts is None: js_opts = opt_level >= 2
925
1031
if llvm_opts is None: llvm_opts = LLVM_OPT_LEVEL[opt_level]
926
1032
if llvm_lto is None and opt_level >= 3: llvm_lto = 3
927
1033
if opt_level == 0: debug_level = 4
971
1077
prev = newargs[i-1]
972
if prev in ['-MT', '-MF', '-MQ', '-D', '-U', '-o', '-x', '-Xpreprocessor', '-include', '-imacros', '-idirafter', '-iprefix', '-iwithprefix', '-iwithprefixbefore', '-isysroot', '-imultilib', '-A', '-isystem', '-iquote', '-install_name', '-I', '-L']: continue # ignore this gcc-style argument
1078
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
974
if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES)):
1080
if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS)):
975
1081
arg = os.path.realpath(arg)
977
if not arg.startswith('-') and (arg.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
979
if os.path.exists(arg):
980
if arg.endswith(SOURCE_SUFFIXES):
1083
if not arg.startswith('-'):
1084
if not os.path.exists(arg):
1085
logging.error('%s: No such file or directory ("%s" was expected to be an input file, based on the commandline arguments provided)' % (arg, arg))
1088
arg_ending = filename_type_ending(arg)
1089
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
1091
if arg_ending.endswith(SOURCE_ENDINGS):
981
1092
input_files.append(arg)
982
1093
has_source_inputs = True
1094
elif arg_ending.endswith(ASSEMBLY_ENDINGS) or shared.Building.is_bitcode(arg): # this should be bitcode, make sure it is valid
1095
input_files.append(arg)
1096
elif arg_ending.endswith(STATICLIB_ENDINGS + DYNAMICLIB_ENDINGS):
1097
# if it's not, and it's a library, just add it to libs to find later
1098
l = unsuffixed_basename(arg)
1099
for prefix in LIB_PREFIXES:
1100
if not prefix: continue
1101
if l.startswith(prefix):
984
# this should be bitcode, make sure it is valid
985
if arg.endswith(ASSEMBLY_SUFFIXES) or shared.Building.is_bitcode(arg):
986
input_files.append(arg)
987
elif arg.endswith(STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES):
988
# if it's not, and it's a library, just add it to libs to find later
989
l = unsuffixed_basename(arg)
990
for prefix in LIB_PREFIXES:
991
if not prefix: continue
992
if l.startswith(prefix):
1107
logging.warning(arg + ' is not valid LLVM bitcode')
1108
elif arg_ending.endswith(STATICLIB_ENDINGS):
1109
if not shared.Building.is_ar(arg):
1110
if shared.Building.is_bitcode(arg):
1111
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))
998
logging.warning(arg + ' is not valid LLVM bitcode')
1113
logging.error(arg + ': Unknown format, not a static library!')
1000
logging.error(arg + ': No such file or directory')
1116
logging.error(arg + ": Input file has an unknown suffix, don't know what to do with it!")
1002
1118
elif arg.startswith('-L'):
1003
1119
lib_dirs.append(arg[2:])
1017
1133
target = target_basename + '.o'
1018
1134
final_suffix = 'o'
1020
# do not link in libs when just generating object code (not an 'executable', i.e. JS, or a library)
1021
if ('.' + final_suffix) in BITCODE_SUFFIXES and len(libs) > 0:
1022
logging.warning('not linking against libraries since only compiling to bitcode')
1025
1136
# Find library files
1026
1137
for lib in libs:
1027
1138
logging.debug('looking for library "%s"' % lib)
1029
1140
for prefix in LIB_PREFIXES:
1030
for suff in STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES:
1141
for suff in STATICLIB_ENDINGS + DYNAMICLIB_ENDINGS:
1031
1142
name = prefix + lib + suff
1032
1143
for lib_dir in lib_dirs:
1033
1144
path = os.path.join(lib_dir, name)
1039
1150
if found: break
1040
1151
if found: break
1152
if not found: logging.warning('emcc: cannot find library "%s"' % lib)
1042
if ignore_dynamic_linking:
1043
input_files = filter(lambda input_file: not input_file.endswith(DYNAMICLIB_SUFFIXES), input_files)
1154
# If not compiling to JS, then we are compiling to an intermediate bitcode objects or library, so
1155
# ignore dynamic linking, since multiple dynamic linkings can interfere with each other
1156
if not filename_type_suffix(target) in JS_CONTAINING_SUFFIXES or ignore_dynamic_linking:
1157
def check(input_file):
1158
if filename_type_ending(input_file) in DYNAMICLIB_ENDINGS:
1159
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))
1163
input_files = filter(lambda input_file: check(input_file), input_files)
1045
1165
if len(input_files) == 0:
1046
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))
1166
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))
1049
1169
newargs = CC_ADDITIONAL_ARGS + newargs
1070
1190
logging.warning('disabling asm.js since embind is not ready for it yet')
1071
1191
shared.Settings.ASM_JS = 0
1193
fastcomp = os.environ.get('EMCC_FAST_COMPILER') == '1'
1196
shared.Settings.ASM_JS = 1
1197
assert shared.Settings.ALLOW_MEMORY_GROWTH == 0, 'memory growth not supported in fastcomp yet'
1198
assert shared.Settings.UNALIGNED_MEMORY == 0, 'forced unaligned memory not supported in fastcomp'
1199
assert shared.Settings.SAFE_HEAP == 0, 'safe heap not supported in fastcomp yet'
1200
assert shared.Settings.CHECK_HEAP_ALIGN == 0, 'check heap align not supported in fastcomp yet'
1201
assert shared.Settings.SAFE_DYNCALLS == 0, 'safe dyncalls not supported in fastcomp'
1202
assert shared.Settings.RESERVED_FUNCTION_POINTERS == 0, 'reserved function pointers not supported in fastcomp'
1203
assert shared.Settings.ASM_HEAP_LOG == 0, 'asm heap log not supported in fastcomp'
1204
assert shared.Settings.LABEL_DEBUG == 0, 'label debug not supported in fastcomp'
1205
assert shared.Settings.LEGACY_GL_EMULATION == 0, 'legacy gl emulation not supported in fastcomp'
1206
assert shared.Settings.EXECUTION_TIMEOUT == -1, 'execution timeout not supported in fastcomp'
1207
assert shared.Settings.NAMED_GLOBALS == 0, 'named globals not supported in fastcomp'
1208
assert shared.Settings.PGO == 0, 'pgo not supported in fastcomp'
1209
assert shared.Settings.TARGET_LE32 == 1, 'fastcomp requires le32'
1210
assert shared.Settings.USE_TYPED_ARRAYS == 2, 'fastcomp assumes ta2'
1211
assert not bind, 'embind not supported in fastcomp yet'
1213
logging.warning('jcache is not supported in fastcomp (you should not need it anyhow), disabling')
1216
fastcomp_opts = ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt']
1217
if not shared.Settings.DISABLE_EXCEPTION_CATCHING:
1218
fastcomp_opts += ['-enable-emscripten-cxx-exceptions']
1073
1220
if shared.Settings.ASM_JS:
1074
assert opt_level >= 1, 'asm.js requires -O1 or above'
1221
assert opt_level >= 1 or fastcomp, 'asm.js requires -O1 or above'
1077
1224
shared.Settings.RESERVED_FUNCTION_POINTERS = max(shared.Settings.RESERVED_FUNCTION_POINTERS, 10)
1147
1298
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
1148
1299
for input_file in input_files:
1149
if input_file.endswith(SOURCE_SUFFIXES):
1300
file_ending = filename_type_ending(input_file)
1301
if file_ending.endswith(SOURCE_ENDINGS):
1150
1302
logging.debug('compiling source file: ' + input_file)
1151
1303
input_file = shared.Building.preprocess(input_file, in_temp(uniquename(input_file)))
1152
1304
output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
1153
1305
temp_files.append(output_file)
1154
1306
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
1155
if input_file.endswith(CXX_SUFFIXES):
1307
if file_ending.endswith(CXX_ENDINGS):
1156
1308
args += shared.EMSDK_CXX_OPTS
1157
1309
logging.debug("running: " + call + ' ' + ' '.join(args))
1158
1310
execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
1160
1312
logging.error('compiler frontend failed to generate LLVM bitcode, halting')
1162
1314
else: # bitcode
1163
if input_file.endswith(BITCODE_SUFFIXES):
1315
if file_ending.endswith(BITCODE_ENDINGS):
1164
1316
logging.debug('copying bitcode file: ' + input_file)
1165
1317
temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
1166
1318
shutil.copyfile(input_file, temp_file)
1167
1319
temp_files.append(temp_file)
1168
elif input_file.endswith(DYNAMICLIB_SUFFIXES) or shared.Building.is_ar(input_file):
1320
elif file_ending.endswith(DYNAMICLIB_ENDINGS) or shared.Building.is_ar(input_file):
1169
1321
logging.debug('copying library file: ' + input_file)
1170
1322
temp_file = in_temp(uniquename(input_file))
1171
1323
shutil.copyfile(input_file, temp_file)
1172
1324
temp_files.append(temp_file)
1325
elif file_ending.endswith(ASSEMBLY_ENDINGS):
1174
1326
if not LEAVE_INPUTS_RAW:
1175
1327
# Note that by assembling the .ll file, then disassembling it later, we will
1176
1328
# remove annotations which is a good thing for compilation time
1185
1340
# Optimize source files
1186
1341
if llvm_opts > 0:
1187
1342
for i, input_file in enumerate(input_files):
1188
if input_file.endswith(SOURCE_SUFFIXES):
1343
file_ending = filename_type_ending(input_file)
1344
if file_ending.endswith(SOURCE_ENDINGS):
1189
1345
temp_file = temp_files[i]
1190
logging.debug('optimizing %s with -O%d' % (input_file, llvm_opts))
1346
logging.debug('optimizing %s with -O%s' % (input_file, llvm_opts))
1191
1347
shared.Building.llvm_opt(temp_file, llvm_opts)
1193
1349
# If we were just asked to generate bitcode, stop there
1197
1353
shutil.move(in_temp(unsuffixed(uniquename(input_file)) + '.o'), unsuffixed_basename(input_file) + '.' + final_suffix)
1199
1355
if len(input_files) == 1:
1200
shutil.move(in_temp(unsuffixed(uniquename(input_files[0])) + '.o'), specified_target)
1356
temp_output_base = in_temp(unsuffixed(uniquename(input_files[0])))
1357
if specified_target.endswith('/') or specified_target.endswith('\\') or os.path.isdir(specified_target): # User passed '-o <directory' as the location to output to.
1358
obj_output_name = os.path.join(specified_target, os.path.splitext(os.path.basename(input_file))[0] + default_object_extension)
1359
logging.debug('User specified -o <directoryname> as the location of the output. Generating output file ' + obj_output_name)
1361
shutil.move(temp_output_base + '.o', obj_output_name)
1363
logging.error('Could not write to output file ' + obj_output_name + '. Perhaps the output directory does not exist?')
1365
else: # User passed '-o <filename>' as the location to output to.
1366
shutil.move(temp_output_base + '.o', specified_target)
1367
if os.path.exists(temp_output_base + '.d'):
1368
# There was a .d file generated, from -MD or -MMD and friends, save a copy of it to where the output resides,
1369
# adjusting the target name away from the temporary file name to the specified target.
1370
# It will be deleted with the rest of the temporary directory.
1371
deps = open(temp_output_base + '.d').read()
1372
deps = deps.replace(temp_output_base + '.o', specified_target)
1373
with open(os.path.join(os.path.dirname(specified_target), os.path.basename(unsuffixed(input_files[0]) + '.d')), "w") as out_dep:
1202
1376
assert len(original_input_files) == 1 or not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv) + ':' + str(original_input_files)
1203
1377
# We have a specified target (-o <target>), which is not JavaScript or HTML, and
1268
1442
os.path.join('libcxx', 'new.cpp'),
1269
os.path.join('libc', 'stdlib', 'getopt_long.c'),
1270
os.path.join('libc', 'gen', 'err.c'),
1271
os.path.join('libc', 'gen', 'errx.c'),
1272
os.path.join('libc', 'gen', 'warn.c'),
1273
os.path.join('libc', 'gen', 'warnx.c'),
1274
os.path.join('libc', 'gen', 'verr.c'),
1275
os.path.join('libc', 'gen', 'verrx.c'),
1276
os.path.join('libc', 'gen', 'vwarn.c'),
1277
os.path.join('libc', 'gen', 'vwarnx.c'),
1278
os.path.join('libc', 'stdlib', 'strtod.c'),
1464
for directory, sources in musl_files:
1465
libc_files += [os.path.join('libc', 'musl', 'src', directory, source) for source in sources]
1280
1466
return build_libc('libc.bc', libc_files)
1282
1468
def apply_libc(need):
1477
1755
# First, combine the bitcode files if there are several. We must also link if we have a singleton .a
1478
1756
if len(input_files) + len(extra_files_to_link) > 1 or \
1479
(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])):
1757
(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])):
1480
1758
linker_inputs = temp_files + extra_files_to_link
1481
1759
logging.debug('linking: ' + str(linker_inputs))
1482
1760
t0 = time.time()
1483
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)
1761
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)
1484
1762
t1 = time.time()
1485
1763
logging.debug(' linking took %.2f seconds' % (t1 - t0))
1486
1764
final = in_temp(target_basename + '.bc')
1526
1804
# At minimum remove dead functions etc., this potentially saves a lot in the size of the generated code (and the time to compile it)
1527
1805
link_opts += shared.Building.get_safe_internalize() + ['-globaldce']
1528
shared.Building.llvm_opt(in_temp(target_basename + '.bc'), link_opts)
1529
if DEBUG: save_intermediate('linktime', 'bc')
1532
shutil.copyfile(final, save_bc)
1807
if (not save_bc and not fastcomp) or AUTODEBUG:
1808
# let llvm opt directly emit ll, to skip writing and reading all the bitcode
1810
shared.Building.llvm_opt(final, link_opts, final + '.link.ll')
1811
final = final + '.link.ll'
1812
if DEBUG: save_intermediate('linktime', 'll')
1814
if fastcomp and not save_bc:
1815
# Simplify LLVM bitcode for fastcomp
1816
link_opts += fastcomp_opts
1817
shared.Building.llvm_opt(final, link_opts)
1818
if DEBUG: save_intermediate('linktime', 'bc')
1820
shutil.copyfile(final, save_bc)
1822
shared.Building.llvm_opt(final, fastcomp_opts, final + '.adsimp.bc')
1823
final += '.adsimp.bc'
1824
if DEBUG: save_intermediate('adsimp', 'bc')
1534
1826
# Prepare .ll for Emscripten
1535
1827
if not LEAVE_INPUTS_RAW:
1536
final = shared.Building.llvm_dis(final, final + '.ll')
1829
final = shared.Building.llvm_dis(final, final + '.ll')
1538
1831
assert len(input_files) == 1
1539
if DEBUG: save_intermediate('ll', 'll')
1832
if DEBUG and save_bc: save_intermediate('ll', 'll')
1542
1835
logging.debug('autodebug')
1544
1837
final += '.ad.ll'
1545
1838
if DEBUG: save_intermediate('autodebug', 'll')
1840
# Simplify bitcode after autodebug
1841
if fastcomp and (AUTODEBUG or LEAVE_INPUTS_RAW):
1842
shared.Building.llvm_opt(final, fastcomp_opts, final + '.adsimp.bc')
1843
final += '.adsimp.bc'
1844
if DEBUG: save_intermediate('adsimp', 'bc')
1548
1847
logging.debug('LLVM => JS')
1549
1848
extra_args = [] if not js_libraries else ['--libraries', ','.join(map(os.path.abspath, js_libraries))]
1561
1860
if len(embed_files) > 0:
1562
1861
file_args.append('--embed')
1563
1862
file_args += embed_files
1863
if len(exclude_files) > 0:
1864
file_args.append('--exclude')
1865
file_args += exclude_files
1564
1866
if Compression.on:
1565
1867
file_args += ['--compress', Compression.encoder, Compression.decoder, Compression.js_name]
1566
1868
if use_preload_cache:
1567
1869
file_args.append('--use-preload-cache')
1568
code = execute([shared.PYTHON, shared.FILE_PACKAGER, unsuffixed(target) + '.data'] + file_args, stdout=PIPE)[0]
1569
src = open(final).read().replace('// {{PRE_RUN_ADDITIONS}}', '// {{PRE_RUN_ADDITIONS}}\n' + code)
1570
final += '.files.js'
1571
open(final, 'w').write(src)
1572
if DEBUG: save_intermediate('files')
1871
file_args.append('--no-heap-copy')
1872
file_code = execute([shared.PYTHON, shared.FILE_PACKAGER, unsuffixed(target) + '.data'] + file_args, stdout=PIPE)[0]
1873
pre_js = file_code + pre_js
1574
1875
# Apply pre and postjs files
1575
1876
if pre_js or post_js:
1618
1919
temp_memfile = os.path.join(shared.EMSCRIPTEN_TEMP_DIR, os.path.basename(memfile))
1619
1920
if os.path.abspath(memfile) != os.path.abspath(memfile):
1620
1921
shutil.copyfile(memfile, temp_memfile)
1621
return 'loadMemoryInitializer("%s");' % os.path.basename(memfile)
1922
return 'var memoryInitializer = "%s";' % os.path.basename(memfile)
1622
1923
src = re.sub(shared.JS.memory_initializer_pattern, repl, open(final).read(), count=1)
1623
1924
open(final + '.mem.js', 'w').write(src)
1624
1925
final += '.mem.js'
1718
2025
if final_suffix == 'html':
1719
2026
logging.debug('generating HTML')
1720
2027
shell = open(shell_path).read()
2028
assert '{{{ SCRIPT }}}' in shell, 'HTML shell must contain {{{ SCRIPT }}} , see src/shell.html for an example'
1721
2029
html = open(target, 'w')
2030
js_target = unsuffixed(target) + '.js'
2031
base_js_target = os.path.basename(js_target)
1722
2032
if proxy_to_worker:
1723
html.write(shell.replace('{{{ SCRIPT_CODE }}}', open(shared.path_from_root('src', 'proxyClient.js')).read().replace('{{{ filename }}}', target_basename)))
1724
js_target = unsuffixed(target) + '.js'
1725
shutil.copyfile(final, js_target)
2033
html.write(shell.replace('{{{ SCRIPT }}}', '<script>' + open(shared.path_from_root('src', 'proxyClient.js')).read().replace('{{{ filename }}}', target_basename) + '</script>'))
2034
shutil.move(final, js_target)
1726
2035
elif not Compression.on:
1727
2036
if debug_level >= 4:
1728
match = re.match('.*?<script[^>]*>{{{ SCRIPT_CODE }}}</script>', shell,
1731
raise RuntimeError('''Could not find script insertion point - make sure you have <script type='text/javascript'>{{{ SCRIPT_CODE }}}</script> in your HTML file (with no newlines)''')
1732
generate_source_map(target, match.group().count('\n'))
1733
html.write(shell.replace('{{{ SCRIPT_CODE }}}', open(final).read()))
2037
generate_source_map(target)
2038
shutil.move(final, js_target)
2039
# TODO: use an async blob, which would allow code rewriting on the client:
2040
# var blob = new Blob([codeString]);
2041
# var script = document.createElement('script');
2042
# script.src = URL.createObjectURL(blob);
2043
# document.body.appendChild(script);
2044
script_tag = '''<script async type="text/javascript" src="%s"></script>''' % base_js_target
2045
html.write(shell.replace('{{{ SCRIPT }}}', script_tag))
1735
2047
# Compress the main code
1736
js_target = unsuffixed(target) + '.js'
1737
2048
shutil.move(final, js_target)
1738
2049
Compression.compress(js_target)