~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to emcc

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-09-20 22:44:35 UTC
  • mfrom: (4.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20130920224435-apuwj4fsl3fqv1a6
Tags: 1.5.6~20130920~6010666-1
* New snapshot release
* Update the list of supported architectures to the same as libv8
  (Closes: #723129)
* emlibtool has been removed from upstream.
* Fix warning syntax-error-in-dep5-copyright
* Refresh of the patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
 
50
50
import os, sys, shutil, tempfile, subprocess, shlex, time, re, logging
51
51
from subprocess import PIPE, STDOUT
52
 
from tools import shared
 
52
from tools import shared, jsrun
53
53
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename
54
54
from tools.response_file import read_response_file
55
55
 
56
 
logging = logging.getLogger('emcc')
 
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',)
 
62
LIB_PREFIXES = ('', 'lib')
 
63
JS_CONTAINING_SUFFIXES = ('js', 'html')
57
64
 
58
65
# Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt
59
66
# levels 2 and 3 (emcc 3 is unsafe opts, so unsuitable for the only level to get
129
136
                           (For details on the affects of different
130
137
                           opt levels, see apply_opt_level() in
131
138
                           tools/shared.py and also src/settings.js.)
132
 
                           Note: Optimizations are only done when
133
 
                           compiling to JavaScript, not to intermediate
134
 
                           bitcode, *unless* you build with
135
 
                           EMCC_OPTIMIZE_NORMALLY=1 (not recommended
136
 
                           unless you know what you are doing!)
137
139
  -O2                      As -O1, plus the relooper (loop recreation),
138
 
                           LLVM -O2 optimizations, and
 
140
                           LLVM -O3 optimizations, and
139
141
 
140
142
                              -s ALIASING_FUNCTION_POINTERS=1
141
143
 
146
148
                              -s DOUBLE_MODE=0
147
149
                              -s PRECISE_I64_MATH=0
148
150
                              --closure 1
149
 
                              --llvm-lto 1
 
151
                              --llvm-lto 3
150
152
 
151
153
                           This is not recommended at all. A better idea
152
154
                           is to try each of these separately on top of
184
186
                           ). Note that the path must be absolute, not
185
187
                           relative.
186
188
 
187
 
  -g                       Use debug info. Note that you need this during
188
 
                           the last compilation phase from bitcode to
189
 
                           JavaScript, or else we will remove it by
190
 
                           default in -O1 and above.
191
 
                           In -O0, line numbers wil be shown in the
192
 
                           generated code. In -O1 and above, the optimizer
193
 
                           removes those comments. This flag does however
194
 
                           have the effect of disabling anything that
195
 
                           causes name mangling or minification (closure
196
 
                           or the registerize pass).
 
189
  -g                       Use debug info. When compiling to bitcode,
 
190
                           this is the same as in clang and gcc, it
 
191
                           adds debug info to the object files. When
 
192
                           compiling from source to JS or bitcode to JS,
 
193
                           it is equivalent to -g3 (keep code as debuggable
 
194
                           as possible, except for discarding LLVM
 
195
                           debug info, so no C/C++ line numbers; use
 
196
                           -g4 to get line number debugging info in JS).
 
197
 
 
198
  -g<level>                When compiling from bitcode to JS, we can
 
199
                           keep the code debuggable to different
 
200
                           degrees. Each of these levels builds on the
 
201
                           previous:
 
202
 
 
203
                            -g0  Make no effort to keep code debuggable.
 
204
                                 Will discard LLVM debug info. (default
 
205
                                 in -O1+)
 
206
                            -g1  Preserve (do not minify) whitespace
 
207
                            -g2  Preserve function names
 
208
                            -g3  Preserve variable names
 
209
                            -g4  Preserve LLVM debug info (if -g was
 
210
                                 used when compiling the C/C++ sources),
 
211
                                 show line number debug comments, and
 
212
                                 generate source maps. This is the highest
 
213
                                 level of debuggability. Note that this
 
214
                                 may make -O1 and above significantly
 
215
                                 slower because JS optimization will be
 
216
                                 limited to 1 core.  (default in -O0)
197
217
 
198
218
  --typed-arrays <mode>    0: No typed arrays
199
219
                           1: Parallel typed arrays
200
220
                           2: Shared (C-like) typed arrays (default)
201
221
 
 
222
  --js-opts                0: Prevent JS optimizer from running
 
223
                           1: Use JS optimizer (default)
 
224
 
202
225
  --llvm-opts <level>      0: No LLVM optimizations (default in -O0)
203
226
                           1: -O1 LLVM optimizations (default in -O1)
204
227
                           2: -O2 LLVM optimizations
205
228
                           3: -O3 LLVM optimizations (default in -O2+)
206
229
 
207
 
  --llvm-lto <level>       0: No LLVM LTO (default in -O2 and below)
208
 
                           1: LLVM LTO (default in -O3)
 
230
  --llvm-lto <level>       0: No LLVM LTO (default)
 
231
                           1: LLVM LTO is performed
 
232
                           2: We combine all the bitcode and run LLVM opt -O3
 
233
                              on that (which optimizes across modules, but is
 
234
                              not the same as normal LTO), but do not do normal
 
235
                              LTO
 
236
                           3: We do both 2 and then 1
209
237
                           Note: If LLVM optimizations are not run
210
 
                           (see --llvm-opts), setting this to 1 has no
 
238
                           (see --llvm-opts), setting this has no
211
239
                           effect.
212
240
 
213
241
  --closure <on>           0: No closure compiler (default in -O2 and below)
286
314
                           your main compiled code (or run it before in
287
315
                           some other way).
288
316
 
 
317
                           For more docs on the options --preload-file
 
318
                           accepts, see  https://github.com/kripken/emscripten/wiki/Filesystem-Guide
 
319
 
289
320
  --compression <codec>    Compress both the compiled code and embedded/
290
321
                           preloaded files. <codec> should be a triple,
291
322
 
305
336
                           archive, which is given the same name as the
306
337
                           output HTML but with suffix .data.compress
307
338
 
308
 
  --minify <on>            0: Do not minify the generated JavaScript's
309
 
                              whitespace (default in -O0, -O1, or if
310
 
                              -g is used)
311
 
                           1: Minify the generated JavaScript's
312
 
                              whitespace (default in -O2+, assuming
313
 
                              -g is not used)
 
339
  --minify 0               Identical to -g1
314
340
 
315
341
  --split <size>           Splits the resulting javascript file into pieces
316
342
                           to ease debugging. This option only works if
439
465
                           memory initialization data embedded inside
440
466
                           JavaScript as text. (default is off)
441
467
 
 
468
  -Wno-warn-absolute-paths If not specified, the compiler will warn about any
 
469
                           uses of absolute paths in -I and -L command line
 
470
                           directives. Pass this flag on the command line
 
471
                           to hide these warnings and acknowledge that the
 
472
                           explicit use of absolute paths is intentional.
 
473
 
 
474
  --proxy-to-worker        Generates both html and js files. The main
 
475
                           program is in js, and the html proxies to/from it.
 
476
 
442
477
The target file, if specified (-o <target>), defines what will
443
478
be generated:
444
479
 
511
546
      open(tempout, 'w').write('//\n')
512
547
 
513
548
  src = None
514
 
  for i in range(len(sys.argv)):
515
 
    if sys.argv[i].endswith('.c'):
 
549
  for arg in sys.argv:
 
550
    if arg.endswith('.c'):
516
551
      try:
517
 
        src = open(sys.argv[i]).read()
518
 
        if debug_configure: open(tempout, 'a').write('============= ' + sys.argv[i] + '\n' + src + '\n=============\n\n')
 
552
        src = open(arg).read()
 
553
        if debug_configure: open(tempout, 'a').write('============= ' + arg + '\n' + src + '\n=============\n\n')
519
554
      except:
520
555
        pass
521
 
    if sys.argv[i].endswith('.s'):
 
556
    elif arg.endswith('.s'):
522
557
      if debug_configure: open(tempout, 'a').write('(compiling .s assembly, must use clang\n')
523
558
      use_js = 0
524
559
 
601
636
 
602
637
# ---------------- Utilities ---------------
603
638
 
604
 
SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc', '.m', '.mm')
605
 
BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
606
 
DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
607
 
STATICLIB_SUFFIXES = ('.a',)
608
 
ASSEMBLY_SUFFIXES = ('.ll',)
609
 
LIB_PREFIXES = ('', 'lib')
610
 
 
611
 
JS_CONTAINING_SUFFIXES = ('js', 'html')
612
 
 
613
639
seen_names = {}
614
640
def uniquename(name):
615
641
  if name not in seen_names:
640
666
  logging.debug('just dependencies: ' + ' '.join(cmd))
641
667
  exit(subprocess.call(cmd))
642
668
 
 
669
if '-E' in sys.argv:
 
670
  # Just run the preprocessor
 
671
  cmd = [CC] + sys.argv[1:]
 
672
  logging.debug('just preprocssor ' + ' '.join(cmd))
 
673
  exit(subprocess.call(cmd))
 
674
 
643
675
# Check if a target is specified
644
676
target = None
645
677
for i in range(len(sys.argv)-1):
691
723
  newargs = sys.argv[1:]
692
724
 
693
725
  opt_level = 0
 
726
  debug_level = 0
 
727
  js_opts = None
694
728
  llvm_opts = None
695
729
  llvm_lto = None
696
730
  closure = None
697
731
  js_transform = None
698
732
  pre_js = ''
699
733
  post_js = ''
700
 
  minify_whitespace = None
701
734
  split_js_file = None
702
735
  preload_files = []
703
736
  embed_files = []
705
738
  ignore_dynamic_linking = False
706
739
  shell_path = shared.path_from_root('src', 'shell.html')
707
740
  js_libraries = []
708
 
  keep_llvm_debug = False
709
 
  keep_js_debug = False
710
741
  bind = False
711
742
  jcache = False
712
743
  save_bc = False
713
744
  memory_init_file = False
714
745
  use_preload_cache = False
 
746
  proxy_to_worker = False
715
747
 
716
748
  if use_cxx:
717
749
    default_cxx_std = '-std=c++03' # Enforce a consistent C++ standard when compiling .cpp files, if user does not specify one on the cmdline.
723
755
 
724
756
  absolute_warning_shown = False
725
757
 
 
758
  # Scan for warning suppression message in advance from other cmdline flags, so that it works even if -I or -L directives are present before this.
 
759
  for i in range(len(newargs)):
 
760
    if newargs[i] == '-Wno-warn-absolute-paths':
 
761
      newargs[i] = ''
 
762
      absolute_warning_shown = True
 
763
 
726
764
  settings_changes = []
727
765
 
 
766
  def validate_arg_level(level_string, max_level, err_msg):
 
767
    try:
 
768
      level = int(level_string)
 
769
      assert 0 <= level <= max_level
 
770
    except:
 
771
      raise Exception(err_msg)
 
772
    return level
 
773
 
728
774
  for i in range(len(newargs)):
729
775
    newargs[i] = newargs[i].strip() # On Windows Vista (and possibly others), excessive spaces in the command line leak into the items in this array, so trim e.g. 'foo.cpp ' -> 'foo.cpp'
730
776
    if newargs[i].startswith('-O'):
733
779
      if requested_level == 's':
734
780
        requested_level = 2
735
781
        settings_changes.append('INLINING_LIMIT=50')
736
 
      try:
737
 
        opt_level = int(requested_level)
738
 
        assert 0 <= opt_level <= 3
739
 
      except:
740
 
        raise Exception('Invalid optimization level: ' + newargs[i])
741
 
      newargs[i] = ''
 
782
      opt_level = validate_arg_level(requested_level, 3, 'Invalid optimization level: ' + newargs[i])
 
783
      newargs[i] = ''
 
784
    elif newargs[i].startswith('--js-opts'):
 
785
      check_bad_eq(newargs[i])
 
786
      js_opts = eval(newargs[i+1])
 
787
      newargs[i] = ''
 
788
      newargs[i+1] = ''
742
789
    elif newargs[i].startswith('--llvm-opts'):
743
790
      check_bad_eq(newargs[i])
744
791
      llvm_opts = eval(newargs[i+1])
771
818
      newargs[i+1] = ''
772
819
    elif newargs[i].startswith('--minify'):
773
820
      check_bad_eq(newargs[i])
774
 
      minify_whitespace = int(newargs[i+1])
 
821
      assert newargs[i+1] == '0', '0 is the only supported option for --minify; 1 has been deprecated'
 
822
      debug_level = max(1, debug_level)
775
823
      newargs[i] = ''
776
824
      newargs[i+1] = ''
777
825
    elif newargs[i].startswith('--split'):
779
827
      split_js_file = int(newargs[i+1])
780
828
      newargs[i] = ''
781
829
      newargs[i+1] = ''
782
 
    elif newargs[i] == '-g':
783
 
      keep_llvm_debug = True
784
 
      keep_js_debug = True
 
830
    elif newargs[i].startswith('-g'):
 
831
      requested_level = newargs[i][2:] or '3'
 
832
      debug_level = validate_arg_level(requested_level, 4, 'Invalid debug level: ' + newargs[i])
 
833
      newargs[i] = '-g' # we'll need this to get LLVM debug info
785
834
    elif newargs[i] == '--bind':
786
835
      bind = True
787
836
      newargs[i] = ''
812
861
      newargs[i] = ''
813
862
      newargs[i+1] = ''
814
863
    elif newargs[i].startswith('--use-preload-cache'):
815
 
      use_preload_cache = True;
 
864
      use_preload_cache = True
816
865
      newargs[i] = ''
817
866
    elif newargs[i] == '--ignore-dynamic-linking':
818
867
      ignore_dynamic_linking = True
819
868
      newargs[i] = ''
820
869
    elif newargs[i] == '-v':
821
870
      shared.COMPILER_OPTS += ['-v']
822
 
      DEBUG = 1
823
871
      os.environ['EMCC_DEBUG'] = '1' # send to child processes too
 
872
      if DEBUG != 1:
 
873
        # swap in debug logging
 
874
        DEBUG = 1
 
875
        shared.set_logging()
 
876
        logging.debug('invocation: ' + ' '.join(sys.argv))
 
877
        shared.apply_configuration() # reset config to pick up change
824
878
      newargs[i] = ''
825
879
    elif newargs[i].startswith('--shell-file'):
826
880
      check_bad_eq(newargs[i])
853
907
      memory_init_file = int(newargs[i+1])
854
908
      newargs[i] = ''
855
909
      newargs[i+1] = ''
856
 
    elif newargs[i].startswith(('-I/', '-L/')):
857
 
      if not absolute_warning_shown:
858
 
        logging.warning ('-I or -L of an absolute path 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)') # 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
 
910
    elif newargs[i] == '--proxy-to-worker':
 
911
      proxy_to_worker = True
 
912
      newargs[i] = ''
 
913
    elif newargs[i].startswith(('-I', '-L')):
 
914
      path_name = newargs[i][2:]
 
915
      if not absolute_warning_shown and os.path.isabs(path_name):
 
916
        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
859
917
        absolute_warning_shown = True
860
918
  newargs = [ arg for arg in newargs if arg is not '' ]
861
919
 
863
921
  if default_cxx_std:
864
922
    newargs = newargs + [default_cxx_std]
865
923
 
 
924
  if js_opts is None: js_opts = True
866
925
  if llvm_opts is None: llvm_opts = LLVM_OPT_LEVEL[opt_level]
867
 
  if llvm_lto is None: llvm_lto = opt_level >= 3
868
 
  if opt_level <= 0: keep_llvm_debug = keep_js_debug = True # always keep debug in -O0
869
 
  if opt_level > 0: keep_llvm_debug = False # JS optimizer wipes out llvm debug info from being visible
 
926
  if llvm_lto is None and opt_level >= 3: llvm_lto = 3
 
927
  if opt_level == 0: debug_level = 4
870
928
  if closure is None and opt_level == 3: closure = True
871
929
 
 
930
  if llvm_lto is None and bind:
 
931
    logging.debug('running lto for embind') # XXX this is a workaround for a pointer issue
 
932
    llvm_lto = 1
 
933
 
 
934
  # TODO: support source maps with js_transform
 
935
  if js_transform and debug_level >= 4:
 
936
    logging.warning('disabling source maps because a js transform is being done')
 
937
    debug_level = 3
 
938
 
872
939
  if DEBUG: start_time = time.time() # done after parsing arguments, which might affect debug state
873
940
 
874
941
  if closure:
902
969
 
903
970
    if i > 0:
904
971
      prev = newargs[i-1]
905
 
      if prev in ['-MT', '-install_name', '-I', '-L']: continue # ignore this gcc-style argument
 
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
906
973
 
907
974
    if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES)):
