Skip to content

Instantly share code, notes, and snippets.

@ichadhr
Created December 21, 2025 23:42
Show Gist options
  • Select an option

  • Save ichadhr/5d4c7b9c86558846067986078ac782b3 to your computer and use it in GitHub Desktop.

Select an option

Save ichadhr/5d4c7b9c86558846067986078ac782b3 to your computer and use it in GitHub Desktop.
Windows build ik_llama.cpp (fork of llama.cpp)
<#
install_ik_llama.ps1
--------------------
Installs all prerequisites and builds ikawrakow/ik_llama.cpp on Windows.
• Works on Windows PowerShell 5 and PowerShell 7
• Uses the Ninja generator (fast, no VS-integration dependency)
• Re-usable: just run the script; it installs only what is missing
• Supports CUDA 12.4+ and 13.x
• Pass -CudaArch <SM> to target a different GPU
(auto-detects if not specified; defaults to 86 = RTX-30-series; GTX-1070 = 61, Ada = 89, etc.)
#>
[CmdletBinding()]
param(
[int] $CudaArch,
[switch]$SkipBuild
)
$ScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Definition
$RepoDir = Join-Path $ScriptRoot 'vendor\ik_llama.cpp'
# ---------------------------------------------------------------------------
# Helper functions
# ---------------------------------------------------------------------------
function Assert-Admin {
$id = [Security.Principal.WindowsIdentity]::GetCurrent()
$prn = New-Object Security.Principal.WindowsPrincipal($id)
if (-not $prn.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
throw "Run this script from an *elevated* PowerShell window."
}
}
function Test-Command ([string]$Name) {
$null -ne (Get-Command $Name -ErrorAction SilentlyContinue)
}
function Test-VSTools {
$vswhere = Join-Path ${Env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe'
if (-not (Test-Path $vswhere)) { return $false }
$path = & $vswhere -latest -products * `
-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
-property installationPath 2>$null
-not [string]::IsNullOrWhiteSpace($path)
}
function Test-CUDA {
$root = 'C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA'
if (-not (Test-Path $root)) { return $false }
foreach ($d in Get-ChildItem $root -Directory) {
if ($d.Name -match '^v(12|13)\.(\d+)$') {
$major = [int]$Matches[1]
$minor = [int]$Matches[2]
if ($major -gt 12 -or ($major -eq 12 -and $minor -ge 4)) { return $true }
}
}
return $false
}
function Wait-Until ($TestFn, [int]$TimeoutMin, [string]$What) {
Write-Host " waiting for $What ..."
$sw = [Diagnostics.Stopwatch]::StartNew()
while ($sw.Elapsed.TotalMinutes -lt $TimeoutMin) {
if (& $TestFn) { return }
Start-Sleep 30
}
throw "$What did not finish installing in $TimeoutMin minutes."
}
function Wait-VSToolsReady {
try {
Wait-Until { Test-VSTools } 10 "VS Build Tools"
return $true
} catch {
return $false
}
}
function Wait-CUDAReady {
try {
Wait-Until { Test-CUDA } 10 "CUDA Toolkit"
return $true
} catch {
return $false
}
}
function Install-Winget ([string]$Id, [string]$Override = '') {
Write-Host "-> installing $Id ..."
$wingetArgs = @(
'install', '--id', $Id, '--silent', '--disable-interactivity',
'--accept-source-agreements', '--accept-package-agreements', '-e', '--wait'
)
if ($Override) { $wingetArgs += @('--override', "`"$Override`"") }
$p = Start-Process winget -ArgumentList $wingetArgs -NoNewWindow -Wait -PassThru
# -1978335189 (0x8A150005) = "no applicable upgrade found"
if ($p.ExitCode -and $p.ExitCode -ne -1978335189) {
throw "winget failed (exit $($p.ExitCode)) while installing $Id"
}
}
function Install-VSTools {
Write-Host "-> downloading and installing VS 2022 Build Tools ..."
$url = 'https://aka.ms/vs/17/release/vs_BuildTools.exe'
$exe = Join-Path $env:TEMP 'vs_BuildTools.exe'
Invoke-WebRequest -Uri $url -OutFile $exe
$vsArgs = '--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --quiet --norestart --wait'
$p = Start-Process -FilePath $exe -ArgumentList $vsArgs -Wait -PassThru
if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) {
throw "VS Build Tools installer failed with exit code $($p.ExitCode)."
}
}
# Bring MSVC variables (cl, link, lib paths, etc.) into this PowerShell session
function Import-VSEnv {
$vswhere = Join-Path ${Env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe'
$vsroot = & $vswhere -latest -products * `
-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
-property installationPath 2>$null
if (-not $vsroot) { throw "VS Build Tools not found." }
$vcvars = Join-Path $vsroot 'VC\Auxiliary\Build\vcvars64.bat'
Write-Host " importing MSVC environment from $vcvars"
$envDump = cmd /s /c "`"$vcvars`" && set"
foreach ($line in $envDump -split "`r?`n") {
if ($line -match '^(.*?)=(.*)$') {
$name, $value = $Matches[1], $Matches[2]
Set-Item -Path "Env:$name" -Value $value
}
}
}
# Select newest CUDA >=12.4, export env, return CMake arg
function Use-LatestCuda {
$root = 'C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA'
$latest = Get-ChildItem $root -Directory |
Where-Object { $_.Name -match '^v(12|13)\.(\d+)$' -and
($Matches[1] -gt 12 -or ($Matches[1] -eq 12 -and $Matches[2] -ge 4)) } |
Sort-Object { [version]($_.Name -replace '^v') } -Descending |
Select-Object -First 1
if (-not $latest) { throw 'No CUDA >=12.4 installation found.' }
$env:CUDA_PATH = $latest.FullName
$version = $latest.Name -replace '^v'
$major, $minor = $version -split '\.'
Set-Item -Path ("Env:CUDA_PATH_V${major}_${minor}") -Value $latest.FullName
$env:Path = "$($latest.FullName)\bin;$env:Path"
Write-Host " Using CUDA toolkit at $($env:CUDA_PATH)"
"-DCUDAToolkit_ROOT=$($latest.FullName)"
}
function Get-CudaArch {
try {
$computeCap = nvidia-smi --query-gpu=compute_cap --format=csv,noheader,nounits 2>$null | Select-Object -First 1
if ($computeCap) {
$major, $minor = $computeCap -split '\.'
$sm = [int]($major + $minor.PadLeft(1, '0'))
Write-Host "Detected CUDA architecture: $sm"
return $sm
}
} catch {}
Write-Host "Could not detect CUDA architecture, using default 86"
return 86
}
# ---------------------------------------------------------------------------
# Main routine
# ---------------------------------------------------------------------------
Assert-Admin
if (-not $PSBoundParameters.ContainsKey('CudaArch')) {
$CudaArch = Get-CudaArch
}
$reqs = @(
@{Name = 'Git'; Test = { Test-Command git }; Id = 'Git.Git' },
@{Name = 'CMake'; Test = { Test-Command cmake }; Id = 'Kitware.CMake' },
@{Name = 'Ninja'; Test = { Test-Command ninja }; Id = 'Kitware.Ninja' },
@{Name = 'VS Build Tools'; Test = { Test-VSTools };
Id = 'Microsoft.VisualStudio.2022.BuildTools';
Override = '--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --quiet --norestart'
},
@{Name = 'CUDA Toolkit >=12.4'; Test = { Test-CUDA }; Id = 'Nvidia.CUDA' }
)
foreach ($r in $reqs) {
if (-not (& $r.Test)) {
if ($r.Name -eq 'VS Build Tools') {
Install-VSTools
if (-not (Wait-VSToolsReady)) { throw 'VS Build Tools install timed out.' }
}
else {
Install-Winget -Id $r.Id -Override $r.Override
if ($r.Name -eq 'CUDA Toolkit >=12.4') {
if (-not (Wait-CUDAReady)) { throw 'CUDA install timed out.' }
}
elseif (-not (& $r.Test)) {
throw "$($r.Name) could not be installed automatically."
}
}
}
Write-Host ("[OK] {0}" -f $r.Name)
}
if (-not $PSBoundParameters.ContainsKey('CudaArch')) {
# Set CUDA environment to make nvidia-smi available
$null = Use-LatestCuda
$CudaArch = Get-CudaArch
}
Import-VSEnv # make cl.exe etc. available in this session
# Clone or update repo
if (-not (Test-Path $RepoDir)) {
Write-Host "-> cloning ik_llama.cpp into $RepoDir"
git clone https://github.com/ikawrakow/ik_llama.cpp $RepoDir
}
else {
Write-Host "-> updating existing ik_llama.cpp in $RepoDir"
git -C $RepoDir pull --ff-only
}
if ($SkipBuild) { Write-Host 'SkipBuild set – done.'; return }
# Configure & build
$cudaRootArg = Use-LatestCuda
$build = Join-Path $RepoDir 'build'
New-Item $build -ItemType Directory -Force | Out-Null
$cmakeArgs = @(
'-G', 'Ninja',
'-DGGML_CUDA=ON',
'-DGGML_CUBLAS=ON',
'-DCMAKE_BUILD_TYPE=Release',
"-DCMAKE_CUDA_ARCHITECTURES=$CudaArch",
$cudaRootArg
)
Push-Location $build
Write-Host '-> generating solution ...'
cmake .. @cmakeArgs
Write-Host '-> building (Release) ...'
cmake --build . --config Release --target llama-server llama-batched-bench llama-cli llama-bench --parallel
Pop-Location
Write-Host ''
Write-Host ("Done! Binaries are in: ""{0}""." -f (Join-Path $build 'bin'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment