Mercurial
view third_party/emsdk/bazel/emscripten_toolchain/link_wrapper.py @ 279:b3b547563ec7
Add Google connector service and agent wiki
Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code.
Co-authored-by: Copilot <[email protected]>
Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 17 Aug 2026 22:22:36 -0700 |
| parents | 8d17f6e6e290 |
| children |
line wrap: on
line source
#!/usr/bin/env python """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 # Only argument should be @path/to/parameter/file 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()] # Re-write response file if needed. 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) # Parse the arguments that we gave to the linker to determine what the output # file is named and what the output format is. 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) # The output file name is the name of the build rule that was built. # Add an appropriate file extension based on --oformat. if oformat is not None: base_name_split = os.path.splitext(base_name) # If the output name has no extension, give it the appropriate extension. if not base_name_split[1]: os.replace(output_file, output_file + '.' + oformat) # If the output name does have an extension and it matches the output format, # change the base_name so it doesn't have an extension. elif base_name_split[1] == '.' + oformat: base_name = base_name_split[0] # If the output name does have an extension and it does not match the output # format, change the base_name so it doesn't have an extension and rename # the output_file so it has the proper extension. # Note that if you do something like name your build rule "foo.js" and pass # "--oformat=html", emscripten will write to the same file for both the js and # html output, overwriting the js output entirely with the html. # Please don't do that. 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', ] 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): # If we have a .wasm.debug.wasm file and a .wasm file, we need to rewrite the # section in the .wasm file that refers to it. The path that's in there # is the blaze output path; we want it to be just the filename. llvm_objcopy = os.path.join( os.environ['EM_BIN_PATH'], 'bin/llvm-objcopy') # First, check to make sure the .wasm file has the header that needs to be # rewritten. rtn = subprocess.call([ llvm_objcopy, '--dump-section=external_debug_info=/dev/null', wasm_base], stdout=subprocess.PIPE, stderr=subprocess.PIPE) if rtn == 0: # If llvm-objcopy did not return an error, the external_debug_info section # must exist, so we're good to continue. # Next we need to convert length of the filename to LEB128. # Start by converting the length of the filename to a bit string. bit_string = '{0:b}'.format(len(base_name + '.wasm.debug.wasm')) # Pad the bit string with 0s so that its length is a multiple of 7. while len(bit_string) % 7 != 0: bit_string = '0' + bit_string # Break up our bit string into chunks of 7. # We do this backwards because the final format is little-endian. final_bytes = bytearray() for i in reversed(range(0, len(bit_string), 7)): binary_part = bit_string[i:i + 7] if i != 0: # Every chunk except the last one needs to be prepended with '1'. # The length of each chunk is 7, so that one has an implicit '0'. binary_part = '1' + binary_part final_bytes.append(int(binary_part, 2)) # Finally, add the actual filename. final_bytes.extend((base_name + '.wasm.debug.wasm').encode()) # Write our length + filename bytes to a temp file. with open(base_name + '_debugsection.tmp', 'wb+') as f: f.write(final_bytes) f.close() # First delete the old section. subprocess.check_call([ llvm_objcopy, wasm_base, '--remove-section=external_debug_info']) # Rewrite section with the new size and filename from the temp file. subprocess.check_call([ llvm_objcopy, wasm_base, '--add-section=external_debug_info=' + base_name + '_debugsection.tmp']) # Make sure we have at least one output file. if not files: print('emcc.py did not appear to output any known files!') sys.exit(1) # cc_binary must output exactly one file; put all the output files in a tarball. 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)