@@ -762,6 +762,7 @@ function checkBuildTools() {
762762 const tools = {
763763 cmake : 'CMake' ,
764764 ninja : 'Ninja' ,
765+ mold : 'Mold Linker' ,
765766 make : 'Make' ,
766767 git : 'Git' ,
767768 }
@@ -781,6 +782,117 @@ function checkBuildTools() {
781782 return results
782783}
783784
785+ /**
786+ * Install build tools (ninja and mold).
787+ */
788+ async function installBuildTools ( ) {
789+ if ( CHECK_ONLY ) {
790+ logInfo ( 'Skipping build tools installation (check-only mode)' )
791+ return false
792+ }
793+
794+ logInfo ( 'Installing build tools (ninja, mold)...' )
795+
796+ try {
797+ if ( PLATFORM === 'darwin' ) {
798+ if ( ! commandExists ( 'brew' ) ) {
799+ logError ( 'Homebrew not found. Install from: https://brew.sh/' )
800+ return false
801+ }
802+
803+ // Install ninja.
804+ if ( ! commandExists ( 'ninja' ) ) {
805+ logInfo ( 'Installing ninja...' )
806+ if ( ! exec ( 'brew install ninja' ) ) {
807+ logWarn ( 'Failed to install ninja via brew' )
808+ }
809+ }
810+
811+ // Install mold (not available on macOS via brew, use lld instead).
812+ if ( ! commandExists ( 'mold' ) && ! commandExists ( 'ld64.lld' ) ) {
813+ logInfo ( 'Installing llvm (includes lld linker)...' )
814+ if ( ! exec ( 'brew install llvm' ) ) {
815+ logWarn ( 'Failed to install llvm via brew' )
816+ }
817+ }
818+
819+ return true
820+ }
821+
822+ if ( PLATFORM === 'linux' ) {
823+ // Try apt-get first.
824+ if ( commandExists ( 'apt-get' ) ) {
825+ const packages = [ ]
826+ if ( ! commandExists ( 'ninja' ) ) {
827+ packages . push ( 'ninja-build' )
828+ }
829+ if ( ! commandExists ( 'mold' ) ) {
830+ packages . push ( 'mold' )
831+ }
832+
833+ if ( packages . length ) {
834+ logInfo ( `Installing ${ packages . join ( ', ' ) } ...` )
835+ return (
836+ exec ( 'sudo apt-get update' ) &&
837+ exec ( `sudo apt-get install -y ${ packages . join ( ' ' ) } ` )
838+ )
839+ }
840+ return true
841+ }
842+
843+ // Try yum.
844+ if ( commandExists ( 'yum' ) ) {
845+ const packages = [ ]
846+ if ( ! commandExists ( 'ninja' ) ) {
847+ packages . push ( 'ninja-build' )
848+ }
849+ // mold not available in default yum repos, user needs to build from source.
850+
851+ if ( packages . length ) {
852+ logInfo ( `Installing ${ packages . join ( ', ' ) } ...` )
853+ return exec ( `sudo yum install -y ${ packages . join ( ' ' ) } ` )
854+ }
855+ return true
856+ }
857+
858+ logError ( 'No supported package manager found' )
859+ return false
860+ }
861+
862+ if ( PLATFORM === 'win32' ) {
863+ if ( commandExists ( 'choco' ) ) {
864+ if ( ! commandExists ( 'ninja' ) ) {
865+ logInfo ( 'Installing ninja...' )
866+ if ( ! exec ( 'choco install -y ninja' ) ) {
867+ logWarn ( 'Failed to install ninja via choco' )
868+ }
869+ }
870+ // mold not available on Windows, will use MSVC linker.
871+ return true
872+ }
873+
874+ if ( commandExists ( 'winget' ) ) {
875+ if ( ! commandExists ( 'ninja' ) ) {
876+ logInfo ( 'Installing ninja...' )
877+ if ( ! exec ( 'winget install Ninja-build.ninja' ) ) {
878+ logWarn ( 'Failed to install ninja via winget' )
879+ }
880+ }
881+ return true
882+ }
883+
884+ logError ( 'No supported package manager found' )
885+ return false
886+ }
887+
888+ logError ( `Unsupported platform: ${ PLATFORM } ` )
889+ return false
890+ } catch ( error ) {
891+ logError ( `Failed to install build tools: ${ error . message } ` )
892+ return false
893+ }
894+ }
895+
784896/**
785897 * Create environment activation script.
786898 */
@@ -923,6 +1035,13 @@ async function main() {
9231035 log ( '' )
9241036 }
9251037
1038+ // Install build tools (ninja, mold) after platform installers are ready.
1039+ const buildToolsCheck = checkBuildTools ( )
1040+ if ( ! buildToolsCheck . ninja || ! buildToolsCheck . mold ) {
1041+ await installBuildTools ( )
1042+ log ( '' )
1043+ }
1044+
9261045 // Create activation script.
9271046 await createActivationScript ( )
9281047
0 commit comments