gen_windows.ps1 9.64 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}/CMakeLists.txt" -Pattern 'ollama')) {
        Add-Content -Path "${script:llamacppDir}/CMakeLists.txt" -Value 'add_subdirectory(../ext_server ext_server) # 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
        foreach ($file in $filePaths) {
            git checkout $file
        }
    }

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

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

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

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

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

156
function cleanup {
157
158
159
160
161
162
163
164
165
166
167
168
169
170
    $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
        }
    }
171
172
    Set-Location "${script:llamacppDir}/"
    git checkout CMakeLists.txt
173

174
175
176
177
178
}

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

180
181
182
183
184
# -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

185
$script:commonCpuDefs = @("-DCMAKE_POSITION_INDEPENDENT_CODE=on")
186

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

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

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

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

Daniel Hiltgen's avatar
Daniel Hiltgen committed
231
232
233
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
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
}
268
269

cleanup
270
write-host "`ngo generate completed"