908
975
      arg = os.path.realpath(arg)
924
991
              if not prefix: continue
925
992
              if l.startswith(prefix):
926
993
                l = l[len(prefix):]
927
 
                break;
 
994
                break
928
995
            libs.append(l)
929
996
            newargs[i] = ''
930
997
          else:
979
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))
980
1047
    exit(0)
981
1048
 
982
 
  newargs += CC_ADDITIONAL_ARGS
 
1049
  newargs = CC_ADDITIONAL_ARGS + newargs
983
1050
 
984
1051
  assert not (Compression.on and final_suffix != 'html'), 'Compression only works when generating HTML'
985
1052
 
999
1066
    exec('shared.Settings.' + key + ' = ' + value)
1000
1067
 
1001
1068
  # Apply effects from settings
 
1069
  if bind and shared.Settings.ASM_JS:
 
1070
    logging.warning('disabling asm.js since embind is not ready for it yet')
 
1071
    shared.Settings.ASM_JS = 0
 
1072
 
1002
1073
  if shared.Settings.ASM_JS:
1003
1074
    assert opt_level >= 1, 'asm.js requires -O1 or above'
1004
1075
 
1012
1083
      shared.Settings.CORRECT_OVERFLOWS = 1
1013
1084
    assert not shared.Settings.PGO, 'cannot run PGO in ASM_JS mode'
