gen_windows.ps1 9.99 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
16
17
18
19
20
21
22
23
24
25
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-"
        "gfx1010"
        "gfx1012"
        "gfx1030"
        "gfx1100"
        "gfx1101"
        "gfx1102"
    )
    $GPU_LIST -join ';'
}

26
function init_vars {
Daniel Hiltgen's avatar
Daniel Hiltgen committed
27
28
29
30
31
32
    # 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
    }
33
    $script:SRC_DIR = $(resolve-path "..\..\")
34
    $script:llamacppDir = "../llama.cpp"
Daniel Hiltgen's avatar
Daniel Hiltgen committed
35
36
37
38
    $script:cmakeDefs = @(
        "-DBUILD_SHARED_LIBS=on",
        "-DLLAMA_NATIVE=off"
        )
39
40
    $script:cmakeTargets = @("ext_server")
    $script:ARCH = "amd64" # arm not yet supported.
41
    if ($env:CGO_CFLAGS -contains "-g") {
Daniel Hiltgen's avatar
Daniel Hiltgen committed
42
        $script:cmakeDefs += @("-DCMAKE_VERBOSE_MAKEFILE=on", "-DLLAMA_SERVER_VERBOSE=on", "-DCMAKE_BUILD_TYPE=RelWithDebInfo")
Daniel Hiltgen's avatar
Daniel Hiltgen committed
43
        $script:config = "RelWithDebInfo"
44
    } else {
Daniel Hiltgen's avatar
Daniel Hiltgen committed
45
        $script:cmakeDefs += @("-DLLAMA_SERVER_VERBOSE=off", "-DCMAKE_BUILD_TYPE=Release")
Daniel Hiltgen's avatar
Daniel Hiltgen committed
46
        $script:config = "Release"
47
    }
Daniel Hiltgen's avatar
Daniel Hiltgen committed
48
49
50
    if ($null -ne $env:CMAKE_SYSTEM_VERSION) {
        $script:cmakeDefs += @("-DCMAKE_SYSTEM_VERSION=${env:CMAKE_SYSTEM_VERSION}")
    }
51
52
53
54
55
    # 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)
56
            $script:CUDA_INCLUDE_DIR=($script:CUDA_LIB_DIR|split-path -parent)+"\include"
57
58
59
60
        }
    } else {
        $script:CUDA_LIB_DIR=$env:CUDA_LIB_DIR
    }
61
    $script:GZIP=(get-command -ea 'silentlycontinue' gzip).path
62
    $script:DUMPBIN=(get-command -ea 'silentlycontinue' dumpbin).path
63
64
65
66
67
    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
    }
68
69
    # Note: 10 Windows Kit signtool crashes with GCP's plugin
    ${script:SignTool}="C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe"
70
71
72
    if ("${env:KEY_CONTAINER}") {
        ${script:OLLAMA_CERT}=$(resolve-path "${script:SRC_DIR}\ollama_inc.crt")
    }
73
74
75
76
77
}

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
78
    if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
79
    & git submodule update --force "${script:llamacppDir}"
Daniel Hiltgen's avatar
Daniel Hiltgen committed
80
    if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
81
82
83
}

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

    # 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
99
        Set-Location -Path ${script:llamacppDir}
100
101
102
103
104
105
106
107
108
109
110
        foreach ($file in $filePaths) {
            git checkout $file
        }
    }

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

111
    # Avoid duplicate main symbols when we link into the cgo binary
112
    $content = Get-Content -Path "${script:llamacppDir}/examples/server/server.cpp"
113
    $content = $content -replace 'int main\(', 'int __main('
114
    Set-Content -Path "${script:llamacppDir}/examples/server/server.cpp" -Value $content
115
116
117
}

function build {
118
    write-host "generating config with: cmake -S ${script:llamacppDir} -B $script:buildDir $script:cmakeDefs"
119
    & cmake --version
120
    & cmake -S "${script:llamacppDir}" -B $script:buildDir $script:cmakeDefs
Daniel Hiltgen's avatar
Daniel Hiltgen committed
121
    if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
122
123
    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
124
    if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
125
126
}

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

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

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

161
function cleanup {
162
163
164
165
166
167
168
169
170
171
172
173
174
175
    $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
        }
    }
176
    Set-Location "${script:llamacppDir}/examples/server"
177
    git checkout CMakeLists.txt server.cpp
178

179
180
181
182
183
}

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

185
186
187
188
189
# -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

190
$script:commonCpuDefs = @("-DCMAKE_POSITION_INDEPENDENT_CODE=on")
191

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

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

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

219
220
if ($null -ne $script:CUDA_LIB_DIR) {
    # Then build cuda as a dynamically loaded library
221
222
    $nvcc = "$script:CUDA_LIB_DIR\nvcc.exe"
    $script:CUDA_VERSION=(get-item ($nvcc | split-path | split-path)).Basename
223
224
225
226
227
    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
228
229
    $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"
230
231
    build
    install
232
    sign
233
234
    compress_libs
}
235

Daniel Hiltgen's avatar
Daniel Hiltgen committed
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
271
272
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
}
273
274

cleanup
275
write-host "`ngo generate completed"