build_windows.ps1 7.71 KB
Newer Older
xuxzh1's avatar
init  
xuxzh1 committed
1
2
3
4
5
6
7
8
9
#!powershell
#
# powershell -ExecutionPolicy Bypass -File .\scripts\build_windows.ps1
#
# gcloud auth application-default login

$ErrorActionPreference = "Stop"

function checkEnv() {
xuxzh1's avatar
update  
xuxzh1 committed
10
11
12
13
14
15
16
17
18
19
20
21
    if ($null -ne $env:ARCH ) {
        $script:ARCH = $env:ARCH
    } else {
        $arch=([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)
        if ($null -ne $arch) {
            $script:ARCH = ($arch.ToString().ToLower()).Replace("x64", "amd64")
        } else {
            write-host "WARNING: old powershell detected, assuming amd64 architecture - set `$env:ARCH to override"
            $script:ARCH="amd64"
        }
    }
    $script:TARGET_ARCH=$script:ARCH
xuxzh1's avatar
init  
xuxzh1 committed
22
23
24
    Write-host "Building for ${script:TARGET_ARCH}"
    write-host "Locating required tools and paths"
    $script:SRC_DIR=$PWD
xuxzh1's avatar
update  
xuxzh1 committed
25
    if ($null -eq $env:VCToolsRedistDir) {
xuxzh1's avatar
init  
xuxzh1 committed
26
27
28
        $MSVC_INSTALL=(Get-CimInstance MSFT_VSInstance -Namespace root/cimv2/vs)[0].InstallLocation
        $env:VCToolsRedistDir=(get-item "${MSVC_INSTALL}\VC\Redist\MSVC\*")[0]
    }
xuxzh1's avatar
update  
xuxzh1 committed
29
30
31
32
    # Locate CUDA versions
    # Note: this assumes every version found will be built
    $cudaList=(get-item "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v*\bin\" -ea 'silentlycontinue')
    if ($cudaList.length -eq 0) {
xuxzh1's avatar
init  
xuxzh1 committed
33
        $d=(get-command -ea 'silentlycontinue' nvcc).path
xuxzh1's avatar
update  
xuxzh1 committed
34
35
        if ($null -ne $d) {
            $script:CUDA_DIRS=@($d| split-path -parent)
xuxzh1's avatar
init  
xuxzh1 committed
36
37
        }
    } else {
xuxzh1's avatar
update  
xuxzh1 committed
38
        $script:CUDA_DIRS=$cudaList
xuxzh1's avatar
init  
xuxzh1 committed
39
40
    }
    
xuxzh1's avatar
update  
xuxzh1 committed
41
42
43
44
    $inoSetup=(get-item "C:\Program Files*\Inno Setup*\")
    if ($inoSetup.length -gt 0) {
        $script:INNO_SETUP_DIR=$inoSetup[0]
    }
xuxzh1's avatar
init  
xuxzh1 committed
45

xuxzh1's avatar
update  
xuxzh1 committed
46
    $script:DIST_DIR="${script:SRC_DIR}\dist\windows-${script:TARGET_ARCH}"
xuxzh1's avatar
init  
xuxzh1 committed
47
    $env:CGO_ENABLED="1"
xuxzh1's avatar
update  
xuxzh1 committed
48
    Write-Output "Checking version"
xuxzh1's avatar
init  
xuxzh1 committed
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
    if (!$env:VERSION) {
        $data=(git describe --tags --first-parent --abbrev=7 --long --dirty --always)
        $pattern="v(.+)"
        if ($data -match $pattern) {
            $script:VERSION=$matches[1]
        }
    } else {
        $script:VERSION=$env:VERSION
    }
    $pattern = "(\d+[.]\d+[.]\d+).*"
    if ($script:VERSION -match $pattern) {
        $script:PKG_VERSION=$matches[1]
    } else {
        $script:PKG_VERSION="0.0.0"
    }
    write-host "Building Ollama $script:VERSION with package version $script:PKG_VERSION"

    # Note: Windows Kits 10 signtool crashes with GCP's plugin
    if ($null -eq $env:SIGN_TOOL) {
        ${script:SignTool}="C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe"
    } else {
        ${script:SignTool}=${env:SIGN_TOOL}
    }
    if ("${env:KEY_CONTAINER}") {
        ${script:OLLAMA_CERT}=$(resolve-path "${script:SRC_DIR}\ollama_inc.crt")
        Write-host "Code signing enabled"
    } else {
        write-host "Code signing disabled - please set KEY_CONTAINERS to sign and copy ollama_inc.crt to the top of the source tree"
    }
}


function buildOllama() {
    if ($null -eq ${env:OLLAMA_SKIP_GENERATE}) {
xuxzh1's avatar
update  
xuxzh1 committed
83
84
85
86
        write-host "Building ollama runners"
        Remove-Item -ea 0 -recurse -force -path "${script:SRC_DIR}\dist\windows-${script:ARCH}"
        & make -C llama -j 12
        if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
xuxzh1's avatar
init  
xuxzh1 committed
87
88
89
    } else {
        write-host "Skipping generate step with OLLAMA_SKIP_GENERATE set"
    }
xuxzh1's avatar
update  
xuxzh1 committed
90
    write-host "Building ollama CLI"
xuxzh1's avatar
init  
xuxzh1 committed
91
92
93
94
95
96
97
98
99
100
    & go build -trimpath -ldflags "-s -w -X=github.com/ollama/ollama/version.Version=$script:VERSION -X=github.com/ollama/ollama/server.mode=release" .
    if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
    New-Item -ItemType Directory -Path .\dist\windows-${script:TARGET_ARCH}\ -Force
    cp .\ollama.exe .\dist\windows-${script:TARGET_ARCH}\
}

function buildApp() {
    write-host "Building Ollama App"
    cd "${script:SRC_DIR}\app"
    & windres -l 0 -o ollama.syso ollama.rc
xuxzh1's avatar
update  
xuxzh1 committed
101
    & go build -trimpath -ldflags "-s -w -H windowsgui -X=github.com/ollama/ollama/version.Version=$script:VERSION -X=github.com/ollama/ollama/server.mode=release" -o "${script:SRC_DIR}\dist\windows-${script:TARGET_ARCH}-app.exe" .
xuxzh1's avatar
init  
xuxzh1 committed
102
103
104
105
    if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
}

function gatherDependencies() {
xuxzh1's avatar
update  
xuxzh1 committed
106
107
108
109
110
    if ($null -eq $env:VCToolsRedistDir) {
        write-error "Unable to locate VC Install location - please use a Developer shell"
        exit 1
    }
    write-host "Gathering runtime dependencies from $env:VCToolsRedistDir"
xuxzh1's avatar
init  
xuxzh1 committed
111
    cd "${script:SRC_DIR}"
xuxzh1's avatar
update  
xuxzh1 committed
112
    md "${script:DIST_DIR}\lib\ollama" -ea 0 > $null
xuxzh1's avatar
init  
xuxzh1 committed
113
114
115

    # TODO - this varies based on host build system and MSVC version - drive from dumpbin output
    # currently works for Win11 + MSVC 2019 + Cuda V11
xuxzh1's avatar
update  
xuxzh1 committed
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    if ($script:TARGET_ARCH -eq "amd64") {
        $depArch="x64"
    } else {
        $depArch=$script:TARGET_ARCH
    }
    if ($depArch -eq "x64") {
        cp "${env:VCToolsRedistDir}\${depArch}\Microsoft.VC*.CRT\msvcp140*.dll" "${script:DIST_DIR}\lib\ollama\"
        cp "${env:VCToolsRedistDir}\${depArch}\Microsoft.VC*.CRT\vcruntime140.dll" "${script:DIST_DIR}\lib\ollama\"
        cp "${env:VCToolsRedistDir}\${depArch}\Microsoft.VC*.CRT\vcruntime140_1.dll" "${script:DIST_DIR}\lib\ollama\"
        $llvmCrtDir="$env:VCToolsRedistDir\..\..\..\Tools\Llvm\${depArch}\bin"
        foreach ($part in $("runtime", "stdio", "filesystem", "math", "convert", "heap", "string", "time", "locale", "environment")) {
            write-host "cp ${llvmCrtDir}\api-ms-win-crt-${part}*.dll ${script:DIST_DIR}\lib\ollama\"
            cp "${llvmCrtDir}\api-ms-win-crt-${part}*.dll" "${script:DIST_DIR}\lib\ollama\"
        }
    } else {
        # Carying the dll's doesn't seem to work, so use the redist installer
        copy-item -path "${env:VCToolsRedistDir}\vc_redist.arm64.exe" -destination "${script:DIST_DIR}" -verbose
xuxzh1's avatar
init  
xuxzh1 committed
133
134
135
    }

    cp "${script:SRC_DIR}\app\ollama_welcome.ps1" "${script:SRC_DIR}\dist\"
xuxzh1's avatar
update  
xuxzh1 committed
136
137
138
}

function sign() {
xuxzh1's avatar
init  
xuxzh1 committed
139
    if ("${env:KEY_CONTAINER}") {
xuxzh1's avatar
update  
xuxzh1 committed
140
141
142
143
144
145
146
147
        write-host "Signing Ollama executables, scripts and libraries"
        & "${script:SignTool}" sign /v /fd sha256 /t http://timestamp.digicert.com /f "${script:OLLAMA_CERT}" `
            /csp "Google Cloud KMS Provider" /kc ${env:KEY_CONTAINER} `
            $(get-childitem -path "${script:SRC_DIR}\dist" -r -include @('ollama_welcome.ps1')) `
            $(get-childitem -path "${script:SRC_DIR}\dist\windows-*" -r -include @('*.exe', '*.dll'))
        if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
    } else {
        write-host "Signing not enabled"
xuxzh1's avatar
init  
xuxzh1 committed
148
149
150
151
    }
}

function buildInstaller() {
xuxzh1's avatar
update  
xuxzh1 committed
152
153
154
155
    if ($null -eq ${script:INNO_SETUP_DIR}) {
        write-host "Inno Setup not present, skipping installer build"
        return
    }
xuxzh1's avatar
init  
xuxzh1 committed
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
    write-host "Building Ollama Installer"
    cd "${script:SRC_DIR}\app"
    $env:PKG_VERSION=$script:PKG_VERSION
    if ("${env:KEY_CONTAINER}") {
        & "${script:INNO_SETUP_DIR}\ISCC.exe" /DARCH=$script:TARGET_ARCH /SMySignTool="${script:SignTool} sign /fd sha256 /t http://timestamp.digicert.com /f ${script:OLLAMA_CERT} /csp `$qGoogle Cloud KMS Provider`$q /kc ${env:KEY_CONTAINER} `$f" .\ollama.iss
    } else {
        & "${script:INNO_SETUP_DIR}\ISCC.exe" /DARCH=$script:TARGET_ARCH .\ollama.iss
    }
    if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
}

function distZip() {
    write-host "Generating stand-alone distribution zip file ${script:SRC_DIR}\dist\ollama-windows-${script:TARGET_ARCH}.zip"
    Compress-Archive -Path "${script:SRC_DIR}\dist\windows-${script:TARGET_ARCH}\*" -DestinationPath "${script:SRC_DIR}\dist\ollama-windows-${script:TARGET_ARCH}.zip" -Force
}

xuxzh1's avatar
update  
xuxzh1 committed
172
checkEnv
xuxzh1's avatar
init  
xuxzh1 committed
173
try {
xuxzh1's avatar
update  
xuxzh1 committed
174
175
176
177
178
179
180
181
182
183
184
185
186
    if ($($args.count) -eq 0) {
        buildOllama
        buildApp
        gatherDependencies
        sign
        buildInstaller
        distZip
    } else {
        for ( $i = 0; $i -lt $args.count; $i++ ) {
            write-host "performing $($args[$i])"
            & $($args[$i])
        } 
    }
xuxzh1's avatar
init  
xuxzh1 committed
187
188
189
190
191
192
193
} catch {
    write-host "Build Failed"
    write-host $_
} finally {
    set-location $script:SRC_DIR
    $env:PKG_VERSION=""
}