From 540f4af45fa233431e7d22a57b300e68428c10de Mon Sep 17 00:00:00 2001 From: Daniel Hiltgen Date: Thu, 7 Mar 2024 10:54:21 -0800 Subject: [PATCH] Wire up more complete CI for releases Flesh out our github actions CI so we can build official releaes. --- .github/workflows/release.yaml | 463 +++++++++++++++++++++++++++++++++ Dockerfile | 1 + llm/generate/gen_windows.ps1 | 65 +++-- scripts/build_docker.sh | 91 +++++-- scripts/build_windows.ps1 | 39 ++- 5 files changed, 598 insertions(+), 61 deletions(-) create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..8195824f --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,463 @@ +name: release + +on: + push: + tags: + - 'v*' + +jobs: + # Full build of the Mac assets + build-darwin: + runs-on: macos-latest + environment: release + steps: + - uses: actions/checkout@v4 + - name: Set Version + shell: bash + run: | + echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV + echo "RELEASE_VERSION=$(echo ${GITHUB_REF_NAME} | cut -f1 -d-)" >> $GITHUB_ENV + - name: key + env: + MACOS_SIGNING_KEY: ${{ secrets.MACOS_SIGNING_KEY }} + MACOS_SIGNING_KEY_PASSWORD: ${{ secrets.MACOS_SIGNING_KEY_PASSWORD }} + 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 + - uses: actions/setup-go@v5 + with: + go-version: '1.22' + cache: true + - name: Build Darwin + env: + APPLE_IDENTITY: ${{ secrets.APPLE_IDENTITY }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ vars.APPLE_TEAM_ID }} + APPLE_ID: ${{ vars.APPLE_ID }} + run: | + ./scripts/build_darwin.sh + + - uses: actions/upload-artifact@v4 + with: + name: dist-darwin + path: | + dist/*arwin* + !dist/*-cov + + + # Windows builds take a long time to both install the dependencies and build, so parallelize + # CPU generation step + generate-windows-cpu: + environment: release + runs-on: windows + env: + KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} + steps: + - uses: actions/checkout@v4 + - name: Set Version + shell: bash + run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV + - uses: 'google-github-actions/auth@v2' + with: + project_id: 'ollama' + credentials_json: '${{ secrets.GOOGLE_SIGNING_CREDENTIALS }}' + - run: echo "${{ vars.OLLAMA_CERT }}" > ollama_inc.crt + - name: install Windows SDK 8.1 to get signtool + run: | + $ErrorActionPreference = "Stop" + write-host "downloading SDK" + Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=323507" -OutFile "${env:RUNNER_TEMP}\sdksetup.exe" + Start-Process "${env:RUNNER_TEMP}\sdksetup.exe" -ArgumentList @("/q") -NoNewWindow -Wait + write-host "Win SDK 8.1 installed" + gci -path 'C:\Program Files (x86)\Windows Kits\' -r -fi 'signtool.exe' + - name: install signing plugin + run: | + $ErrorActionPreference = "Stop" + write-host "downloading plugin" + Invoke-WebRequest -Uri "https://github.com/GoogleCloudPlatform/kms-integrations/releases/download/cng-v1.0/kmscng-1.0-windows-amd64.zip" -OutFile "${env:RUNNER_TEMP}\plugin.zip" + Expand-Archive -Path "${env:RUNNER_TEMP}\plugin.zip" -DestinationPath ${env:RUNNER_TEMP}\plugin\ + write-host "Installing plugin" + & "${env:RUNNER_TEMP}\plugin\*\kmscng.msi" /quiet + write-host "plugin installed" + - uses: actions/setup-go@v5 + with: + go-version: '1.22' + cache: true + - run: go get ./... + - run: | + $gopath=(get-command go).source | split-path -parent + & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Launch-VsDevShell.ps1" + cd $env:GITHUB_WORKSPACE + $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" + $env:PATH="$gopath;$env:PATH" + go generate -x ./... + name: go generate + - uses: actions/upload-artifact@v4 + with: + name: generate-windows-cpu + path: llm/llama.cpp/build/**/lib/* + + # ROCm generation step + generate-windows-rocm: + environment: release + runs-on: windows + env: + KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} + steps: + - uses: actions/checkout@v4 + - name: Set Version + shell: bash + run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV + - uses: 'google-github-actions/auth@v2' + with: + project_id: 'ollama' + credentials_json: '${{ secrets.GOOGLE_SIGNING_CREDENTIALS }}' + - run: echo "${{ vars.OLLAMA_CERT }}" > ollama_inc.crt + - name: install Windows SDK 8.1 to get signtool + run: | + $ErrorActionPreference = "Stop" + write-host "downloading SDK" + Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=323507" -OutFile "${env:RUNNER_TEMP}\sdksetup.exe" + Start-Process "${env:RUNNER_TEMP}\sdksetup.exe" -ArgumentList @("/q") -NoNewWindow -Wait + write-host "Win SDK 8.1 installed" + gci -path 'C:\Program Files (x86)\Windows Kits\' -r -fi 'signtool.exe' + - name: install signing plugin + run: | + $ErrorActionPreference = "Stop" + write-host "downloading plugin" + Invoke-WebRequest -Uri "https://github.com/GoogleCloudPlatform/kms-integrations/releases/download/cng-v1.0/kmscng-1.0-windows-amd64.zip" -OutFile "${env:RUNNER_TEMP}\plugin.zip" + Expand-Archive -Path "${env:RUNNER_TEMP}\plugin.zip" -DestinationPath ${env:RUNNER_TEMP}\plugin\ + write-host "Installing plugin" + & "${env:RUNNER_TEMP}\plugin\*\kmscng.msi" /quiet + write-host "plugin installed" + - uses: actions/setup-go@v5 + with: + go-version: '1.22' + cache: true + - name: "Install ROCm" + run: | + $ErrorActionPreference = "Stop" + write-host "downloading AMD HIP Installer" + Invoke-WebRequest -Uri "https://download.amd.com/developer/eula/rocm-hub/AMD-Software-PRO-Edition-23.Q4-WinSvr2022-For-HIP.exe" -OutFile "${env:RUNNER_TEMP}\rocm-install.exe" + write-host "Installing AMD HIP" + Start-Process "${env:RUNNER_TEMP}\rocm-install.exe" -ArgumentList '-install' -NoNewWindow -Wait + write-host "Completed AMD HIP" + - name: "Verify ROCm" + run: | + & 'C:\Program Files\AMD\ROCm\*\bin\clang.exe' --version + - run: go get ./... + - run: | + $gopath=(get-command go).source | split-path -parent + & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Launch-VsDevShell.ps1" + cd $env:GITHUB_WORKSPACE + $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" + $env:PATH="$gopath;$env:PATH" + $env:OLLAMA_SKIP_CPU_GENERATE="1" + $env:HIP_PATH=$(Resolve-Path 'C:\Program Files\AMD\ROCm\*\bin\clang.exe' | split-path | split-path) + go generate -x ./... + name: go generate + - name: "gather rocm dependencies" + run: | + $HIP_PATH=$(Resolve-Path 'C:\Program Files\AMD\ROCm\*\bin\clang.exe' | split-path | split-path) + md "dist\deps\bin\rocblas\library" + cp "${HIP_PATH}\bin\hipblas.dll" "dist\deps\bin\" + cp "${HIP_PATH}\bin\rocblas.dll" "dist\deps\bin\" + cp "${HIP_PATH}\bin\rocblas\library\*" "dist\deps\bin\rocblas\library\" + - uses: actions/upload-artifact@v4 + with: + name: generate-windows-rocm + path: llm/llama.cpp/build/**/lib/* + - uses: actions/upload-artifact@v4 + with: + name: windows-rocm-deps + path: dist/deps/* + + # CUDA generation step + generate-windows-cuda: + environment: release + runs-on: windows + env: + KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} + steps: + - uses: actions/checkout@v4 + - name: Set Version + shell: bash + run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV + - uses: 'google-github-actions/auth@v2' + with: + project_id: 'ollama' + credentials_json: '${{ secrets.GOOGLE_SIGNING_CREDENTIALS }}' + - run: echo "${{ vars.OLLAMA_CERT }}" > ollama_inc.crt + - name: install Windows SDK 8.1 to get signtool + run: | + $ErrorActionPreference = "Stop" + write-host "downloading SDK" + Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=323507" -OutFile "${env:RUNNER_TEMP}\sdksetup.exe" + Start-Process "${env:RUNNER_TEMP}\sdksetup.exe" -ArgumentList @("/q") -NoNewWindow -Wait + write-host "Win SDK 8.1 installed" + gci -path 'C:\Program Files (x86)\Windows Kits\' -r -fi 'signtool.exe' + - name: install signing plugin + run: | + $ErrorActionPreference = "Stop" + write-host "downloading plugin" + Invoke-WebRequest -Uri "https://github.com/GoogleCloudPlatform/kms-integrations/releases/download/cng-v1.0/kmscng-1.0-windows-amd64.zip" -OutFile "${env:RUNNER_TEMP}\plugin.zip" + Expand-Archive -Path "${env:RUNNER_TEMP}\plugin.zip" -DestinationPath ${env:RUNNER_TEMP}\plugin\ + write-host "Installing plugin" + & "${env:RUNNER_TEMP}\plugin\*\kmscng.msi" /quiet + write-host "plugin installed" + - uses: actions/setup-go@v5 + with: + go-version: '1.22' + cache: true + # TODO - consider replacing this action with a ps1 snippet to install + # This actions seems to fail sometimes with "no tools in cache" but a re-run of the failed job clears it + # https://developer.download.nvidia.com/compute/cuda/11.3.1/local_installers/cuda_11.3.1_465.89_win10.exe + - name: "Install CUDA" + uses: Jimver/cuda-toolkit@v0.2.14 + id: cuda-toolkit + with: + cuda: '11.3.1' + - name: "Verify CUDA" + run: nvcc -V + - run: go get ./... + - name: go generate + run: | + $gopath=(get-command go).source | split-path -parent + & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Launch-VsDevShell.ps1" + cd $env:GITHUB_WORKSPACE + $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" + $env:PATH="$gopath;$env:PATH" + $env:OLLAMA_SKIP_CPU_GENERATE="1" + go generate -x ./... + - name: "gather cuda dependencies" + run: | + $NVIDIA_DIR=(resolve-path 'C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\*\bin\')[0] + md "dist\deps" + cp "${NVIDIA_DIR}\cudart64_*.dll" "dist\deps\" + cp "${NVIDIA_DIR}\cublas64_*.dll" "dist\deps\" + cp "${NVIDIA_DIR}\cublasLt64_*.dll" "dist\deps\" + - uses: actions/upload-artifact@v4 + with: + name: generate-windows-cuda + path: llm/llama.cpp/build/**/lib/* + - uses: actions/upload-artifact@v4 + with: + name: windows-cuda-deps + path: dist/deps/* + + # Import the prior generation steps and build the final windows assets + build-windows: + environment: release + runs-on: windows + needs: + - generate-windows-cuda + - generate-windows-rocm + - generate-windows-cpu + env: + KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Set Version + shell: bash + run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV + - uses: 'google-github-actions/auth@v2' + with: + project_id: 'ollama' + credentials_json: '${{ secrets.GOOGLE_SIGNING_CREDENTIALS }}' + - run: echo "${{ vars.OLLAMA_CERT }}" > ollama_inc.crt + - name: install Windows SDK 8.1 to get signtool + run: | + $ErrorActionPreference = "Stop" + write-host "downloading SDK" + Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=323507" -OutFile "${env:RUNNER_TEMP}\sdksetup.exe" + Start-Process "${env:RUNNER_TEMP}\sdksetup.exe" -ArgumentList @("/q") -NoNewWindow -Wait + write-host "Win SDK 8.1 installed" + gci -path 'C:\Program Files (x86)\Windows Kits\' -r -fi 'signtool.exe' + - name: install signing plugin + run: | + $ErrorActionPreference = "Stop" + write-host "downloading plugin" + Invoke-WebRequest -Uri "https://github.com/GoogleCloudPlatform/kms-integrations/releases/download/cng-v1.0/kmscng-1.0-windows-amd64.zip" -OutFile "${env:RUNNER_TEMP}\plugin.zip" + Expand-Archive -Path "${env:RUNNER_TEMP}\plugin.zip" -DestinationPath ${env:RUNNER_TEMP}\plugin\ + write-host "Installing plugin" + & "${env:RUNNER_TEMP}\plugin\*\kmscng.msi" /quiet + write-host "plugin installed" + - uses: actions/setup-go@v5 + with: + go-version: '1.22' + cache: true + - run: go get + - uses: actions/download-artifact@v4 + with: + name: generate-windows-cpu + path: llm/llama.cpp/build + - uses: actions/download-artifact@v4 + with: + name: generate-windows-cuda + path: llm/llama.cpp/build + - uses: actions/download-artifact@v4 + with: + name: windows-cuda-deps + path: dist/deps + - uses: actions/download-artifact@v4 + with: + name: windows-rocm-deps + path: dist/deps + - uses: actions/download-artifact@v4 + with: + name: generate-windows-rocm + path: llm/llama.cpp/build + - run: dir llm/llama.cpp/build + - run: | + $gopath=(get-command go).source | split-path -parent + & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Launch-VsDevShell.ps1" + cd $env:GITHUB_WORKSPACE + $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" + $env:PATH="$gopath;$env:PATH" + $env:OLLAMA_SKIP_GENERATE="1" + $env:NVIDIA_DIR=$(resolve-path ".\dist\deps") + $env:HIP_PATH=$(resolve-path ".\dist\deps") + & .\scripts\build_windows.ps1 + - uses: actions/upload-artifact@v4 + with: + name: dist-windows + path: dist/*.exe + + # Linux x86 assets built using the container based build + build-linux-amd64: + environment: release + runs-on: linux + env: + OLLAMA_SKIP_MANIFEST_CREATE: "1" + BUILD_ARCH: amd64 + PUSH: "1" + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Set Version + shell: bash + run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ vars.DOCKER_USER }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + - run: | + ./scripts/build_linux.sh + ./scripts/build_docker.sh + mv dist/deps/* dist/ + - uses: actions/upload-artifact@v4 + with: + name: dist-linux-amd64 + path: | + dist/*linux* + !dist/*-cov + + # Linux ARM assets built using the container based build + # (at present, docker isn't pre-installed on arm ubunutu images) + build-linux-arm64: + environment: release + runs-on: linux-arm64 + env: + OLLAMA_SKIP_MANIFEST_CREATE: "1" + BUILD_ARCH: arm64 + PUSH: "1" + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Set Version + shell: bash + run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV + - name: "Install Docker" + run: | + # Add Docker's official GPG key: + env + uname -a + sudo apt-get update + sudo apt-get install -y ca-certificates curl + sudo install -m 0755 -d /etc/apt/keyrings + sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc + sudo chmod a+r /etc/apt/keyrings/docker.asc + + # Add the repository to Apt sources: + echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + sudo apt-get update + sudo apt-get install -y docker-ce docker-ce-cli containerd.io + sudo usermod -aG docker $USER + sudo apt-get install acl + sudo setfacl --modify user:$USER:rw /var/run/docker.sock + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ vars.DOCKER_USER }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + - run: | + ./scripts/build_linux.sh + ./scripts/build_docker.sh + - uses: actions/upload-artifact@v4 + with: + name: dist-linux-arm64 + path: | + dist/*linux* + !dist/*-cov + + # Aggregate all the assets and ship a release + release: + needs: + - build-darwin + - build-windows + - build-linux-amd64 + - build-linux-arm64 + runs-on: ubuntu-latest + environment: release + permissions: + contents: write + env: + OLLAMA_SKIP_IMAGE_BUILD: "1" + PUSH: "1" + steps: + - uses: actions/checkout@v4 + - name: Set Version + shell: bash + run: | + echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV + echo "RELEASE_VERSION=$(echo ${GITHUB_REF_NAME} | cut -f1 -d-)" >> $GITHUB_ENV + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ vars.DOCKER_USER }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + - run: ./scripts/build_docker.sh + - name: Retrieve built artifact + uses: actions/download-artifact@v4 + with: + path: dist + pattern: dist-* + merge-multiple: true + - run: | + ls -lh dist/ + (cd dist; sha256sum * > sha256sum.txt) + cat dist/sha256sum.txt + - uses: ncipollo/release-action@v1 + with: + name: ${{ env.RELEASE_VERSION }} + allowUpdates: true + artifacts: "dist/*" + draft: true + prerelease: true + omitBodyDuringUpdate: true + generateReleaseNotes: true + omitDraftDuringUpdate: true + omitPrereleaseDuringUpdate: true + replacesArtifacts: true \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 0cbc7e34..8e0fd010 100644 --- a/Dockerfile +++ b/Dockerfile @@ -101,6 +101,7 @@ ARG GOLANG_VERSION WORKDIR /go/src/github.com/jmorganca/ollama COPY . . COPY --from=cuda-build-arm64 /go/src/github.com/jmorganca/ollama/llm/llama.cpp/build/linux/ llm/llama.cpp/build/linux/ +RUN mkdir -p /go/src/github.com/jmorganca/ollama/dist/deps/ ARG GOFLAGS ARG CGO_CFLAGS RUN go build -trimpath . diff --git a/llm/generate/gen_windows.ps1 b/llm/generate/gen_windows.ps1 index 579b2bca..f381477a 100644 --- a/llm/generate/gen_windows.ps1 +++ b/llm/generate/gen_windows.ps1 @@ -65,8 +65,12 @@ function init_vars { } else { $script:CMAKE_CUDA_ARCHITECTURES=$env:CMAKE_CUDA_ARCHITECTURES } - # Note: 10 Windows Kit signtool crashes with GCP's plugin - ${script:SignTool}="C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" + # 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") } @@ -139,7 +143,7 @@ function sign { if ("${env:KEY_CONTAINER}") { write-host "Signing ${script:buildDir}/lib/*.dll" foreach ($file in (get-childitem "${script:buildDir}/lib/*.dll")){ - & "${script:SignTool}" sign /v /fd sha256 /t http://timestamp.digicert.com /f "${script:OLLAMA_CERT}" ` + & "${script:SignTool}" sign /v /debug /fd sha256 /t http://timestamp.digicert.com /f "${script:OLLAMA_CERT}" ` /csp "Google Cloud KMS Provider" /kc "${env:KEY_CONTAINER}" $file if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} } @@ -189,32 +193,37 @@ apply_patches $script:commonCpuDefs = @("-DCMAKE_POSITION_INDEPENDENT_CODE=on") -init_vars -$script:cmakeDefs = $script:commonCpuDefs + @("-A", "x64", "-DLLAMA_AVX=off", "-DLLAMA_AVX2=off", "-DLLAMA_AVX512=off", "-DLLAMA_FMA=off", "-DLLAMA_F16C=off") + $script:cmakeDefs -$script:buildDir="${script:llamacppDir}/build/windows/${script:ARCH}/cpu" -write-host "Building LCD CPU" -build -install -sign -compress_libs +if ($null -eq ${env:OLLAMA_SKIP_CPU_GENERATE}) { -init_vars -$script:cmakeDefs = $script:commonCpuDefs + @("-A", "x64", "-DLLAMA_AVX=on", "-DLLAMA_AVX2=off", "-DLLAMA_AVX512=off", "-DLLAMA_FMA=off", "-DLLAMA_F16C=off") + $script:cmakeDefs -$script:buildDir="${script:llamacppDir}/build/windows/${script:ARCH}/cpu_avx" -write-host "Building AVX CPU" -build -install -sign -compress_libs + init_vars + $script:cmakeDefs = $script:commonCpuDefs + @("-A", "x64", "-DLLAMA_AVX=off", "-DLLAMA_AVX2=off", "-DLLAMA_AVX512=off", "-DLLAMA_FMA=off", "-DLLAMA_F16C=off") + $script:cmakeDefs + $script:buildDir="${script:llamacppDir}/build/windows/${script:ARCH}/cpu" + write-host "Building LCD CPU" + build + install + sign + compress_libs -init_vars -$script:cmakeDefs = $script:commonCpuDefs + @("-A", "x64", "-DLLAMA_AVX=on", "-DLLAMA_AVX2=on", "-DLLAMA_AVX512=off", "-DLLAMA_FMA=on", "-DLLAMA_F16C=on") + $script:cmakeDefs -$script:buildDir="${script:llamacppDir}/build/windows/${script:ARCH}/cpu_avx2" -write-host "Building AVX2 CPU" -build -install -sign -compress_libs + init_vars + $script:cmakeDefs = $script:commonCpuDefs + @("-A", "x64", "-DLLAMA_AVX=on", "-DLLAMA_AVX2=off", "-DLLAMA_AVX512=off", "-DLLAMA_FMA=off", "-DLLAMA_F16C=off") + $script:cmakeDefs + $script:buildDir="${script:llamacppDir}/build/windows/${script:ARCH}/cpu_avx" + write-host "Building AVX CPU" + build + install + sign + compress_libs + + init_vars + $script:cmakeDefs = $script:commonCpuDefs + @("-A", "x64", "-DLLAMA_AVX=on", "-DLLAMA_AVX2=on", "-DLLAMA_AVX512=off", "-DLLAMA_FMA=on", "-DLLAMA_F16C=on") + $script:cmakeDefs + $script:buildDir="${script:llamacppDir}/build/windows/${script:ARCH}/cpu_avx2" + write-host "Building AVX2 CPU" + build + install + sign + compress_libs +} else { + write-host "Skipping CPU generation step as requested" +} if ($null -ne $script:CUDA_LIB_DIR) { # Then build cuda as a dynamically loaded library @@ -272,4 +281,4 @@ if ($null -ne $env:HIP_PATH) { } cleanup -write-host "`ngo generate completed" +write-host "`ngo generate completed. LLM runners: $(get-childitem -path ${script:SRC_DIR}\llm\llama.cpp\build\windows\${script:ARCH})" diff --git a/scripts/build_docker.sh b/scripts/build_docker.sh index a3aa4264..7bdad641 100755 --- a/scripts/build_docker.sh +++ b/scripts/build_docker.sh @@ -5,30 +5,73 @@ set -eu export VERSION=${VERSION:-$(git describe --tags --first-parent --abbrev=7 --long --dirty --always | sed -e "s/^v//g")} export GOFLAGS="'-ldflags=-w -s \"-X=github.com/jmorganca/ollama/version.Version=$VERSION\" \"-X=github.com/jmorganca/ollama/server.mode=release\"'" -IMAGE_NAME=${IMAGE_NAME:-"ollama/ollama"} -BUILD_PLATFORM=${BUILD_PLATFORM:-"linux/arm64,linux/amd64"} -docker build \ - --load \ - --platform=${BUILD_PLATFORM} \ - --build-arg=VERSION \ - --build-arg=GOFLAGS \ - -f Dockerfile \ - -t ${IMAGE_NAME}:$VERSION \ - . +# We use 2 different image repositories to handle combining architecture images into multiarch manifest +# (The ROCm image is x86 only and is not a multiarch manifest) +# For developers, you can override the DOCKER_ORG to generate multiarch manifests +# DOCKER_ORG=jdoe PUSH=1 ./scripts/build_docker.sh +DOCKER_ORG=${DOCKER_ORG:-"ollama"} +ARCH_IMAGE_REPO=${ARCH_IMAGE_REPO:-"${DOCKER_ORG}/release"} +FINAL_IMAGE_REPO=${FINAL_IMAGE_REPO:-"${DOCKER_ORG}/ollama"} -docker build \ - --load \ - --platform=linux/amd64 \ - --build-arg=VERSION \ - --build-arg=GOFLAGS \ - --target runtime-rocm \ - -f Dockerfile \ - -t ${IMAGE_NAME}:$VERSION-rocm \ - . +BUILD_ARCH=${BUILD_ARCH:-"amd64 arm64"} -docker tag ${IMAGE_NAME}:$VERSION ${IMAGE_NAME}:latest -docker tag ${IMAGE_NAME}:$VERSION-rocm ${IMAGE_NAME}:rocm +# Set PUSH to a non-empty string to trigger push instead of load +PUSH=${PUSH:-""} -echo "To release, run:" -echo " docker push ${IMAGE_NAME}:$VERSION && docker push ${IMAGE_NAME}:latest" -echo " docker push ${IMAGE_NAME}:$VERSION-rocm && docker push ${IMAGE_NAME}:rocm" \ No newline at end of file +# In CI mode, we break things down +OLLAMA_SKIP_MANIFEST_CREATE=${OLLAMA_SKIP_MANIFEST_CREATE:-""} +OLLAMA_SKIP_IMAGE_BUILD=${OLLAMA_SKIP_IMAGE_BUILD:-""} + +if [ -z "${PUSH}" ] ; then + LOAD_OR_PUSH="--load" +else + echo "Will be pushing ${ARCH_IMAGE_REPO}:$VERSION for ${BUILD_ARCH}" + LOAD_OR_PUSH="--push" +fi + +if [ -z "${OLLAMA_SKIP_IMAGE_BUILD}" ]; then + for TARGETARCH in ${BUILD_ARCH}; do + docker build \ + ${LOAD_OR_PUSH} \ + --platform=linux/${TARGETARCH} \ + --build-arg=VERSION \ + --build-arg=GOFLAGS \ + -f Dockerfile \ + -t ${ARCH_IMAGE_REPO}:$VERSION-${TARGETARCH} \ + . + done + + if echo ${BUILD_ARCH} | grep "amd64" > /dev/null; then + docker build \ + ${LOAD_OR_PUSH} \ + --platform=linux/amd64 \ + --build-arg=VERSION \ + --build-arg=GOFLAGS \ + --target runtime-rocm \ + -f Dockerfile \ + -t ${ARCH_IMAGE_REPO}:$VERSION-rocm \ + . + fi +fi + +if [ -z "${OLLAMA_SKIP_MANIFEST_CREATE}" ]; then + if [ -n "${PUSH}" ]; then + docker manifest create ${FINAL_IMAGE_REPO}:$VERSION \ + ${ARCH_IMAGE_REPO}:$VERSION-amd64 \ + ${ARCH_IMAGE_REPO}:$VERSION-arm64 + docker manifest push ${FINAL_IMAGE_REPO}:$VERSION + + # For symmetry, tag/push the rocm image + if [ "${ARCH_IMAGE_REPO}" != "${FINAL_IMAGE_REPO}" ]; then + echo "Tagging and pushing rocm image" + docker pull ${ARCH_IMAGE_REPO}:$VERSION-rocm + docker tag ${ARCH_IMAGE_REPO}:$VERSION-rocm ${FINAL_IMAGE_REPO}:$VERSION-rocm + docker push ${FINAL_IMAGE_REPO}:$VERSION-rocm + fi + else + echo "Skipping manifest generation when not pushing images are available locally as " + echo " ${ARCH_IMAGE_REPO}:$VERSION-amd64" + echo " ${ARCH_IMAGE_REPO}:$VERSION-arm64" + echo " ${ARCH_IMAGE_REPO}:$VERSION-rocm" + fi +fi \ No newline at end of file diff --git a/scripts/build_windows.ps1 b/scripts/build_windows.ps1 index ee184799..e6e1f4b0 100644 --- a/scripts/build_windows.ps1 +++ b/scripts/build_windows.ps1 @@ -13,7 +13,21 @@ function checkEnv() { $MSVC_INSTALL=(Get-CimInstance MSFT_VSInstance -Namespace root/cimv2/vs)[0].InstallLocation $env:VCToolsRedistDir=(get-item "${MSVC_INSTALL}\VC\Redist\MSVC\*")[0] } - $script:NVIDIA_DIR=(get-item "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v*\bin\")[0] + # Try to find the CUDA dir + if ($null -eq $env:NVIDIA_DIR) { + $d=(get-command -ea 'silentlycontinue' nvcc).path + if ($d -ne $null) { + $script:NVIDIA_DIR=($d| split-path -parent) + } else { + $cudaList=(get-item "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v*\bin\" -ea 'silentlycontinue') + if ($cudaList.length > 0) { + $script:NVIDIA_DIR=$cudaList[0] + } + } + } else { + $script:NVIDIA_DIR=$env:NVIDIA_DIR + } + $script:INNO_SETUP_DIR=(get-item "C:\Program Files*\Inno Setup*\")[0] $script:DEPS_DIR="${script:SRC_DIR}\dist\windeps" @@ -28,20 +42,23 @@ function checkEnv() { } else { $script:VERSION=$env:VERSION } - $pattern = "(\d+[.]\d+[.]\d+)-(\d+)-" + $pattern = "(\d+[.]\d+[.]\d+).*" if ($script:VERSION -match $pattern) { - $script:PKG_VERSION=$matches[1] + "." + $matches[2] + $script:PKG_VERSION=$matches[1] } else { - $script:PKG_VERSION=$script:VERSION + $script:PKG_VERSION="0.0.0" } write-host "Building Ollama $script:VERSION with package version $script:PKG_VERSION" - # Check for signing key + # 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" - # Note: 10 Windows Kit signtool crashes with GCP's plugin - ${script:SignTool}="C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" } else { write-host "Code signing disabled - please set KEY_CONTAINERS to sign and copy ollama_inc.crt to the top of the source tree" } @@ -51,8 +68,12 @@ function checkEnv() { function buildOllama() { write-host "Building ollama CLI" - & go generate ./... - if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} + if ($null -eq ${env:OLLAMA_SKIP_GENERATE}) { + & go generate ./... + if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} + } else { + write-host "Skipping generate step with OLLAMA_SKIP_GENERATE set" + } & go build -trimpath -ldflags "-s -w -X=github.com/jmorganca/ollama/version.Version=$script:VERSION -X=github.com/jmorganca/ollama/server.mode=release" . if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} if ("${env:KEY_CONTAINER}") {