@@ -392,7 +392,7 @@ def _ci_group(title: str):
392392
393393
394394# ---------------------------------------------------------------------------
395- # Plan: download host tools (clang-format, clang-tidy static binaries)
395+ # Plan: download host tools (clang-format, clang-tidy static binaries, mold linker )
396396# ---------------------------------------------------------------------------
397397
398398def download_host_tools_plan (host : HostInfo , base_dir : Path ) -> BuildPlan :
@@ -449,6 +449,55 @@ def _up_to_date(p=tool_path, s=stamp_path, sid=stamp_id) -> bool:
449449 skip_reason = f"stamp already at { stamp_id } " ,
450450 ))
451451
452+ # mold linker (Linux hosts only)
453+ if host .os == "linux" :
454+ mold_ver = "2.41.0"
455+ mold_stamp_id = f"v{ mold_ver } "
456+ mold_arch = host .arch # "x86_64" or "aarch64"
457+ mold_tarball = f"mold-{ mold_ver } -{ mold_arch } -linux.tar.gz"
458+ mold_url = (
459+ f"https://github.com/rui314/mold/releases/download"
460+ f"/v{ mold_ver } /{ mold_tarball } "
461+ )
462+ mold_path = bin_dir / "mold"
463+ mold_stamp_path = bin_dir / "mold.version"
464+
465+ def _mold_up_to_date (p = mold_path , s = mold_stamp_path , sid = mold_stamp_id ) -> bool :
466+ return p .exists () and s .exists () and s .read_text ().strip () == sid
467+
468+ def _download_mold (
469+ bd = bin_dir , url = mold_url , ver = mold_ver , arch = mold_arch ,
470+ p = mold_path , s = mold_stamp_path , sid = mold_stamp_id ,
471+ ) -> None :
472+ install_dir = bd .parent # multi_build/compilers/
473+ tarball = install_dir / f"mold-{ ver } -{ arch } -linux.tar.gz"
474+ subprocess .run (["wget" , url , "-q" , "-O" , str (tarball )], check = True )
475+ # Extract bin/, lib/, and libexec/ — skip share/ (docs only).
476+ # --strip-components=1 drops the top-level "mold-X.Y.Z-arch-linux/"
477+ # prefix so bin/mold lands at multi_build/compilers/bin/mold and
478+ # mold can find lib/mold/mold-wrapper.so and libexec/mold/ld via
479+ # relative paths from its own location.
480+ subprocess .run (
481+ [
482+ "tar" , "xf" , str (tarball ),
483+ "-C" , str (install_dir ),
484+ "--strip-components=1" ,
485+ "--exclude=*/share" ,
486+ ],
487+ check = True ,
488+ )
489+ tarball .unlink (missing_ok = True )
490+ p .chmod (p .stat ().st_mode | 0o111 )
491+ s .write_text (sid )
492+
493+ plan .add (PythonStep (
494+ name = "download-mold" ,
495+ fn = _download_mold ,
496+ description = f"Download and extract mold v{ mold_ver } ({ mold_arch } -linux)" ,
497+ skip_if = _mold_up_to_date ,
498+ skip_reason = f"mold already at { mold_stamp_id } " ,
499+ ))
500+
452501 return plan
453502
454503
@@ -1113,6 +1162,8 @@ def _env_for_target(target: TargetSpec, host: HostInfo, base_dir: Path) -> dict[
11131162 return env
11141163
11151164 env .update (_base_env (target , host , base_dir ))
1165+ compilers_bin = base_dir / "multi_build/compilers/bin"
1166+ env ["PATH" ] = f"{ compilers_bin } :{ os .environ .get ('PATH' , '' )} "
11161167
11171168 if target .platform == "web" :
11181169 default_root = base_dir / "multi_build/compilers/emsdk"
@@ -1172,7 +1223,7 @@ def _env_for_target(target: TargetSpec, host: HostInfo, base_dir: Path) -> dict[
11721223 toolchain_sysroot = toolchain_root / toolchain_prefix / "sysroot"
11731224 env ["TOOLCHAIN_ROOT" ] = str (toolchain_root )
11741225 env ["TOOLCHAIN_SYSROOT" ] = str (toolchain_sysroot )
1175- env ["PATH" ] = f"{ toolchain_root / 'bin' } :{ os . environ .get ('PATH' , '' )} "
1226+ env ["PATH" ] = f"{ toolchain_root / 'bin' } :{ env .get ('PATH' , '' )} "
11761227
11771228 return env
11781229
0 commit comments