1014
1085
 
1015
 
    if shared.Settings.ASSERTIONS and shared.Settings.ALIASING_FUNCTION_POINTERS:
1016
 
      logging.warning('ALIASING_FUNCTION_POINTERS is on, function pointer comparisons may be invalid across types')
1017
 
 
1018
1086
  if shared.Settings.CORRECT_SIGNS >= 2 or shared.Settings.CORRECT_OVERFLOWS >= 2 or shared.Settings.CORRECT_ROUNDINGS >= 2:
1019
 
    keep_llvm_debug = True # must keep debug info to do line-by-line operations
 
1087
    debug_level = 4 # must keep debug info to do line-by-line operations
1020
1088
 
1021
 
  if (keep_llvm_debug or keep_js_debug) and closure:
 
1089
  if debug_level > 1 and closure:
1022
1090
    logging.warning('disabling closure because debug info was requested')
1023
1091
    closure = False
1024
1092
 
1025
 
  if minify_whitespace is None:
1026
 
    minify_whitespace = opt_level >= 2 and not keep_js_debug
1027
 
 
1028
1093
  assert shared.LLVM_TARGET in shared.COMPILER_OPTS
1029
1094
  if shared.LLVM_TARGET == 'i386-pc-linux-gnu':
1030
1095
    shared.Settings.TARGET_X86 = 1
1037
1102
  else:
1038
1103
    raise Exception('unknown llvm target: ' + str(shared.LLVM_TARGET))
1039
1104
 
 
1105
  if shared.Settings.USE_TYPED_ARRAYS != 2 and llvm_opts > 0:
 
1106
    logging.warning('disabling LLVM optimizations, need typed arrays mode 2 for them')
 
1107
    llvm_opts = 0
 
1108
 
 
1109
  if shared.Settings.MAIN_MODULE:
 
1110
    assert not shared.Settings.SIDE_MODULE
 
1111
    shared.Settings.INCLUDE_FULL_LIBRARY = 1
 
1112
  elif shared.Settings.SIDE_MODULE:
 
1113
    assert not shared.Settings.MAIN_MODULE
 
1114
 
 
1115
  if shared.Settings.MAIN_MODULE or shared.Settings.SIDE_MODULE:
 
1116
    assert not memory_init_file, 'memory init file is not supported with module linking'
 
1117
    shared.Settings.LINKABLE = 1 # TODO: add FORCE_DCE option for the brave people that do want to dce here and in side modules
 
1118
    debug_level = max(debug_level, 2)
 
1119
 
 
1120
  if shared.Settings.ASSERTIONS and shared.Settings.ALIASING_FUNCTION_POINTERS:
 
1121
    logging.warning('ALIASING_FUNCTION_POINTERS is on, function pointer comparisons may be invalid across types')
 
1122
 
 
1123
  if shared.Settings.STB_IMAGE and final_suffix in JS_CONTAINING_SUFFIXES:
 
1124
    input_files.append(shared.path_from_root('third_party', 'stb_image.c'))
 
1125
    shared.Settings.EXPORTED_FUNCTIONS += ['_stbi_load', '_stbi_load_from_memory', '_stbi_image_free']
 
1126
 
 
1127
  if type(shared.Settings.EXPORTED_FUNCTIONS) in (list, tuple):
 
1128
    # always need malloc and free to be kept alive and exported, for internal use and other modules
 
1129
    for required_export in ['_malloc', '_free']:
 
1130
      if required_export not in shared.Settings.EXPORTED_FUNCTIONS:
 
1131
        shared.Settings.EXPORTED_FUNCTIONS.append(required_export)
 
1132
  else:
 
1133
    logging.debug('using response file for EXPORTED_FUNCTIONS, make sure it includes _malloc and _free')
 
1134
 
 
1135
  if shared.Settings.ASM_JS and shared.Settings.DLOPEN_SUPPORT:
 
1136
    assert shared.Settings.DISABLE_EXCEPTION_CATCHING, 'no exceptions support with dlopen in asm yet'
 
1137
 
 
1138
  if proxy_to_worker:
 
1139
    shared.Settings.PROXY_TO_WORKER = 1
 
1140
 
1040
1141
  ## Compile source code to bitcode
1041
1142
 
1042
1143
  logging.debug('compiling to bitcode')
1051
1152
      output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
1052
1153
      temp_files.append(output_file)
1053
1154
      args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
1054
 
      logging.debug("running:" + call + ' '.join(args))
 
1155
      if input_file.endswith(CXX_SUFFIXES):
 
1156
        args += shared.EMSDK_CXX_OPTS
 
1157
      logging.debug("running: " + call + ' ' + ' '.join(args))
1055
1158
      execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
1056
1159
      if not os.path.exists(output_file):
1057
1160
        logging.error('compiler frontend failed to generate LLVM bitcode, halting')
1076
1179
          shared.Building.llvm_as(input_file, temp_file)
1077
1180
          temp_files.append(temp_file)
1078
1181
 
1079
 
  if not LEAVE_INPUTS_RAW: assert len(temp_files) == len(input_files)
 
1182
  if not LEAVE_INPUTS_RAW:
 
1183
    assert len(temp_files) == len(input_files)
 
1184
 
 
1185
    # Optimize source files
 
1186
    if llvm_opts > 0:
 
