gen_windows.ps1 9.69 KB
Newer Older
1
2
3
4
#!powershell

$ErrorActionPreference = "Stop"

Daniel Hiltgen's avatar
Daniel Hiltgen committed
5
6
7
8
9
10
11
12
13
14
15
function amdGPUs {
    if ($env:AMDGPU_TARGETS) {
        return $env:AMDGPU_TARGETS
    }
    # TODO - load from some common data file for linux + windows build consistency
    $GPU_LIST = @(
        "gfx900"
        "gfx906:xnack-"
        "gfx908:xnack-"
        "gfx90a:xnack+"
        "gfx90a:xnack-"
16
17
18
        "gfx940"
        "gfx941"
        "gfx942"
Daniel Hiltgen's avatar
Daniel Hiltgen committed
19
20
21
22
23
24
25
26
27
28
        "gfx1010"
        "gfx1012"
        "gfx1030"
        "gfx1100"
        "gfx1101"
        "gfx1102"
    )
    $GPU_LIST -join ';'
}

29
function init_vars {
Daniel Hiltgen's avatar
Daniel Hiltgen committed
30
31
32
33
34
35
    # Verify the environment is a Developer Shell for MSVC 2019
    write-host $env:VSINSTALLDIR
    if (($env:VSINSTALLDIR -eq $null)) {
        Write-Error "`r`nBUILD ERROR - YOUR DEVELOPMENT ENVIRONMENT IS NOT SET UP CORRECTLY`r`nTo build Ollama you must run from an MSVC Developer Shell`r`nSee .\docs\development.md for instructions to set up your dev environment"
        exit 1
    }
36
    $script:SRC_DIR = $(resolve-path "..\..\")
37
    $script:llamacppDir = "../llama.cpp"
Daniel Hiltgen's avatar
Daniel Hiltgen committed
38
39
40
41
    $script:cmakeDefs = @(
        "-DBUILD_SHARED_LIBS=on",
        "-DLLAMA_NATIVE=off"
        )
42
43
    $script:cmakeTargets = @("ext_server")
    $script:ARCH = "amd64" # arm not yet supported.
44
    if ($env:CGO_CFLAGS -contains "-g") {
Daniel Hiltgen's avatar
Daniel Hiltgen committed
45
        $script:cmakeDefs += @("-DCMAKE_VERBOSE_MAKEFILE=on", "-DLLAMA_SERVER_VERBOSE=on", "-DCMAKE_BUILD_TYPE=RelWithDebInfo")
Daniel Hiltgen's avatar
Daniel Hiltgen committed
46
        $script:config = "RelWithDebInfo"
47
    } else {
Daniel Hiltgen's avatar
Daniel Hiltgen committed
48
        $script:cmakeDefs += @("-DLLAMA_SERVER_VERBOSE=off", "-DCMAKE_BUILD_TYPE=Release")
Daniel Hiltgen's avatar
Daniel Hiltgen committed
49
        $script:config = "Release"
50
    }
Daniel Hiltgen's avatar
Daniel Hiltgen committed
51
52
53
    if ($null -ne $env:CMAKE_SYSTEM_VERSION) {
        $script:cmakeDefs += @("-DCMAKE_SYSTEM_VERSION=${env:CMAKE_SYSTEM_VERSION}")
    }
54
55
56
57
58
    # Try to find the CUDA dir
    if ($env:CUDA_LIB_DIR -eq $null) {
        $d=(get-command -ea 'silentlycontinue' nvcc).path
        if ($d -ne $null) {
            $script:CUDA_LIB_DIR=($d| split-path -parent)
59
            $script:CUDA_INCLUDE_DIR=($script:CUDA_LIB_DIR|split-path -parent)+"\include"
60
61
62
63
        }
    } else {
        $script:CUDA_LIB_DIR=$env:CUDA_LIB_DIR
    }
64
    $script:GZIP=(get-command -ea 'silentlycontinue' gzip).path
65
    $script:DUMPBIN=(get-command -ea 'silentlycontinue' dumpbin).path
66
67
68
69
70
    if ($null -eq $env:CMAKE_CUDA_ARCHITECTURES) {
        $script:CMAKE_CUDA_ARCHITECTURES="50;52;61;70;75;80"
    } else {
        $script:CMAKE_CUDA_ARCHITECTURES=$env:CMAKE_CUDA_ARCHITECTURES
    }
71
72
    # Note: 10 Windows Kit signtool crashes with GCP's plugin
    ${script:SignTool}="C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe"
73
74
75
    if ("${env:KEY_CONTAINER}") {
        ${script:OLLAMA_CERT}=$(resolve-path "${script:SRC_DIR}\ollama_inc.crt")
    }
76
77
78
79
80
}

function git_module_setup {
    # TODO add flags to skip the init/patch logic to make it easier to mod llama.cpp code in-repo
    & git submodule init
Daniel Hiltgen's avatar
Daniel Hiltgen committed
81
    if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
82
    & git submodule update --force "${script:llamacppDir}"
Daniel Hiltgen's avatar
Daniel Hiltgen committed
83
    if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
84
85
86
}

function apply_patches {
87
    # Wire up our CMakefile
88
89
    if (!(Select-String -Path "${script:llamacppDir}/CMakeLists.txt" -Pattern 'ollama')) {
        Add-Content -Path "${script:llamacppDir}/CMakeLists.txt" -Value 'add_subdirectory(../ext_server ext_server) # ollama'
90
    }
91
92
93
94
95
96
97
98
99
100
101

    # Apply temporary patches until fix is upstream
    $patches = Get-ChildItem "../patches/*.diff"
    foreach ($patch in $patches) {
        # Extract file paths from the patch file
        $filePaths = Get-Content $patch.FullName | Where-Object { $_ -match '^\+\+\+ ' } | ForEach-Object {
            $parts = $_ -split ' '
            ($parts[1] -split '/', 2)[1]
        }

        # Checkout each file
102
        Set-Location -Path ${script:llamacppDir}
103
104
105
106
107
108
109
110
111
112
        foreach ($file in $filePaths) {
            git checkout $file
        }
    }

    # Apply each patch
    foreach ($patch in $patches) {
        Set-Location -Path ${script:llamacppDir}
        git apply $patch.FullName
    }
113
114
115
}

function build {
116
    write-host "generating config with: cmake -S ${script:llamacppDir} -B $script:buildDir $script:cmakeDefs"
117
    & cmake --version
118
    & cmake -S "${script:llamacppDir}" -B $script:buildDir $script:cmakeDefs
Daniel Hiltgen's avatar
Daniel Hiltgen committed
119
    if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
120
121
    write-host "building with: cmake --build $script:buildDir --config $script:config ($script:cmakeTargets | ForEach-Object { "--target", $_ })"
    & cmake --build $script:buildDir --config $script:config ($script:cmakeTargets | ForEach-Object { "--target", $_ })
Daniel Hiltgen's avatar
Daniel Hiltgen committed
122
    if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
123
124
}

125
126
127
function install {
    rm -ea 0 -recurse -force -path "${script:buildDir}/lib"
    md "${script:buildDir}/lib" -ea 0 > $null
128
    cp "${script:buildDir}/bin/${script:config}/ext_server.dll" "${script:buildDir}/lib"
129
    cp "${script:buildDir}/bin/${script:config}/llama.dll" "${script:buildDir}/lib"
130
    # Display the dll dependencies in the build log
131
132
133
134
135
    if ($script:DUMPBIN -ne $null) {
        & "$script:DUMPBIN" /dependents "${script:buildDir}/bin/${script:config}/ext_server.dll" | select-string ".dll"
    }
}

136
137
138
139
function sign {
    if ("${env:KEY_CONTAINER}") {
        write-host "Signing ${script:buildDir}/lib/*.dll"
        foreach ($file in (get-childitem "${script:buildDir}/lib/*.dll")){
140
            & "${script:SignTool}" sign /v /fd sha256 /t http://timestamp.digicert.com /f "${script:OLLAMA_CERT}" `
141
142
143
144
145
146
                /csp "Google Cloud KMS Provider" /kc "${env:KEY_CONTAINER}" $file
            if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
        }
    }
}

147
function compress_libs {
148
149
    if ($script:GZIP -eq $null) {
        write-host "gzip not installed, not compressing files"
150
151
152
153
154
        return
    }
    write-host "Compressing dlls..."
    $libs = dir "${script:buildDir}/lib/*.dll"
    foreach ($file in $libs) {
Jeffrey Morgan's avatar
Jeffrey Morgan committed
155
        & "$script:GZIP" --best -f $file
156
    }
157
158
}

159
function cleanup {
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    $patches = Get-ChildItem "../patches/*.diff"
    foreach ($patch in $patches) {
        # Extract file paths from the patch file
        $filePaths = Get-Content $patch.FullName | Where-Object { $_ -match '^\+\+\+ ' } | ForEach-Object {
            $parts = $_ -split ' '
            ($parts[1] -split '/', 2)[1]
        }

        # Checkout each file
        Set-Location -Path ${script:llamacppDir}
        foreach ($file in $filePaths) {            
            git checkout $file
        }
    }
174
175
    Set-Location "${script:llamacppDir}/"
    git checkout CMakeLists.txt
176

177
178
179
180
181
}

init_vars
git_module_setup
apply_patches
Daniel Hiltgen's avatar
Daniel Hiltgen committed
182

183
184
185
186
187
# -DLLAMA_AVX -- 2011 Intel Sandy Bridge & AMD Bulldozer
# -DLLAMA_F16C -- 2012 Intel Ivy Bridge & AMD 2011 Bulldozer (No significant improvement over just AVX)
# -DLLAMA_AVX2 -- 2013 Intel Haswell & 2015 AMD Excavator / 2017 AMD Zen
# -DLLAMA_FMA (FMA3) -- 2013 Intel Haswell & 2012 AMD Piledriver

188
$script:commonCpuDefs = @("-DCMAKE_POSITION_INDEPENDENT_CODE=on")
189

190
init_vars
Daniel Hiltgen's avatar
Daniel Hiltgen committed
191
$script:cmakeDefs = $script:commonCpuDefs + @("-A", "x64", "-DLLAMA_AVX=off", "-DLLAMA_AVX2=off", "-DLLAMA_AVX512=off", "-DLLAMA_FMA=off", "-DLLAMA_F16C=off") + $script:cmakeDefs
192
$script:buildDir="${script:llamacppDir}/build/windows/${script:ARCH}/cpu"
193
194
195
write-host "Building LCD CPU"
build
install
196
sign
197
compress_libs
198

199
init_vars
Daniel Hiltgen's avatar
Daniel Hiltgen committed
200
$script:cmakeDefs = $script:commonCpuDefs + @("-A", "x64", "-DLLAMA_AVX=on", "-DLLAMA_AVX2=off", "-DLLAMA_AVX512=off", "-DLLAMA_FMA=off", "-DLLAMA_F16C=off") + $script:cmakeDefs
201
$script:buildDir="${script:llamacppDir}/build/windows/${script:ARCH}/cpu_avx"
202
203
204
write-host "Building AVX CPU"
build
install
205
sign
206
compress_libs
Daniel Hiltgen's avatar
Daniel Hiltgen committed
207

208
init_vars
Daniel Hiltgen's avatar
Daniel Hiltgen committed
209
$script:cmakeDefs = $script:commonCpuDefs + @("-A", "x64", "-DLLAMA_AVX=on", "-DLLAMA_AVX2=on", "-DLLAMA_AVX512=off", "-DLLAMA_FMA=on", "-DLLAMA_F16C=on") + $script:cmakeDefs
210
$script:buildDir="${script:llamacppDir}/build/windows/${script:ARCH}/cpu_avx2"
211
write-host "Building AVX2 CPU"
Daniel Hiltgen's avatar
Daniel Hiltgen committed
212
build
213
install
214
sign
215
compress_libs
Daniel Hiltgen's avatar
Daniel Hiltgen committed
216

217
218
if ($null -ne $script:CUDA_LIB_DIR) {
    # Then build cuda as a dynamically loaded library
219
220
    $nvcc = "$script:CUDA_LIB_DIR\nvcc.exe"
    $script:CUDA_VERSION=(get-item ($nvcc | split-path | split-path)).Basename
221
222
223
224
225
    if ($null -ne $script:CUDA_VERSION) {
        $script:CUDA_VARIANT="_"+$script:CUDA_VERSION
    }
    init_vars
    $script:buildDir="${script:llamacppDir}/build/windows/${script:ARCH}/cuda$script:CUDA_VARIANT"
Daniel Hiltgen's avatar
Daniel Hiltgen committed
226
227
    $script:cmakeDefs += @("-A", "x64", "-DLLAMA_CUBLAS=ON", "-DLLAMA_AVX=on", "-DLLAMA_AVX2=off", "-DCUDAToolkit_INCLUDE_DIR=$script:CUDA_INCLUDE_DIR", "-DCMAKE_CUDA_ARCHITECTURES=${script:CMAKE_CUDA_ARCHITECTURES}")
    write-host "Building CUDA"
228
229
    build
    install
230
    sign
231
232
    compress_libs
}
233

Daniel Hiltgen's avatar
Daniel Hiltgen committed
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
if ($null -ne $env:HIP_PATH) {
    $script:ROCM_VERSION=(get-item $env:HIP_PATH).Basename
    if ($null -ne $script:ROCM_VERSION) {
        $script:ROCM_VARIANT="_v"+$script:ROCM_VERSION
    }

    init_vars
    $script:buildDir="${script:llamacppDir}/build/windows/${script:ARCH}/rocm$script:ROCM_VARIANT"
    $script:cmakeDefs += @(
        "-G", "Ninja", 
        "-DCMAKE_C_COMPILER=clang.exe",
        "-DCMAKE_CXX_COMPILER=clang++.exe",
        "-DLLAMA_HIPBLAS=on",
        "-DLLAMA_AVX=on",
        "-DLLAMA_AVX2=off",
        "-DCMAKE_POSITION_INDEPENDENT_CODE=on",
        "-DAMDGPU_TARGETS=$(amdGPUs)",
        "-DGPU_TARGETS=$(amdGPUs)"
        )

    # Make sure the ROCm binary dir is first in the path
    $env:PATH="$env:HIP_PATH\bin;$env:VSINSTALLDIR\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja;$env:PATH"

    # We have to clobber the LIB var from the developer shell for clang to work properly
    $env:LIB=""

    write-host "Building ROCm"
    build
    # Ninja doesn't prefix with config name
    ${script:config}=""
    install
    if ($null -ne $script:DUMPBIN) {
        & "$script:DUMPBIN" /dependents "${script:buildDir}/bin/${script:config}/ext_server.dll" | select-string ".dll"
    }
    sign
    compress_libs
}
271
272

cleanup
273
write-host "`ngo generate completed"