Run emcc link as subprocess with verbose output to capture wasm-ld command. Uses EMCC_VERBOSE=1 to make emcc print the wasm-ld command to stderr, then saves it (with placeholders) for future fast re-linking via _fast_link(). This is a one-time operation per build directory — subsequent
(
emcc_args: list[str],
sketch_object: Path,
cached_wasm: Path,
build_dir: Path,
cwd: str,
mode: str,
library_archive: Path | None = None,
)
| 1264 | |
| 1265 | |
| 1266 | def _intercept_emcc_link( |
| 1267 | emcc_args: list[str], |
| 1268 | sketch_object: Path, |
| 1269 | cached_wasm: Path, |
| 1270 | build_dir: Path, |
| 1271 | cwd: str, |
| 1272 | mode: str, |
| 1273 | library_archive: Path | None = None, |
| 1274 | ) -> int: |
| 1275 | """Run emcc link as subprocess with verbose output to capture wasm-ld command. |
| 1276 | |
| 1277 | Uses EMCC_VERBOSE=1 to make emcc print the wasm-ld command to stderr, |
| 1278 | then saves it (with placeholders) for future fast re-linking via _fast_link(). |
| 1279 | |
| 1280 | This is a one-time operation per build directory — subsequent links use |
| 1281 | _fast_link() which runs wasm-ld directly (~0.2s vs ~1.1s). |
| 1282 | """ |
| 1283 | from ci.wasm_tools import get_emcc |
| 1284 | |
| 1285 | emcc = get_emcc() |
| 1286 | |
| 1287 | # Set up env to capture wasm-ld command and preserve temp files |
| 1288 | emcc_tmp = build_dir / "emcc_tmp" |
| 1289 | emcc_tmp.mkdir(parents=True, exist_ok=True) |
| 1290 | env = os.environ.copy() |
| 1291 | env["EMCC_VERBOSE"] = "1" |
| 1292 | env["EMCC_DEBUG"] = "1" # preserves temp files (js_symbols stub) |
| 1293 | env["EMCC_TEMP_DIR"] = str(emcc_tmp) |
| 1294 | env["EM_FORCE_RESPONSE_FILES"] = "0" # ensure full command, no @file |
| 1295 | |
| 1296 | result = subprocess.run( |
| 1297 | [emcc] + emcc_args, |
| 1298 | cwd=cwd, |
| 1299 | stderr=subprocess.PIPE, |
| 1300 | text=True, |
| 1301 | env=env, |
| 1302 | ) |
| 1303 | |
| 1304 | if result.returncode != 0: |
| 1305 | # Print captured stderr so user sees the error |
| 1306 | if result.stderr: |
| 1307 | print(result.stderr, file=sys.stderr, end="") |
| 1308 | return result.returncode |
| 1309 | |
| 1310 | # Parse wasm-ld command from verbose output |
| 1311 | wasm_ld_cmd = _parse_wasm_ld_from_verbose(result.stderr) |
| 1312 | if wasm_ld_cmd is None: |
| 1313 | print("[WASM] Warning: could not capture wasm-ld command from verbose output") |
| 1314 | return 0 # link succeeded, just can't cache the fast path |
| 1315 | |
| 1316 | # Copy js_symbols stub from temp dir to build_dir for persistence |
| 1317 | emcc_temp_dir = emcc_tmp / "emscripten_temp" |
| 1318 | cached_stub = build_dir / "libemscripten_js_symbols.so" |
| 1319 | for i, arg in enumerate(wasm_ld_cmd): |
| 1320 | if "js_symbols" in arg: |
| 1321 | stub_src = Path(arg) |
| 1322 | if stub_src.exists(): |
| 1323 | shutil.copy2(str(stub_src), str(cached_stub)) |
no test coverage detected