1187
      for i, input_file in enumerate(input_files):
 
1188
        if input_file.endswith(SOURCE_SUFFIXES):
 
1189
          temp_file = temp_files[i]
 
1190
          logging.debug('optimizing %s with -O%d' % (input_file, llvm_opts))
 
1191
          shared.Building.llvm_opt(temp_file, llvm_opts)
1080
1192
 
1081
1193
  # If we were just asked to generate bitcode, stop there
1082
1194
  if final_suffix not in JS_CONTAINING_SUFFIXES:
1083
 
    if llvm_opts > 0:
1084
 
      if not os.environ.get('EMCC_OPTIMIZE_NORMALLY'):
1085
 
        logging.warning('-Ox flags ignored, since not generating JavaScript')
1086
 
      else:
1087
 
        for input_file in input_files:
1088
 
          if input_file.endswith(SOURCE_SUFFIXES):
1089
 
            logging.debug('optimizing %s with -O%d since EMCC_OPTIMIZE_NORMALLY defined' % (input_file, llvm_opts))
1090
 
            shared.Building.llvm_opt(in_temp(unsuffixed(uniquename(input_file)) + '.o'), llvm_opts)
1091
 
          else:
1092
 
            logging.debug('not optimizing %s despite EMCC_OPTIMIZE_NORMALLY since not source code' % (input_file))
1093
1195
    if not specified_target:
1094
1196
      for input_file in input_files:
1095
1197
        shutil.move(in_temp(unsuffixed(uniquename(input_file)) + '.o'), unsuffixed_basename(input_file) + '.' + final_suffix)
1111
1213
  extra_files_to_link = []
1112
1214
 
1113
1215
  if not LEAVE_INPUTS_RAW and not AUTODEBUG and \
1114
 
     not shared.Settings.BUILD_AS_SHARED_LIB == 2: # shared lib 2 use the library in the parent
 
1216
     not shared.Settings.BUILD_AS_SHARED_LIB == 2 and \
 
1217
     not shared.Settings.SIDE_MODULE: # shared libraries/side modules link no C libraries, need them in parent
 
1218
 
1115
1219
    # Check if we need to include some libraries that we compile. (We implement libc ourselves in js, but
1116
1220
    # compile a malloc implementation and stdlibc++.)
1117
1221
 
1121
1225
        symbols = filter(lambda symbol: symbol not in exclude, symbols)
1122
1226
      return set(symbols)
1123
1227
 
 
1228
    lib_opts = ['-O2']
 
1229
 
1124
1230
    # XXX We also need to add libc symbols that use malloc, for example strdup. It's very rare to use just them and not
1125
1231
    #     a normal malloc symbol (like free, after calling strdup), so we haven't hit this yet, but it is possible.
1126
1232
    libc_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libc.symbols'))
1129
1235
    libcxx_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxx', 'symbols'), exclude=libc_symbols)
1130
1236
    libcxxabi_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxxabi', 'symbols'), exclude=libc_symbols)
1131
1237
 
 
1238
    # XXX we should disable EMCC_DEBUG when building libs, just like in the relooper
 
1239
 
1132
1240
    def build_libc(lib_filename, files):
1133
1241
      o_s = []
1134
1242
      prev_cxx = os.environ.get('EMMAKEN_CXX')
1136
1244
      musl_internal_includes = shared.path_from_root('system', 'lib', 'libc', 'musl', 'src', 'internal')
1137
1245
      for src in files:
1138
1246
        o = in_temp(os.path.basename(src) + '.o')
1139
 
        execute([shared.PYTHON, shared.EMCC, shared.path_from_root('system', 'lib', src), '-o', o, '-I', musl_internal_includes], stdout=stdout, stderr=stderr)
 
1247
        execute([shared.PYTHON, shared.EMCC, shared.path_from_root('system', 'lib', src), '-o', o, '-I', musl_internal_includes] + lib_opts, stdout=stdout, stderr=stderr)
1140
1248
        o_s.append(o)
1141
1249
      if prev_cxx: os.environ['EMMAKEN_CXX'] = prev_cxx
1142
1250
      shared.Building.link(o_s, in_temp(lib_filename))
1147
1255
      for src in files:
1148
1256
        o = in_temp(src + '.o')
1149
1257
        srcfile = shared.path_from_root(src_dirname, src)
1150
 
        execute([shared.PYTHON, shared.EMXX, srcfile, '-o', o, '-std=c++11'], stdout=stdout, stderr=stderr)
 
1258
        execute([shared.PYTHON, shared.EMXX, srcfile, '-o', o, '-std=c++11'] + lib_opts, stdout=stdout, stderr=stderr)
1151
1259
        o_s.append(o)
1152
1260
      shared.Building.link(o_s, in_temp(lib_filename))
1153
1261
      return in_temp(lib_filename)
1168
1276
        os.path.join('libc', 'gen', 'vwarn.c'),
1169
1277
        os.path.join('libc', 'gen', 'vwarnx.c'),
1170
1278
        os.path.join('libc', 'stdlib', 'strtod.c'),
1171
 
      ];
 
1279
      ]
1172
1280
      return build_libc('libc.bc', libc_files)
1173
1281
 
1174
1282
    def apply_libc(need):
1223
1331
          'wctob.c',
1224
1332
          'wctomb.c',
1225
1333
         ]],
 
1334
         ['stdlib', [
 
1335
           'ecvt.c',
 
1336
           'fcvt.c',
 
1337
           'gcvt.c',
 
1338
         ]],
