| |
| """wrapper around emcc link step. |
| |
| This wrapper currently serves the following purposes. |
| |
| 1. When building with --config=wasm the final output is multiple files, usually |
| at least one .js and one .wasm file. Since the cc_binary link step only |
| allows a single output, we must tar up the outputs into a single file. |
| |
| 2. Add quotes around arguments that need them in the response file to work |
| around a bazel quirk. |
| |
| 3. Ensure the external_debug_info section of the wasm points at the correct |
| bazel path. |
| """ |
|
|
|
|
| import argparse |
| import os |
| import subprocess |
| import sys |
|
|
| |
| assert sys.argv[1][0] == '@', sys.argv |
| param_filename = sys.argv[1][1:] |
| param_file_args = [line.strip() for line in open(param_filename).readlines()] |
|
|
| |
| if any(' ' in a for a in param_file_args): |
| new_param_filename = param_filename + '.modified' |
| with open(new_param_filename, 'w') as f: |
| for param in param_file_args: |
| if ' ' in param: |
| f.write('"%s"' % param) |
| else: |
| f.write(param) |
| f.write('\n') |
| sys.argv[1] = '@' + new_param_filename |
|
|
| emcc_py = os.path.join(os.environ['EMSCRIPTEN'], 'emcc.py') |
| rtn = subprocess.call([sys.executable, emcc_py] + sys.argv[1:]) |
| if rtn != 0: |
| sys.exit(1) |
|
|
| |
| |
| parser = argparse.ArgumentParser(add_help=False) |
| parser.add_argument('-o') |
| parser.add_argument('--oformat') |
| options = parser.parse_known_args(param_file_args)[0] |
| output_file = options.o |
| oformat = options.oformat |
| outdir = os.path.normpath(os.path.dirname(output_file)) |
| base_name = os.path.basename(output_file) |
|
|
| |
| |
| if oformat is not None: |
| base_name_split = os.path.splitext(base_name) |
|
|
| |
| if not base_name_split[1]: |
| os.replace(output_file, output_file + '.' + oformat) |
|
|
| |
| |
| elif base_name_split[1] == '.' + oformat: |
| base_name = base_name_split[0] |
|
|
| |
| |
| |
| |
| |
| |
| |
| else: |
| base_name = base_name_split[0] |
| os.replace(output_file, os.path.join(outdir, base_name + '.' + oformat)) |
|
|
| files = [] |
| extensions = [ |
| '.js', |
| '.wasm', |
| '.wasm.map', |
| '.data', |
| '.js.symbols', |
| '.wasm.debug.wasm', |
| '.html', |
| '.ts', |
| '.d.ts', |
| ] |
|
|
| for ext in extensions: |
| filename = base_name + ext |
| if os.path.exists(os.path.join(outdir, filename)): |
| files.append(filename) |
|
|
| wasm_base = os.path.join(outdir, base_name + '.wasm') |
| if os.path.exists(wasm_base + '.debug.wasm') and os.path.exists(wasm_base): |
| |
| |
| |
|
|
| llvm_objcopy = os.path.join( |
| os.environ['EM_BIN_PATH'], 'bin/llvm-objcopy') |
| |
| |
| rtn = subprocess.call([ |
| llvm_objcopy, |
| '--dump-section=external_debug_info=/dev/null', |
| wasm_base], stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| if rtn == 0: |
| |
| |
|
|
| |
| |
| bit_string = '{0:b}'.format(len(base_name + '.wasm.debug.wasm')) |
|
|
| |
| while len(bit_string) % 7 != 0: |
| bit_string = '0' + bit_string |
|
|
| |
| |
| final_bytes = bytearray() |
| for i in reversed(range(0, len(bit_string), 7)): |
| binary_part = bit_string[i:i + 7] |
| if i != 0: |
| |
| |
| binary_part = '1' + binary_part |
| final_bytes.append(int(binary_part, 2)) |
| |
| final_bytes.extend((base_name + '.wasm.debug.wasm').encode()) |
|
|
| |
| with open(base_name + '_debugsection.tmp', 'wb+') as f: |
| f.write(final_bytes) |
| f.close() |
|
|
| |
| subprocess.check_call([ |
| llvm_objcopy, |
| wasm_base, |
| '--remove-section=external_debug_info']) |
| |
| subprocess.check_call([ |
| llvm_objcopy, |
| wasm_base, |
| '--add-section=external_debug_info=' + base_name + '_debugsection.tmp']) |
|
|
| |
| if not files: |
| print('emcc.py did not appear to output any known files!') |
| sys.exit(1) |
|
|
| |
| cmd = ['tar', 'cf', base_name + '.tar'] + files |
| subprocess.check_call(cmd, cwd=outdir) |
| os.replace(os.path.join(outdir, base_name + '.tar'), output_file) |
|
|
| sys.exit(0) |
|
|