@@ -22,6 +22,7 @@ import {BinaryPlatform, getPlatform} from "./getPlatform.js";
2222import { logDistroInstallInstruction } from "./logDistroInstallInstruction.js" ;
2323import { testCmakeBinary } from "./testCmakeBinary.js" ;
2424import { getCudaNvccPaths } from "./detectAvailableComputeLayers.js" ;
25+ import { detectWindowsBuildTools } from "./detectBuildTools.js" ;
2526
2627const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
2728const buildConfigType : "Release" | "RelWithDebInfo" | "Debug" = "Release" ;
@@ -32,7 +33,7 @@ export async function compileLlamaCpp(buildOptions: BuildOptions, compileOptions
3233 includeBuildOptionsInBinaryFolderName ?: boolean ,
3334 ensureLlamaCppRepoIsCloned ?: boolean ,
3435 downloadCmakeIfNeeded ?: boolean ,
35- ignoreWorkarounds ?: ( "cudaArchitecture" | "reduceParallelBuildThreads" | "singleBuildThread" ) [ ] ,
36+ ignoreWorkarounds ?: ( "cudaArchitecture" | "reduceParallelBuildThreads" | "singleBuildThread" | "avoidWindowsLlvm" ) [ ] ,
3637 envVars ?: typeof process . env ,
3738 ciMode ?: boolean
3839} ) : Promise < void > {
@@ -52,6 +53,9 @@ export async function compileLlamaCpp(buildOptions: BuildOptions, compileOptions
5253 const finalBuildFolderName = includeBuildOptionsInBinaryFolderName
5354 ? buildFolderName . withCustomCmakeOptions
5455 : buildFolderName . withoutCustomCmakeOptions ;
56+ const useWindowsLlvm = ( platform === "win" && ! ignoreWorkarounds . includes ( "avoidWindowsLlvm" ) )
57+ ? areWindowsBuildToolsCapableForLlvmBuild ( await detectWindowsBuildTools ( ) )
58+ : false ;
5559
5660 const outDirectory = path . join ( llamaLocalBuildBinsDirectory , finalBuildFolderName ) ;
5761
@@ -76,8 +80,8 @@ export async function compileLlamaCpp(buildOptions: BuildOptions, compileOptions
7680 await downloadCmakeIfNeeded ( buildOptions . progressLogs ) ;
7781
7882 const cmakePathArgs = await getCmakePathArgs ( ) ;
79- const cmakeGeneratorArgs = getCmakeGeneratorArgs ( buildOptions . platform , buildOptions . arch ) ;
80- const toolchainFile = await getToolchainFileForArch ( buildOptions . arch ) ;
83+ const cmakeGeneratorArgs = getCmakeGeneratorArgs ( buildOptions . platform , buildOptions . arch , useWindowsLlvm ) ;
84+ const toolchainFile = await getToolchainFileForArch ( buildOptions . arch , useWindowsLlvm ) ;
8185 const runtimeVersion = nodeTarget . startsWith ( "v" ) ? nodeTarget . slice ( "v" . length ) : nodeTarget ;
8286 const cmakeCustomOptions = new Map ( buildOptions . customCmakeOptions ) ;
8387
@@ -306,6 +310,20 @@ export async function compileLlamaCpp(buildOptions: BuildOptions, compileOptions
306310 chalk . yellow ( "To resolve errors related to Vulkan compilation, see the Vulkan guide: " ) +
307311 documentationPageUrls . Vulkan
308312 ) ;
313+ else if ( useWindowsLlvm ) {
314+ if ( buildOptions . progressLogs )
315+ console . info ( getConsoleLogPrefix ( true ) + "Trying to compile again without LLVM" ) ;
316+
317+ try {
318+ return await compileLlamaCpp ( buildOptions , {
319+ ...compileOptions ,
320+ ignoreWorkarounds : [ ...ignoreWorkarounds , "avoidWindowsLlvm" ]
321+ } ) ;
322+ } catch ( err ) {
323+ if ( buildOptions . progressLogs )
324+ console . error ( getConsoleLogPrefix ( true , false ) , err ) ;
325+ }
326+ }
309327
310328 throw err ;
311329 }
@@ -498,14 +516,20 @@ async function getCmakePathArgs() {
498516 return [ "--cmake-path" , cmakePath ] ;
499517}
500518
501- async function getToolchainFileForArch ( targetArch : string ) {
502- if ( process . arch === targetArch || ( process . platform === "win32" && process . arch === "arm64" ) )
519+ async function getToolchainFileForArch ( targetArch : string , windowsLlvmSupport : boolean = false ) {
520+ let toolchainPrefix = "" ;
521+
522+ if ( process . platform === "win32" && process . arch === "arm64" ) {
523+ // a toolchain is needed to cross-compile to arm64 on Windows, and to compile on arm64 on Windows
524+ } else if ( process . platform === "win32" && process . arch === "x64" && targetArch === "x64" && windowsLlvmSupport ) {
525+ toolchainPrefix = "llvm." ;
526+ } else if ( process . arch === targetArch )
503527 return null ;
504528
505529 const platform = process . platform ;
506530 const hostArch = process . arch ;
507531
508- const toolchainFilename = `${ platform } .host-${ hostArch } .target-${ targetArch } .cmake` ;
532+ const toolchainFilename = `${ toolchainPrefix } ${ platform } .host-${ hostArch } .target-${ targetArch } .cmake` ;
509533
510534 const filePath = path . join ( llamaToolchainsDirectory , toolchainFilename ) ;
511535
@@ -515,9 +539,11 @@ async function getToolchainFileForArch(targetArch: string) {
515539 return null ;
516540}
517541
518- function getCmakeGeneratorArgs ( targetPlatform : BinaryPlatform , targetArch : string ) {
542+ function getCmakeGeneratorArgs ( targetPlatform : BinaryPlatform , targetArch : string , windowsLlvmSupport : boolean ) {
519543 if ( targetPlatform === "win" && targetArch === "arm64" )
520544 return [ "--generator" , "Ninja Multi-Config" ] ;
545+ else if ( windowsLlvmSupport && targetPlatform === "win" && process . arch === "x64" && targetArch === "x64" )
546+ return [ "--generator" , "Ninja Multi-Config" ] ;
521547
522548 return [ ] ;
523549}
@@ -544,3 +570,7 @@ function reduceParallelBuildThreads(originalParallelBuildThreads: number) {
544570function isCmakeValueOff ( value ?: string ) {
545571 return value === "OFF" || value === "0" ;
546572}
573+
574+ function areWindowsBuildToolsCapableForLlvmBuild ( detectedBuildTools : Awaited < ReturnType < typeof detectWindowsBuildTools > > ) {
575+ return detectedBuildTools . hasLlvm && detectedBuildTools . hasNinja && detectedBuildTools . hasLibExe ;
576+ }
0 commit comments