1226
1339
         ['string', [
1227
1340
           'wcpcpy.c',
1228
1341
           'wcpncpy.c',
1319
1432
      return 'SDL_Init' in all_needed and ('malloc' not in all_needed or 'free' not in all_needed)
1320
1433
 
1321
1434
    # Settings this in the environment will avoid checking dependencies and make building big projects a little faster
 
1435
    # 1 means include everything; otherwise it can be the name of a lib (libcxx, etc.)
1322
1436
    force = os.environ.get('EMCC_FORCE_STDLIBS')
 
1437
    force_all = force == '1'
1323
1438
 
1324
1439
    # Scan symbols
1325
1440
    all_needed = set()
1337
1452
                                                  ('libcxxabi', create_libcxxabi, apply_libcxxabi, libcxxabi_symbols),
1338
1453
                                                  ('sdl',       create_sdl,       apply_sdl,       sdl_symbols),
1339
1454
                                                  ('libc',      create_libc,      apply_libc,      libc_symbols)]:
1340
 
      if not force:
 
1455
      force_this = force_all or force == name
 
1456
      if not force_this:
1341
1457
        need = set()
1342
1458
        has = set()
1343
1459
        for symbols in symbolses:
1349
1465
        for haz in has: # remove symbols that are supplied by another of the inputs
1350
1466
          if haz in need:
1351
1467
            need.remove(haz)
1352
 
        logging.debug('considering %s: we need %s and have %s' % (name, str(need), str(has)))
1353
 
      if (force or len(need) > 0) and apply_(need):
1354
 
        # We need to build and link the library in
1355
 
        logging.debug('including %s' % name)
1356
 
        libfile = shared.Cache.get(name, create)
1357
 
        extra_files_to_link.append(libfile)
1358
 
        force = True
 
1468
        if shared.Settings.VERBOSE: logging.debug('considering %s: we need %s and have %s' % (name, str(need), str(has)))
 
1469
      if force_this or len(need) > 0:
 
1470
        force_all = True
 
1471
        if apply_(need):
 
1472
          # We need to build and link the library in
 
1473
          logging.debug('including %s' % name)
 
1474
          libfile = shared.Cache.get(name, create)
 
1475
          extra_files_to_link.append(libfile)
1359
1476
 
1360
1477
  # First, combine the bitcode files if there are several. We must also link if we have a singleton .a
1361
1478
  if len(input_files) + len(extra_files_to_link) > 1 or \
1363
1480
    linker_inputs = temp_files + extra_files_to_link
1364
1481
    logging.debug('linking: ' + str(linker_inputs))
1365
1482
    t0 = time.time()
1366
 
    shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'))
 
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)
1367
1484
    t1 = time.time()
1368
1485
    logging.debug('    linking took %.2f seconds' % (t1 - t0))
1369
1486
    final = in_temp(target_basename + '.bc')
1393
1510
 
1394
1511
  # Optimize, if asked to
1395
1512
  if not LEAVE_INPUTS_RAW:
1396
 
    link_opts = [] if keep_llvm_debug else ['-strip-debug'] # remove LLVM debug info in -O1+, since the optimizer removes it anyhow
1397
 
    if llvm_opts > 0:
1398
 
      if not os.environ.get('EMCC_OPTIMIZE_NORMALLY'):
1399
 
        shared.Building.llvm_opt(in_temp(target_basename + '.bc'), llvm_opts)
1400
 
        if DEBUG: save_intermediate('opt', 'bc')
1401
 
        # Do LTO in a separate pass to work around LLVM bug XXX (see failure e.g. in cubescript)
1402
 
      else:
1403
 
        logging.debug('not running opt because EMCC_OPTIMIZE_NORMALLY was specified, opt should have been run before')
1404
 
    if shared.Building.can_build_standalone():
1405
 
      # If we can LTO, do it before dce, since it opens up dce opportunities
1406
 
      if llvm_lto and shared.Building.can_use_unsafe_opts():
1407
 
        if not shared.Building.can_inline(): link_opts.append('-disable-inlining')
1408
 
        # do not internalize in std-link-opts - it ignores internalize-public-api-list - and add a manual internalize
1409
 
        link_opts += ['-disable-internalize'] + shared.Building.get_safe_internalize() + ['-std-link-opts']
1410
 
      else:
1411
 
        # At minimum remove dead functions etc., this potentially saves a lot in the size of the generated code (and the time to compile it)
1412
 
        link_opts += shared.Building.get_safe_internalize() + ['-globaldce']
1413
 
      shared.Building.llvm_opt(in_temp(target_basename + '.bc'), link_opts)
1414
 
      if DEBUG: save_intermediate('linktime', 'bc')
 
1513
    link_opts = [] if debug_level >= 4 else ['-strip-debug'] # remove LLVM debug if we are not asked for it
 
1514
 
 
1515
    if llvm_lto >= 2:
 
1516
      logging.debug('running LLVM opt -O3 as pre-LTO')
 
1517
      shared.Building.llvm_opt(in_temp(target_basename + '.bc'), ['-O3'])
 
1518
      if DEBUG: save_intermediate('opt', 'bc')
 
1519
 
 
1520
    # If we can LTO, do it before dce, since it opens up dce opportunities
 
1521
    if shared.Building.can_build_standalone() and llvm_lto and llvm_lto != 2 and shared.Building.can_use_unsafe_opts():
 
1522
      if not shared.Building.can_inline(): link_opts.append('-disable-inlining')
 
1523
      # do not internalize in std-link-opts - it ignores internalize-public-api-list - and add a manual internalize
 
1524
      link_opts += ['-disable-internalize'] + shared.Building.get_safe_internalize() + ['-std-link-opts']
 
1525
    else:
 
1526
      # 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
      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')
1415
1530
 
1416
1531
  if save_bc:
1417
1532
    shutil.copyfile(final, save_bc)
1481
1596
    final += '.tr.js'
1482
1597
    posix = True if not shared.WINDOWS else False
1483
1598
    logging.debug('applying transform: %s' % js_transform)
1484
 
    execute(shlex.split(js_transform, posix=posix) + [os.path.abspath(final)])
 
1599
    subprocess.check_call(shlex.split(js_transform, posix=posix) + [os.path.abspath(final)])
1485
1600
    if DEBUG: save_intermediate('transformed')
