From 7ccb65cd5e9b8a8c01226b98bfc8acd8a586838c Mon Sep 17 00:00:00 2001 From: Daniel Hiltgen Date: Mon, 27 Oct 2025 08:23:22 -0700 Subject: [PATCH] ci: update release flow --- .github/workflows/release.yaml | 167 ++++++++++++++++++++------ CMakePresets.json | 23 ++-- Dockerfile | 14 +-- app/ui/ui.go | 1 - scripts/build_windows.ps1 | 213 +++++++++++++++++---------------- 5 files changed, 262 insertions(+), 156 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 33ce2007a..195203f1b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,44 +15,56 @@ jobs: environment: release outputs: GOFLAGS: ${{ steps.goflags.outputs.GOFLAGS }} + VERSION: ${{ steps.goflags.outputs.VERSION }} steps: - uses: actions/checkout@v4 - name: Set environment id: goflags run: | echo GOFLAGS="'-ldflags=-w -s \"-X=github.com/ollama/ollama/version.Version=${GITHUB_REF_NAME#v}\" \"-X=github.com/ollama/ollama/server.mode=release\"'" >>$GITHUB_OUTPUT + echo VERSION="${GITHUB_REF_NAME#v}" >>$GITHUB_OUTPUT darwin-build: - runs-on: macos-13-xlarge + runs-on: macos-14-xlarge environment: release needs: setup-environment - strategy: - matrix: - os: [darwin] - arch: [amd64, arm64] env: GOFLAGS: ${{ needs.setup-environment.outputs.GOFLAGS }} + VERSION: ${{ needs.setup-environment.outputs.VERSION }} + APPLE_IDENTITY: ${{ secrets.APPLE_IDENTITY }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ vars.APPLE_TEAM_ID }} + APPLE_ID: ${{ vars.APPLE_ID }} + MACOS_SIGNING_KEY: ${{ secrets.MACOS_SIGNING_KEY }} + MACOS_SIGNING_KEY_PASSWORD: ${{ secrets.MACOS_SIGNING_KEY_PASSWORD }} + CGO_CFLAGS: '-mmacosx-version-min=14.0 -O3' + CGO_CXXFLAGS: '-mmacosx-version-min=14.0 -O3' + CGO_LDFLAGS: '-mmacosx-version-min=14.0 -O3' steps: - uses: actions/checkout@v4 + - run: | + echo $MACOS_SIGNING_KEY | base64 --decode > certificate.p12 + security create-keychain -p password build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p password build.keychain + security import certificate.p12 -k build.keychain -P $MACOS_SIGNING_KEY_PASSWORD -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k password build.keychain + security set-keychain-settings -lut 3600 build.keychain - uses: actions/setup-go@v5 with: go-version-file: go.mod - run: | - go build -o dist/ . - env: - GOOS: ${{ matrix.os }} - GOARCH: ${{ matrix.arch }} - CGO_ENABLED: 1 - CGO_CPPFLAGS: '-mmacosx-version-min=11.3' - - if: matrix.arch == 'amd64' + ./scripts/build_darwin.sh + - name: Log build results run: | - cmake --preset CPU -DCMAKE_OSX_DEPLOYMENT_TARGET=11.3 -DCMAKE_SYSTEM_PROCESSOR=x86_64 -DCMAKE_OSX_ARCHITECTURES=x86_64 - cmake --build --parallel --preset CPU - cmake --install build --component CPU --strip --parallel 8 + ls -l dist/ - uses: actions/upload-artifact@v4 with: - name: build-${{ matrix.os }}-${{ matrix.arch }} - path: dist/* + name: bundles-darwin + path: | + dist/*.tgz + dist/*.zip + dist/*.dmg windows-depends: strategy: @@ -72,7 +84,6 @@ jobs: - '"cublas_dev"' cuda-version: '12.8' flags: '' - runner_dir: 'cuda_v12' - os: windows arch: amd64 preset: 'CUDA 13' @@ -87,14 +98,12 @@ jobs: - '"nvptxcompiler"' cuda-version: '13.0' flags: '' - runner_dir: 'cuda_v13' - os: windows arch: amd64 preset: 'ROCm 6' install: https://download.amd.com/developer/eula/rocm-hub/AMD-Software-PRO-Edition-24.Q4-WinSvr2022-For-HIP.exe rocm-version: '6.2' flags: '-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="-parallel-jobs=4 -Wno-ignored-attributes -Wno-deprecated-pragma" -DCMAKE_CXX_FLAGS="-parallel-jobs=4 -Wno-ignored-attributes -Wno-deprecated-pragma"' - runner_dir: 'rocm' runs-on: ${{ matrix.arch == 'arm64' && format('{0}-{1}', matrix.os, matrix.arch) || matrix.os }} environment: release env: @@ -160,12 +169,15 @@ jobs: run: | Import-Module 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\Microsoft.VisualStudio.DevShell.dll' Enter-VsDevShell -VsInstallPath 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise' -SkipAutomaticLocation -DevCmdArguments '-arch=x64 -no_logo' - cmake --preset "${{ matrix.preset }}" ${{ matrix.flags }} -DOLLAMA_RUNNER_DIR="${{ matrix.runner_dir }}" - cmake --build --parallel --preset "${{ matrix.preset }}" - cmake --install build --component "${{ startsWith(matrix.preset, 'CUDA ') && 'CUDA' || startsWith(matrix.preset, 'ROCm ') && 'HIP' || 'CPU' }}" --strip --parallel 8 + cmake --preset "${{ matrix.preset }}" ${{ matrix.flags }} --install-prefix "$((pwd).Path)\dist\${{ matrix.os }}-${{ matrix.arch }}" + cmake --build --parallel ([Environment]::ProcessorCount) --preset "${{ matrix.preset }}" + cmake --install build --component "${{ startsWith(matrix.preset, 'CUDA ') && 'CUDA' || startsWith(matrix.preset, 'ROCm ') && 'HIP' || 'CPU' }}" --strip Remove-Item -Path dist\lib\ollama\rocm\rocblas\library\*gfx906* -ErrorAction SilentlyContinue env: CMAKE_GENERATOR: Ninja + - name: Log build results + run: | + gci -path .\dist -Recurse -File | ForEach-Object { get-filehash -path $_.FullName -Algorithm SHA256 } | format-list - uses: actions/upload-artifact@v4 with: name: depends-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.preset }} @@ -188,6 +200,7 @@ jobs: needs: [setup-environment] env: GOFLAGS: ${{ needs.setup-environment.outputs.GOFLAGS }} + VERSION: ${{ needs.setup-environment.outputs.VERSION }} steps: - name: Install ARM64 system dependencies if: matrix.arch == 'arm64' @@ -198,6 +211,9 @@ jobs: iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) echo "C:\ProgramData\chocolatey\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + Invoke-WebRequest -Uri https://aka.ms/vs/17/release/vc_redist.arm64.exe -OutFile "${{ runner.temp }}\vc_redist.arm64.exe" + Start-Process -FilePath "${{ runner.temp }}\vc_redist.arm64.exe" -ArgumentList @("/install", "/quiet", "/norestart") -NoNewWindow -Wait + choco install -y --no-progress git gzip echo "C:\Program Files\Git\cmd" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Install clang and gcc-compat @@ -223,13 +239,72 @@ jobs: exit 1 } $ErrorActionPreference='Stop' + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" - run: | - go build -o dist/${{ matrix.os }}-${{ matrix.arch }}/ . + ./scripts/build_windows ollama app + - name: Log build results + run: | + gci -path .\dist -Recurse -File | ForEach-Object { get-filehash -path $_.FullName -Algorithm SHA256 } | format-list - uses: actions/upload-artifact@v4 with: name: build-${{ matrix.os }}-${{ matrix.arch }} path: | - dist\${{ matrix.os }}-${{ matrix.arch }}\*.exe + dist\* + + windows-app: + runs-on: windows + environment: release + needs: [windows-build, windows-depends] + env: + GOFLAGS: ${{ needs.setup-environment.outputs.GOFLAGS }} + VERSION: ${{ needs.setup-environment.outputs.VERSION }} + KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} + steps: + - uses: actions/checkout@v4 + # - uses: google-github-actions/auth@v2 + # with: + # project_id: ollama + # credentials_json: ${{ secrets.GOOGLE_SIGNING_CREDENTIALS }} + # - run: | + # $ErrorActionPreference = "Stop" + # Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=323507" -OutFile "${{ runner.temp }}\sdksetup.exe" + # Start-Process "${{ runner.temp }}\sdksetup.exe" -ArgumentList @("/q") -NoNewWindow -Wait + + # Invoke-WebRequest -Uri "https://github.com/GoogleCloudPlatform/kms-integrations/releases/download/cng-v1.0/kmscng-1.0-windows-amd64.zip" -OutFile "${{ runner.temp }}\plugin.zip" + # Expand-Archive -Path "${{ runner.temp }}\plugin.zip" -DestinationPath "${{ runner.temp }}\plugin\" + # & "${{ runner.temp }}\plugin\*\kmscng.msi" /quiet + + # echo "${{ vars.OLLAMA_CERT }}" >ollama_inc.crt + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - uses: actions/download-artifact@v4 + with: + pattern: depends-windows* + path: dist + merge-multiple: true + - uses: actions/download-artifact@v4 + with: + pattern: build-windows* + path: dist + merge-multiple: true + - name: Log dist contents after download + run: | + gci -path .\dist -recurse + - run: | + ./scripts/build_windows.ps1 deps sign installer zip + - name: Log contents after build + run: | + gci -path .\dist -Recurse -File | ForEach-Object { get-filehash -path $_.FullName -Algorithm SHA256 } | format-list + - uses: actions/upload-artifact@v4 + with: + name: bundles-windows + path: | + dist/*.zip + dist/OllamaSetup.exe linux-build: strategy: @@ -288,7 +363,7 @@ jobs: done - uses: actions/upload-artifact@v4 with: - name: dist-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.target }} + name: bundles-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.target }} path: | *.tgz @@ -344,7 +419,7 @@ jobs: with: context: . platforms: ${{ matrix.os }}/${{ matrix.arch }} - target: ${{ matrix.target }} + target: ${{ matrix.preset }} build-args: ${{ matrix.build-args }} outputs: type=image,name=${{ vars.DOCKER_REPO }},push-by-digest=true,name-canonical=true,push=true cache-from: type=registry,ref=${{ vars.DOCKER_REPO }}:latest @@ -393,17 +468,28 @@ jobs: docker buildx imagetools inspect ${{ vars.DOCKER_REPO }}:${{ steps.metadata.outputs.version }} working-directory: ${{ runner.temp }} - # Trigger downstream release process - trigger: + # Final release process + release: runs-on: ubuntu-latest environment: release - needs: [darwin-build, windows-build, windows-depends, linux-build] + needs: [darwin-build, windows-app, linux-build] permissions: contents: write env: GH_TOKEN: ${{ github.token }} steps: - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + pattern: bundles-* + path: dist + merge-multiple: true + - name: Log dist contents + run: | + ls -l dist/ + - name: Generate checksum file + run: find . -type f -not -name 'sha256sum.txt' | xargs sha256sum | tee sha256sum.txt + working-directory: dist - name: Create or update Release for tag run: | RELEASE_VERSION="$(echo ${GITHUB_REF_NAME} | cut -f1 -d-)" @@ -420,12 +506,17 @@ jobs: --generate-notes \ --prerelease fi - - name: Trigger downstream release process + - name: Upload release artifacts run: | - curl -L \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.RELEASE_TOKEN }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos/ollama/${{ vars.RELEASE_REPO }}/dispatches \ - -d "{\"event_type\": \"trigger-workflow\", \"client_payload\": {\"run_id\": \"${GITHUB_RUN_ID}\", \"version\": \"${GITHUB_REF_NAME#v}\", \"origin\": \"${GITHUB_REPOSITORY}\", \"publish\": \"1\"}}" + pids=() + for payload in dist/*.txt dist/*.zip dist/*.tgz dist/*.exe dist/*.dmg ; do + echo "Uploading $payload" + gh release upload ${GITHUB_REF_NAME} $payload --clobber & + pids[$!]=$! + sleep 1 + done + echo "Waiting for uploads to complete" + for pid in "${pids[*]}"; do + wait $pid + done + echo "done" diff --git a/CMakePresets.json b/CMakePresets.json index 72417ade9..6fcdf4d25 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -23,7 +23,8 @@ "inherits": [ "CUDA" ], "cacheVariables": { "CMAKE_CUDA_ARCHITECTURES": "50-virtual;60-virtual;61-virtual;70-virtual;75-virtual;80-virtual;86-virtual;87-virtual;89-virtual;90-virtual", - "CMAKE_CUDA_FLAGS": "-Wno-deprecated-gpu-targets -t 2" + "CMAKE_CUDA_FLAGS": "-Wno-deprecated-gpu-targets -t 2", + "OLLAMA_RUNNER_DIR": "cuda_v11" } }, { @@ -31,7 +32,8 @@ "inherits": [ "CUDA" ], "cacheVariables": { "CMAKE_CUDA_ARCHITECTURES": "50;52;60;61;70;75;80;86;89;90;90a;120", - "CMAKE_CUDA_FLAGS": "-Wno-deprecated-gpu-targets -t 2" + "CMAKE_CUDA_FLAGS": "-Wno-deprecated-gpu-targets -t 2", + "OLLAMA_RUNNER_DIR": "cuda_v12" } }, { @@ -39,21 +41,24 @@ "inherits": [ "CUDA" ], "cacheVariables": { "CMAKE_CUDA_ARCHITECTURES": "75-virtual;80-virtual;86-virtual;87-virtual;89-virtual;90-virtual;90a-virtual;100-virtual;103-virtual;110-virtual;120-virtual;121-virtual", - "CMAKE_CUDA_FLAGS": "-t 2" + "CMAKE_CUDA_FLAGS": "-t 2", + "OLLAMA_RUNNER_DIR": "cuda_v13" } }, { "name": "JetPack 5", "inherits": [ "CUDA" ], "cacheVariables": { - "CMAKE_CUDA_ARCHITECTURES": "72;87" + "CMAKE_CUDA_ARCHITECTURES": "72;87", + "OLLAMA_RUNNER_DIR": "cuda_jetpack5" } }, { "name": "JetPack 6", "inherits": [ "CUDA" ], "cacheVariables": { - "CMAKE_CUDA_ARCHITECTURES": "87" + "CMAKE_CUDA_ARCHITECTURES": "87", + "OLLAMA_RUNNER_DIR": "cuda_jetpack6" } }, { @@ -68,12 +73,16 @@ "inherits": [ "ROCm" ], "cacheVariables": { "CMAKE_HIP_FLAGS": "-parallel-jobs=4", - "AMDGPU_TARGETS": "gfx940;gfx941;gfx942;gfx1010;gfx1012;gfx1030;gfx1100;gfx1101;gfx1102;gfx1151;gfx1200;gfx1201;gfx908:xnack-;gfx90a:xnack+;gfx90a:xnack-" + "AMDGPU_TARGETS": "gfx940;gfx941;gfx942;gfx1010;gfx1012;gfx1030;gfx1100;gfx1101;gfx1102;gfx1151;gfx1200;gfx1201;gfx908:xnack-;gfx90a:xnack+;gfx90a:xnack-", + "OLLAMA_RUNNER_DIR": "rocm" } }, { "name": "Vulkan", - "inherits": [ "Default" ] + "inherits": [ "Default" ], + "cacheVariables": { + "OLLAMA_RUNNER_DIR": "vulkan" + } } ], "buildPresets": [ diff --git a/Dockerfile b/Dockerfile index dbc9207e3..c56c229aa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,7 +58,7 @@ RUN dnf install -y cuda-toolkit-${CUDA11VERSION//./-} ENV PATH=/usr/local/cuda-11/bin:$PATH ARG PARALLEL RUN --mount=type=cache,target=/root/.ccache \ - cmake --preset 'CUDA 11' -DOLLAMA_RUNNER_DIR="cuda_v11" \ + cmake --preset 'CUDA 11' \ && cmake --build --parallel ${PARALLEL} --preset 'CUDA 11' \ && cmake --install build --component CUDA --strip --parallel ${PARALLEL} @@ -68,7 +68,7 @@ RUN dnf install -y cuda-toolkit-${CUDA12VERSION//./-} ENV PATH=/usr/local/cuda-12/bin:$PATH ARG PARALLEL RUN --mount=type=cache,target=/root/.ccache \ - cmake --preset 'CUDA 12' -DOLLAMA_RUNNER_DIR="cuda_v12"\ + cmake --preset 'CUDA 12' \ && cmake --build --parallel ${PARALLEL} --preset 'CUDA 12' \ && cmake --install build --component CUDA --strip --parallel ${PARALLEL} @@ -79,7 +79,7 @@ RUN dnf install -y cuda-toolkit-${CUDA13VERSION//./-} ENV PATH=/usr/local/cuda-13/bin:$PATH ARG PARALLEL RUN --mount=type=cache,target=/root/.ccache \ - cmake --preset 'CUDA 13' -DOLLAMA_RUNNER_DIR="cuda_v13" \ + cmake --preset 'CUDA 13' \ && cmake --build --parallel ${PARALLEL} --preset 'CUDA 13' \ && cmake --install build --component CUDA --strip --parallel ${PARALLEL} @@ -88,7 +88,7 @@ FROM base AS rocm-6 ENV PATH=/opt/rocm/hcc/bin:/opt/rocm/hip/bin:/opt/rocm/bin:/opt/rocm/hcc/bin:$PATH ARG PARALLEL RUN --mount=type=cache,target=/root/.ccache \ - cmake --preset 'ROCm 6' -DOLLAMA_RUNNER_DIR="rocm" \ + cmake --preset 'ROCm 6' \ && cmake --build --parallel ${PARALLEL} --preset 'ROCm 6' \ && cmake --install build --component HIP --strip --parallel ${PARALLEL} RUN rm -f dist/lib/ollama/rocm/rocblas/library/*gfx90[06]* @@ -101,7 +101,7 @@ COPY CMakeLists.txt CMakePresets.json . COPY ml/backend/ggml/ggml ml/backend/ggml/ggml ARG PARALLEL RUN --mount=type=cache,target=/root/.ccache \ - cmake --preset 'JetPack 5' -DOLLAMA_RUNNER_DIR="cuda_jetpack5" \ + cmake --preset 'JetPack 5' \ && cmake --build --parallel ${PARALLEL} --preset 'JetPack 5' \ && cmake --install build --component CUDA --strip --parallel ${PARALLEL} @@ -113,13 +113,13 @@ COPY CMakeLists.txt CMakePresets.json . COPY ml/backend/ggml/ggml ml/backend/ggml/ggml ARG PARALLEL RUN --mount=type=cache,target=/root/.ccache \ - cmake --preset 'JetPack 6' -DOLLAMA_RUNNER_DIR="cuda_jetpack6" \ + cmake --preset 'JetPack 6' \ && cmake --build --parallel ${PARALLEL} --preset 'JetPack 6' \ && cmake --install build --component CUDA --strip --parallel ${PARALLEL} FROM base AS vulkan RUN --mount=type=cache,target=/root/.ccache \ - cmake --preset 'Vulkan' -DOLLAMA_RUNNER_DIR="vulkan" \ + cmake --preset 'Vulkan' \ && cmake --build --parallel --preset 'Vulkan' \ && cmake --install build --component Vulkan --strip --parallel 8 diff --git a/app/ui/ui.go b/app/ui/ui.go index 2aaff6ee4..4ab246c1c 100644 --- a/app/ui/ui.go +++ b/app/ui/ui.go @@ -32,7 +32,6 @@ import ( "github.com/ollama/ollama/types/model" ) -//go:generate go get github.com/tkrajina/typescriptify-golang-structs/typescriptify@latest //go:generate tscriptify -package=github.com/ollama/ollama/app/ui/responses -target=./app/codegen/gotypes.gen.ts responses/types.go //go:generate npm --prefix ./app run build diff --git a/scripts/build_windows.ps1 b/scripts/build_windows.ps1 index 081a56275..f43893ec5 100644 --- a/scripts/build_windows.ps1 +++ b/scripts/build_windows.ps1 @@ -8,7 +8,7 @@ $ErrorActionPreference = "Stop" mkdir -Force -path .\dist | Out-Null -function checkEnv() { +function checkEnv { if ($null -ne $env:ARCH ) { $script:ARCH = $env:ARCH } else { @@ -24,10 +24,7 @@ function checkEnv() { Write-host "Building for ${script:TARGET_ARCH}" write-host "Locating required tools and paths" $script:SRC_DIR=$PWD - if ($null -eq $env:VCToolsRedistDir) { - $MSVC_INSTALL=(Get-CimInstance MSFT_VSInstance -Namespace root/cimv2/vs)[0].InstallLocation - $env:VCToolsRedistDir=(get-item "${MSVC_INSTALL}\VC\Redist\MSVC\*")[0] - } + # Locate CUDA versions $cudaList=(get-item "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v*\bin\" -ea 'silentlycontinue') if ($cudaList.length -eq 0) { @@ -36,7 +33,20 @@ function checkEnv() { $script:CUDA_DIRS=@($d| split-path -parent) } } else { - $script:CUDA_DIRS=$cudaList + # Favor newer patch versions if available + $script:CUDA_DIRS=($cudaList | sort-object -Descending) + } + if ($script:CUDA_DIRS.length -gt 0) { + write-host "Available CUDA Versions: $script:CUDA_DIRS" + } else { + write-host "No CUDA versions detected" + } + + # Locate ROCm version + if ($null -ne $env:HIP_PATH) { + $script:HIP_PATH=$env:HIP_PATH + } else { + $script:HIP_PATH=(get-item "C:\Program Files\AMD\ROCm\*\bin\" -ea 'silentlycontinue' | sort-object -Descending) } $inoSetup=(get-item "C:\Program Files*\Inno Setup*\") @@ -76,12 +86,12 @@ function checkEnv() { } else { write-host "Code signing disabled - please set KEY_CONTAINERS to sign and copy ollama_inc.crt to the top of the source tree" } - $script:JOBS=((Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors) + $script:JOBS=([Environment]::ProcessorCount) } -function cpu() { - mkdir -Force -path "${script:DIST_DIR}\" +function cpu { + mkdir -Force -path "${script:DIST_DIR}\" | Out-Null if ($script:ARCH -ne "arm64") { Remove-Item -ea 0 -recurse -force -path "${script:SRC_DIR}\dist\windows-${script:ARCH}" New-Item "${script:SRC_DIR}\dist\windows-${script:ARCH}\lib\ollama\" -ItemType Directory -ea 0 @@ -95,79 +105,89 @@ function cpu() { } } -function cuda11() { +function cuda11 { # CUDA v11 claims to be compatible with MSVC 2022, but the latest updates are no longer compatible # 19.40 is the last compiler version that works, but recent udpates are 19.43 # So this pins to MSVC 2019 for best compatibility - mkdir -Force -path "${script:DIST_DIR}\" + mkdir -Force -path "${script:DIST_DIR}\" | Out-Null + $cudaMajorVer="11" if ($script:ARCH -ne "arm64") { - $hashEnv = @{} - Get-ChildItem env: | foreach { $hashEnv[$_.Name] = $_.Value } - if ("$script:CUDA_DIRS".Contains("v11")) { - $hashEnv.Keys | foreach { if ($_.Contains("CUDA_PATH_V11")) { $x=$hashEnv[$_]; if (test-path -literalpath "$x\bin\nvcc.exe" ) { $cuda=$x} }} - write-host "Building CUDA v11 backend libraries $cuda" + if ("$script:CUDA_DIRS".Contains("v$cudaMajorVer")) { + foreach ($d in $Script:CUDA_DIRS){ + if ($d.FullName.Contains("v$cudaMajorVer")) { + if (test-path -literalpath (join-path -path $d -childpath "nvcc.exe" ) ) { + $cuda=($d.FullName|split-path -parent) + break + } + } + } + write-host "Building CUDA v$cudaMajorVer backend libraries $cuda" $env:CUDAToolkit_ROOT=$cuda - & cmake -B build\cuda_v11 --preset "CUDA 11" -T cuda="$cuda" -DCMAKE_CUDA_COMPILER="$cuda\bin\nvcc.exe" -G "Visual Studio 16 2019" --install-prefix $script:DIST_DIR -DOLLAMA_RUNNER_DIR="cuda_v11" + & cmake -B build\cuda_v$cudaMajorVer --preset "CUDA $cudaMajorVer" -T cuda="$cuda" -DCMAKE_CUDA_COMPILER="$cuda\bin\nvcc.exe" -G "Visual Studio 16 2019" --install-prefix "$script:DIST_DIR" if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} - & cmake --build build\cuda_v11 --target ggml-cuda --config Release --parallel $script:JOBS + & cmake --build build\cuda_v$cudaMajorVer --target ggml-cuda --config Release --parallel $script:JOBS if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} - & cmake --install build\cuda_v11 --component "CUDA" --strip + & cmake --install build\cuda_v$cudaMajorVer --component "CUDA" --strip if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} + } else { + write-host "CUDA v$cudaMajorVer not detected, skipping" + } + } else { + write-host "not arch we wanted" + } + write-host "done" +} + +function cudaCommon { + param ( + [string]$cudaMajorVer + ) + mkdir -Force -path "${script:DIST_DIR}\" | Out-Null + if ($script:ARCH -ne "arm64") { + if ("$script:CUDA_DIRS".Contains("v$cudaMajorVer")) { + foreach ($d in $Script:CUDA_DIRS){ + if ($d.FullName.Contains("v$cudaMajorVer")) { + if (test-path -literalpath (join-path -path $d -childpath "nvcc.exe" ) ) { + $cuda=($d.FullName|split-path -parent) + break + } + } + } + write-host "Building CUDA v$cudaMajorVer backend libraries $cuda" + $env:CUDAToolkit_ROOT=$cuda + & cmake -B build\cuda_v$cudaMajorVer --preset "CUDA $cudaMajorVer" -T cuda="$cuda" --install-prefix "$script:DIST_DIR" + if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} + & cmake --build build\cuda_v$cudaMajorVer --target ggml-cuda --config Release --parallel $script:JOBS + if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} + & cmake --install build\cuda_v$cudaMajorVer --component "CUDA" --strip + if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} + } else { + write-host "CUDA v$cudaMajorVer not detected, skipping" } } } -function cuda12() { - mkdir -Force -path "${script:DIST_DIR}\" - if ($script:ARCH -ne "arm64") { - $hashEnv = @{} - Get-ChildItem env: | foreach { $hashEnv[$_.Name] = $_.Value } - if ("$script:CUDA_DIRS".Contains("v12.8")) { - $hashEnv.Keys | foreach { if ($_.Contains("CUDA_PATH_V12_8")) { $x=$hashEnv[$_]; if (test-path -literalpath "$x\bin\nvcc.exe" ) { $cuda=$x} }} - write-host "Building CUDA v12 backend libraries $cuda" - $env:CUDAToolkit_ROOT=$cuda - & cmake -B build\cuda_v12 --preset "CUDA 12" -T cuda="$cuda" --install-prefix $script:DIST_DIR -DOLLAMA_RUNNER_DIR="cuda_v12" - if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} - & cmake --build build\cuda_v12 --target ggml-cuda --config Release --parallel $script:JOBS - if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} - & cmake --install build\cuda_v12 --component "CUDA" --strip - if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} - } - } +function cuda12 { + cudaCommon("12") } -function cuda13() { - mkdir -Force -path "${script:DIST_DIR}\" - if ($script:ARCH -ne "arm64") { - $hashEnv = @{} - Get-ChildItem env: | foreach { $hashEnv[$_.Name] = $_.Value } - if ("$script:CUDA_DIRS".Contains("v13")) { - $hashEnv.Keys | foreach { if ($_.Contains("CUDA_PATH_V13")) { $x=$hashEnv[$_]; if (test-path -literalpath "$x\bin\nvcc.exe" ) { $cuda=$x} }} - $env:CUDAToolkit_ROOT=$cuda - write-host "Building CUDA v13 backend libraries $cuda" - & cmake -B build\cuda_v13 --preset "CUDA 13" -T cuda="$cuda" --install-prefix $script:DIST_DIR -DOLLAMA_RUNNER_DIR="cuda_v13" - if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} - & cmake --build build\cuda_v13 --target ggml-cuda --config Release --parallel $script:JOBS - if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} - & cmake --install build\cuda_v13 --component "CUDA" --strip - if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} - } - } +function cuda13 { + cudaCommon("13") } -function rocm() { - mkdir -Force -path "${script:DIST_DIR}\" +function rocm { + mkdir -Force -path "${script:DIST_DIR}\" | Out-Null if ($script:ARCH -ne "arm64") { - if ($env:HIP_PATH) { - write-host "Building ROCm backend libraries" + if ($script:HIP_PATH) { + write-host "Building ROCm backend libraries $script:HIP_PATH" if (-Not (get-command -ErrorAction silent ninja)) { $NINJA_DIR=(gci -path (Get-CimInstance MSFT_VSInstance -Namespace root/cimv2/vs)[0].InstallLocation -r -fi ninja.exe).Directory.FullName $env:PATH="$NINJA_DIR;$env:PATH" } - $env:HIPCXX="${env:HIP_PATH}\bin\clang++.exe" + $env:HIPCXX="${script:HIP_PATH}\bin\clang++.exe" $env:HIP_PLATFORM="amd" - $env:CMAKE_PREFIX_PATH="${env:HIP_PATH}" - & cmake --fresh -B build\rocm --preset "ROCm 6" -G Ninja -DOLLAMA_RUNNER_DIR="rocm" ` + $env:CMAKE_PREFIX_PATH="${script:HIP_PATH}" + & cmake -B build\rocm --preset "ROCm 6" -G Ninja` -DCMAKE_C_COMPILER=clang ` -DCMAKE_CXX_COMPILER=clang++ ` -DCMAKE_C_FLAGS="-parallel-jobs=4 -Wno-ignored-attributes -Wno-deprecated-pragma" ` @@ -182,31 +202,35 @@ function rocm() { & cmake --install build\rocm --component "HIP" --strip if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} Remove-Item -Path $script:DIST_DIR\lib\ollama\rocm\rocblas\library\*gfx906* -ErrorAction SilentlyContinue + } else { + write-host "ROCm not detected, skipping" } } } -function vulkan(){ +function vulkan { if ($env:VULKAN_SDK) { write-host "Building Vulkan backend libraries" - & cmake --fresh --preset Vulkan --install-prefix $script:DIST_DIR -DOLLAMA_RUNNER_DIR="vulkan" + & cmake -B build\vulkan --preset Vulkan --install-prefix $script:DIST_DIR if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} - & cmake --build --preset Vulkan --config Release --parallel $script:JOBS + & cmake --build build\vulkan --target ggml-vulkan --config Release --parallel $script:JOBS if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} - & cmake --install build --component Vulkan --strip + & cmake --install build\vulkan --component Vulkan --strip if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} + } else { + write-host "Vulkan not detected, skipping" } } -function ollama() { - mkdir -Force -path "${script:DIST_DIR}\" +function ollama { + mkdir -Force -path "${script:DIST_DIR}\" | Out-Null write-host "Building ollama CLI" & 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)} cp .\ollama.exe "${script:DIST_DIR}\" } -function app() { +function app { write-host "Building Ollama App $script:VERSION with package version $script:PKG_VERSION" if (!(Get-Command npm -ErrorAction SilentlyContinue)) { @@ -219,6 +243,13 @@ function app() { write-host "Installing TypeScript compiler..." npm install -g typescript } + if (!(Get-Command tscriptify -ErrorAction SilentlyContinue)) { + write-host "Installing tscriptify..." + go install github.com/tkrajina/typescriptify-golang-structs/tscriptify@latest + } + if (!(Get-Command tscriptify -ErrorAction SilentlyContinue)) { + $env:PATH="$env:PATH;$(go env GOPATH)\bin" + } Push-Location app/ui/app npm install @@ -255,45 +286,16 @@ function app() { if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} } -function deps() { - 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" - cd "${script:SRC_DIR}" - md "${script:DIST_DIR}\lib\ollama" -ea 0 > $null - - # TODO - this varies based on host build system and MSVC version - drive from dumpbin output - # currently works for Win11 + MSVC 2019 + Cuda V11 - if ($script:TARGET_ARCH -eq "amd64") { - $depArch="x64" - } else { - $depArch=$script:TARGET_ARCH - } - if ($depArch -eq "x64") { - write-host "cp ${env:VCToolsRedistDir}\${depArch}\Microsoft.VC*.CRT\msvcp140*.dll ${script:DIST_DIR}\lib\ollama\" - cp "${env:VCToolsRedistDir}\${depArch}\Microsoft.VC*.CRT\msvcp140*.dll" "${script:DIST_DIR}\lib\ollama\" - write-host "cp ${env:VCToolsRedistDir}\${depArch}\Microsoft.VC*.CRT\vcruntime140.dll ${script:DIST_DIR}\lib\ollama\" - cp "${env:VCToolsRedistDir}\${depArch}\Microsoft.VC*.CRT\vcruntime140.dll" "${script:DIST_DIR}\lib\ollama\" - write-host "cp ${env:VCToolsRedistDir}\${depArch}\Microsoft.VC*.CRT\vcruntime140_1.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\" - } - } +function deps { write-host "Download MSVC Redistributables" - mkdir -Force -path "${script:SRC_DIR}\dist\\windows-arm64" - mkdir -Force -path "${script:SRC_DIR}\dist\\windows-amd64" + mkdir -Force -path "${script:SRC_DIR}\dist\\windows-arm64" | Out-Null + mkdir -Force -path "${script:SRC_DIR}\dist\\windows-amd64" | Out-Null invoke-webrequest -Uri "https://aka.ms/vs/17/release/vc_redist.arm64.exe" -OutFile "${script:SRC_DIR}\dist\windows-arm64\vc_redist.arm64.exe" invoke-webrequest -Uri "https://aka.ms/vs/17/release/vc_redist.x64.exe" -OutFile "${script:SRC_DIR}\dist\windows-amd64\vc_redist.x64.exe" write-host "Done." - } -function sign() { +function sign { if ("${env:KEY_CONTAINER}") { write-host "Signing Ollama executables, scripts and libraries" & "${script:SignTool}" sign /v /fd sha256 /t http://timestamp.digicert.com /f "${script:OLLAMA_CERT}" ` @@ -305,7 +307,7 @@ function sign() { } } -function installer() { +function installer { if ($null -eq ${script:INNO_SETUP_DIR}) { write-host "ERROR: missing Inno Setup installation directory - install from https://jrsoftware.org/isdl.php" exit 1 @@ -321,7 +323,7 @@ function installer() { if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} } -function zip() { +function zip { if (Test-Path -Path "${script:SRC_DIR}\dist\windows-amd64") { if (Test-Path -Path "${script:SRC_DIR}\dist\windows-amd64\lib\ollama\rocm") { write-host "Generating stand-alone distribution zip file ${script:SRC_DIR}\dist\ollama-windows-amd64-rocm.zip" @@ -346,6 +348,11 @@ function zip() { } } +function clean { + Remove-Item -ea 0 -r "${script:SRC_DIR}\dist\" + Remove-Item -ea 0 -r "${script:SRC_DIR}\build\" +} + checkEnv try { if ($($args.count) -eq 0) { @@ -362,7 +369,7 @@ try { zip } else { for ( $i = 0; $i -lt $args.count; $i++ ) { - write-host "performing $($args[$i])" + write-host "running build step $($args[$i])" & $($args[$i]) } }