1486
1601
 
 
1602
  js_transform_tempfiles = [final]
 
1603
 
 
1604
  if memory_init_file:
 
1605
    if shared.Settings.USE_TYPED_ARRAYS != 2:
 
1606
      if type(memory_init_file) == int: logging.warning('memory init file requires typed arrays mode 2')
 
1607
    else:
 
1608
      memfile = target + '.mem'
 
1609
      shared.try_delete(memfile)
 
1610
      def repl(m):
 
1611
        # handle chunking of the memory initializer
 
1612
        s = re.sub('[\[\]\n\(\)\. ]', '', m.groups(0)[0])
 
1613
        s = s.replace('concat', ',')
 
1614
        if s[-1] == ',': s = s[:-1]
 
1615
        open(memfile, 'wb').write(''.join(map(lambda x: chr(int(x or '0')), s.split(','))))
 
1616
        if DEBUG:
 
1617
          # Copy into temp dir as well, so can be run there too
 
1618
          temp_memfile = os.path.join(shared.EMSCRIPTEN_TEMP_DIR, os.path.basename(memfile))
 
1619
          if os.path.abspath(memfile) != os.path.abspath(memfile):
 
1620
            shutil.copyfile(memfile, temp_memfile)
 
1621
        return 'loadMemoryInitializer("%s");' % os.path.basename(memfile)
 
1622
      src = re.sub(shared.JS.memory_initializer_pattern, repl, open(final).read(), count=1)
 
1623
      open(final + '.mem.js', 'w').write(src)
 
1624
      final += '.mem.js'
 
1625
      js_transform_tempfiles[-1] = final # simple text substitution preserves comment line number mappings
 
1626
      if DEBUG:
 
1627
        if os.path.exists(memfile):
 
1628
          save_intermediate('meminit')
 
1629
          logging.debug('wrote memory initialization to %s' % memfile)
 
1630
        else:
 
1631
          logging.debug('did not see memory initialization')
 
1632
 
1487
1633
  # It is useful to run several js optimizer passes together, to save on unneeded unparsing/reparsing
1488
1634
  js_optimizer_queue = []
 
1635
  js_optimizer_extra_info = {}
1489
1636
  def flush_js_optimizer_queue():
1490
 
    global final, js_optimizer_queue
 
1637
    global final, js_optimizer_queue, js_optimizer_extra_info
 
1638
    if len(js_optimizer_extra_info) == 0:
 
1639
      js_optimizer_extra_info = None
1491
1640
    if len(js_optimizer_queue) > 0 and not(len(js_optimizer_queue) == 1 and js_optimizer_queue[0] == 'last'):
1492
1641
      if DEBUG != '2':
1493
1642
        if shared.Settings.ASM_JS:
1494
1643
          js_optimizer_queue = ['asm'] + js_optimizer_queue
1495
1644
        logging.debug('applying js optimization passes: %s', js_optimizer_queue)
1496
 
        final = shared.Building.js_optimizer(final, js_optimizer_queue, jcache)
 
1645
        final = shared.Building.js_optimizer(final, js_optimizer_queue, jcache, debug_level >= 4, js_optimizer_extra_info)
 
1646
        js_transform_tempfiles.append(final)
1497
1647
        if DEBUG: save_intermediate('js_opts')
1498
1648
      else:
1499
1649
        for name in js_optimizer_queue:
1501
1651
          if shared.Settings.ASM_JS:
1502
1652
            passes = ['asm'] + passes
1503
1653
          logging.debug('applying js optimization pass: %s', passes)
1504
 
          final = shared.Building.js_optimizer(final, passes, jcache)
 
1654
          final = shared.Building.js_optimizer(final, passes, jcache, debug_level >= 4, js_optimizer_extra_info)
 
1655
          js_transform_tempfiles.append(final)
1505
1656
          save_intermediate(name)
1506
1657
      js_optimizer_queue = []
 
1658
    js_optimizer_extra_info = {}
1507
1659
 
1508
 
  if opt_level >= 1:
 
1660
  if opt_level >= 1 and js_opts:
1509
1661
    logging.debug('running pre-closure post-opts')
1510
1662
 
1511
1663
    if DEBUG == '2':
1512
1664
      # Clean up the syntax a bit
1513
 
      final = shared.Building.js_optimizer(final, [], jcache)
 
1665
      final = shared.Building.js_optimizer(final, [], jcache, debug_level >= 4)
 
1666
      js_transform_tempfiles.append(final)
1514
1667
      if DEBUG: save_intermediate('pretty')
1515
1668
 
1516
1669
    def get_eliminate():
1519
1672
      else:
1520
1673
        return 'eliminate'
1521
1674
 
1522
 
    js_optimizer_queue += [get_eliminate(), 'simplifyExpressionsPre']
1523
 
 
1524
 
    if shared.Settings.RELOOP and not shared.Settings.ASM_JS:
1525
 
      js_optimizer_queue += ['optimizeShiftsAggressive', get_eliminate()] # aggressive shifts optimization requires loops, it breaks on switches
 
1675
    js_optimizer_queue += [get_eliminate(), 'simplifyExpressions']
1526
1676
 
1527
1677
  if closure and not shared.Settings.ASM_JS:
1528
1678
    flush_js_optimizer_queue()
1529
1679
 
1530
1680
    logging.debug('running closure')
 
1681
    # no need to add this to js_transform_tempfiles, because closure and
 
1682
    # debug_level > 0 are never simultaneously true
1531
1683
    final = shared.Building.closure_compiler(final)
1532
1684
    if DEBUG: save_intermediate('closure')
1533
1685
 
1534
 
  if opt_level >= 1:
1535
 
    logging.debug('running post-closure post-opts')
1536
 
    js_optimizer_queue += ['simplifyExpressionsPost']
1537
 
 
1538
 
  if (not closure or shared.Settings.ASM_JS) and shared.Settings.RELOOP and not keep_js_debug:
1539
 
    # do this if closure is not enabled (it gives similar speedups), and we do not need to keep debug info around
1540
 
    js_optimizer_queue += ['registerize']
1541
 
 
1542
 
  if minify_whitespace:
1543
 
    js_optimizer_queue += ['compress']
1544
 
 
1545
 
  if closure and shared.Settings.ASM_JS: 
1546
 
    js_optimizer_queue += ['closure']
1547
 
 
1548
 
  js_optimizer_queue += ['last']
1549
 
 
1550
 
  flush_js_optimizer_queue()
 
1686
  if js_opts:
 
1687
    if shared.Settings.OUTLINING_LIMIT > 0 and shared.Settings.ASM_JS:
 
1688
      js_optimizer_queue += ['outline']
 
1689
      js_optimizer_extra_info['sizeToOutline'] = shared.Settings.OUTLINING_LIMIT
 
1690
 
 
1691
    if (not closure or shared.Settings.ASM_JS) and shared.Settings.RELOOP and debug_level < 3:
 
1692
      js_optimizer_queue += ['registerize']
 
1693
 
 
1694
    if opt_level > 0:
 
1695
      if debug_level < 2 and shared.Settings.ASM_JS: js_optimizer_queue = map(lambda p: p if p != 'registerize' else 'registerizeAndMinify', js_optimizer_queue)
 
1696
      if debug_level == 0: js_optimizer_queue += ['minifyWhitespace']
 
1697
 
 
1698
    if closure and shared.Settings.ASM_JS: 
 
1699
      js_optimizer_queue += ['closure']
 
1700
 
 
1701
    if not shared.Settings.SIDE_MODULE: js_optimizer_queue += ['last'] # side modules are not finalized until after relocation
 
1702
 
 
1703
    flush_js_optimizer_queue()
1551
1704
 
1552
1705
  # Remove some trivial whitespace # TODO: do not run when compress has already been done on all parts of the code
1553
1706
  src = open(final).read()
1554
1707
  src = re.sub(r'\n+[ \n]*\n+', '\n', src)
1555
1708
  open(final, 'w').write(src)
1556
1709
 
1557
 
  if memory_init_file:
1558
 
    if shared.Settings.USE_TYPED_ARRAYS != 2:
1559
 
      if type(memory_init_file) == int: logging.warning('memory init file requires typed arrays mode 2')
1560
 
    else:
1561
 
      memfile = target + '.mem'
1562
 
      shared.try_delete(memfile)
1563
 
      def repl(m):
1564
 
        # handle chunking of the memory initializer
1565
 
        s = re.sub('[\[\]\n\(\)\. ]', '', m.groups(0)[0])
1566
 
        s = s.replace('concat', ',')
1567
 
        if s[-1] == ',': s = s[:-1]
1568
 
        open(memfile, 'wb').write(''.join(map(lambda x: chr(int(x or '0')), s.split(','))))
1569
 
        if DEBUG:
1570
 
          # Copy into temp dir as well, so can be run there too
1571
 
          temp_memfile = os.path.join(shared.EMSCRIPTEN_TEMP_DIR, os.path.basename(memfile))
1572
 
          if os.path.abspath(memfile) != os.path.abspath(memfile):
1573
 
            shutil.copyfile(memfile, temp_memfile)
1574
 
        return 'loadMemoryInitializer("%s");' % os.path.basename(memfile)
1575
 
      src = re.sub('/\* memory initializer \*/ allocate\(([\d,\.concat\(\)\[\]\\n ]+)"i8", ALLOC_NONE, Runtime\.GLOBAL_BASE\)', repl, src, count=1)
1576
 
      open(final + '.mem.js', 'w').write(src)
1577
 
      final += '.mem.js'
1578
 
      if DEBUG:
1579
 
        if os.path.exists(memfile):
1580
 
          save_intermediate('meminit')
1581
 
          logging.debug('wrote memory initialization to %s' % memfile)
1582
 
        else:
1583
 
          logging.debug('did not see memory initialization')
 
1710
  def generate_source_map(map_file_base_name, offset=0):
 
1711
    jsrun.run_js(shared.path_from_root('tools', 'source-maps', 'sourcemapper.js'),
 
1712
      shared.NODE_JS, js_transform_tempfiles +
 
1713
        ['--sourceRoot', os.getcwd(),
 
1714
         '--mapFileBaseName', map_file_base_name,
 
1715
         '--offset', str(offset)])
1584
1716
 
1585
1717
  # If we were asked to also generate HTML, do that
1586
1718
  if final_suffix == 'html':
1587
1719
    logging.debug('generating HTML')
1588
1720
    shell = open(shell_path).read()
1589
1721
    html = open(target, 'w')
1590
 
    if not Compression.on:
 
1722
    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)
 
1726
    elif not Compression.on:
 
1727
      if debug_level >= 4:
 
1728
        match = re.match('.*?<script[^>]*>{{{ SCRIPT_CODE }}}</script>', shell,
 
1729
            re.DOTALL)
 
1730
        if match is None:
 
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'))
1591
1733
      html.write(shell.replace('{{{ SCRIPT_CODE }}}', open(final).read()))
1592
1734
    else:
1593
1735
      # Compress the main code
1655
1797
    html.close()
1656
1798
  else:
1657
1799
    if split_js_file:
1658
 
        from tools.split import split_javascript_file
1659
 
        split_javascript_file(final, unsuffixed(target), split_js_file)
 
1800
      from tools.split import split_javascript_file
 
1801
      split_javascript_file(final, unsuffixed(target), split_js_file)
1660
1802
    else:
1661
 
        # copy final JS to output
1662
 
        shutil.move(final, target)
 
1803
      if debug_level >= 4: generate_source_map(target)
 
1804
      # copy final JS to output
 
1805
      shutil.move(final, target)
1663
1806
 
1664
1807
  if DEBUG: logging.debug('total time: %.2f seconds' % (time.time() - start_time))
1665
1808