diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0748b7c10..e5ac2833e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -274,7 +274,132 @@ jobs: path: dist/deps/* - # Import the prior generation steps and build the final windows assets + # windows arm64 generate, go build, and zip file (no installer) + # Output of this build is aggregated into the final x86 build + # for a unified windows installer + windows-arm64: + runs-on: windows-arm64 + environment: release + env: + KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} + steps: + - name: Set Version + run: | + $ver=${env:GITHUB_REF_NAME}.trim("v") + write-host VERSION=$ver | Out-File -FilePath ${env:GITHUB_ENV} -Encoding utf8 -Append + - uses: 'google-github-actions/auth@v2' + with: + project_id: 'ollama' + credentials_json: '${{ secrets.GOOGLE_SIGNING_CREDENTIALS }}' + - run: echo "${{ vars.OLLAMA_CERT }}" | Out-File -FilePath ollama_inc.crt -Encoding utf8 + - 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" + # The current Windows arm64 beta image has effectively zero dev tools installed... + - name: Install git and gzip + run: | + Set-ExecutionPolicy Bypass -Scope Process -Force + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 + iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + choco install -y --no-progress git gzip + echo "C:\Program Files\Git\cmd" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + - name: Install Visual Studio 2022 + run: | + $components = @( + "Microsoft.VisualStudio.Component.CoreEditor", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.VisualStudio.Component.Roslyn.Compiler", + "Microsoft.Component.MSBuild", + "Microsoft.VisualStudio.Component.TextTemplating", + "Microsoft.VisualStudio.Component.Debugger.JustInTime", + "Microsoft.VisualStudio.Component.VC.CoreIde", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.Component.Windows11SDK.22621", + "Microsoft.VisualStudio.Component.VC.Tools.ARM64EC", + "Microsoft.VisualStudio.Component.VC.Tools.ARM64", + "Microsoft.VisualStudio.Component.VC.ATL", + "Microsoft.VisualStudio.Component.VC.ATL.ARM64", + "Microsoft.VisualStudio.Component.Graphics", + "Microsoft.VisualStudio.Component.VC.Redist.14.Latest", + "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core", + "Microsoft.VisualStudio.Component.Windows11Sdk.WindowsPerformanceToolkit", + "Microsoft.VisualStudio.Component.CppBuildInsights", + "Microsoft.VisualStudio.Component.VC.DiagnosticTools", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.CMake", + "Microsoft.VisualStudio.Component.VC.CMake.Project", + "Microsoft.VisualStudio.Component.VC.ASAN", + "Microsoft.VisualStudio.Component.Vcpkg", + "Microsoft.VisualStudio.Workload.NativeDesktop" + ) + $config = @{ + "version" = "1.0" + "components" = $components + "extensions" = @() + } + $configPath = "${env:RUNNER_TEMP}\vsconfig" + $config | ConvertTo-Json | Out-File -FilePath $configPath + $bootstrapperFilePath = "${env:RUNNER_TEMP}\vs_community.exe" + write-host "Downloading Visual Studio 2022" + Invoke-WebRequest -Uri "https://aka.ms/vs/17/release/vs_community.exe" -outfile $bootstrapperFilePath + $bootstrapperArgumentList = ('/c', $bootstrapperFilePath, '--config', $configPath, '--quiet', '--wait' ) + write-host "Installing Visual Studio 2022" + $process = Start-Process -FilePath cmd.exe -ArgumentList $bootstrapperArgumentList -Wait -PassThru + $exitCode = $process.ExitCode + write-host $exitCode + # pacman in mingw/msys2 is ~broken on windows arm right now - hangs consistently during attempts to install + # so we'll use this alternative GCC binary + - name: Install llvm-mingw GCC + run: | + $gcc_url="https://github.com/mstorsjo/llvm-mingw/releases/download/20240619/llvm-mingw-20240619-ucrt-aarch64.zip" + write-host "Downloading llvm-mingw" + Invoke-WebRequest -Uri "${gcc_url}" -OutFile "${env:RUNNER_TEMP}\gcc.zip" + write-host "Unpacking llvm-mingw" + expand-archive -path "${env:RUNNER_TEMP}\gcc.zip" -destinationpath "c:\" + mv c:\llvm-mingw-* c:\llvm-mingw + echo "c:\llvm-mingw\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + - name: Verify GCC + run: | + echo $env:PATH + gcc --version + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache: true + - run: go get ./... + - run: | + $gopath=(get-command go).source | split-path -parent + $gccpath=(get-command gcc).source | split-path -parent + & "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\Launch-VsDevShell.ps1" + cd $env:GITHUB_WORKSPACE + $env:CMAKE_SYSTEM_VERSION="10.0.22621.0" + $env:PATH="$gopath;$gccpath;$env:PATH;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin" + echo $env:PATH + .\scripts\build_windows.ps1 buildOllama buildApp gatherDependencies distZip + name: 'Windows Build' + - uses: actions/upload-artifact@v4 + with: + name: windows-arm64 + path: | + dist/windows-arm64/** + dist/windows-arm64-app.exe + dist/ollama-windows-arm64.zip + + # Import the prior generation steps plus the full arm64 build, and build the final windows assets build-windows: environment: release runs-on: windows @@ -282,6 +407,7 @@ jobs: - generate-windows-cuda - generate-windows-rocm - generate-windows-cpu + - windows-arm64 env: KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} steps: @@ -339,6 +465,9 @@ jobs: - uses: actions/download-artifact@v4 with: name: generate-windows-rocm + - uses: actions/download-artifact@v4 + with: + name: windows-arm64 - run: dir build - run: | $gopath=(get-command go).source | split-path -parent diff --git a/app/ollama.iss b/app/ollama.iss index 34cc5c4cd..63b5bdb0f 100644 --- a/app/ollama.iss +++ b/app/ollama.iss @@ -28,8 +28,8 @@ AppPublisher={#MyAppPublisher} AppPublisherURL={#MyAppURL} AppSupportURL={#MyAppURL} AppUpdatesURL={#MyAppURL} -ArchitecturesAllowed=x64 arm64 -ArchitecturesInstallIn64BitMode=x64 arm64 +ArchitecturesAllowed=x64compatible arm64 +ArchitecturesInstallIn64BitMode=x64compatible arm64 DefaultDirName={localappdata}\Programs\{#MyAppName} DefaultGroupName={#MyAppName} DisableProgramGroupPage=yes @@ -48,6 +48,7 @@ OutputDir=..\dist\ SetupLogging=yes CloseApplications=yes RestartApplications=no +RestartIfNeededByRun=no ; https://jrsoftware.org/ishelp/index.php?topic=setup_wizardimagefile WizardSmallImageFile=.\assets\setup.bmp @@ -86,12 +87,21 @@ Name: "english"; MessagesFile: "compiler:Default.isl" DialogFontSize=12 [Files] -Source: ".\app.exe"; DestDir: "{app}"; DestName: "{#MyAppExeName}" ; Flags: ignoreversion 64bit -Source: "..\ollama.exe"; DestDir: "{app}"; Flags: ignoreversion 64bit -Source: "..\dist\windows-{#ARCH}\lib\ollama\runners\*"; DestDir: "{app}\lib\ollama\runners"; Flags: ignoreversion 64bit recursesubdirs +#if DirExists("..\dist\windows-amd64") +Source: "..\dist\windows-amd64-app.exe"; DestDir: "{app}"; DestName: "{#MyAppExeName}" ;Check: not IsArm64(); Flags: ignoreversion 64bit +Source: "..\dist\windows-amd64\ollama.exe"; DestDir: "{app}"; Check: not IsArm64(); Flags: ignoreversion 64bit +Source: "..\dist\windows-amd64\lib\ollama\*"; DestDir: "{app}\lib\ollama\"; Check: not IsArm64(); Flags: ignoreversion 64bit recursesubdirs +#endif + +#if DirExists("..\dist\windows-arm64") +Source: "..\dist\windows-arm64\vc_redist.arm64.exe"; DestDir: "{tmp}"; Check: IsArm64() and vc_redist_needed(); Flags: deleteafterinstall +Source: "..\dist\windows-arm64-app.exe"; DestDir: "{app}"; DestName: "{#MyAppExeName}" ;Check: IsArm64(); Flags: ignoreversion 64bit +Source: "..\dist\windows-arm64\ollama.exe"; DestDir: "{app}"; Check: IsArm64(); Flags: ignoreversion 64bit +Source: "..\dist\windows-arm64\lib\ollama\*"; DestDir: "{app}\lib\ollama\"; Check: IsArm64(); Flags: ignoreversion 64bit recursesubdirs +#endif + Source: "..\dist\ollama_welcome.ps1"; DestDir: "{app}"; Flags: ignoreversion Source: ".\assets\app.ico"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\dist\windows-amd64\lib\ollama\*"; DestDir: "{app}\lib\ollama\"; Flags: ignoreversion recursesubdirs [Icons] Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\app.ico" @@ -99,6 +109,9 @@ Name: "{userstartup}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilen Name: "{userprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\app.ico" [Run] +#if DirExists("..\dist\windows-arm64") +Filename: "{tmp}\vc_redist.arm64.exe"; Parameters: "/install /passive /norestart"; Check: IsArm64() and vc_redist_needed(); StatusMsg: "Installing VC++ Redistributables..."; Flags: waituntilterminated +#endif Filename: "{cmd}"; Parameters: "/C set PATH={app};%PATH% & ""{app}\{#MyAppExeName}"""; Flags: postinstall nowait runhidden [UninstallRun] @@ -154,3 +167,39 @@ begin { Pos() returns 0 if not found } Result := Pos(';' + ExpandConstant(Param) + ';', ';' + OrigPath + ';') = 0; end; + +{ --- VC Runtime libraries discovery code - Only install vc_redist if it isn't already installed ----- } +const VCRTL_MIN_V1 = 14; +const VCRTL_MIN_V2 = 40; +const VCRTL_MIN_V3 = 33807; +const VCRTL_MIN_V4 = 0; + + // check if the minimum required vc redist is installed (by looking the registry) +function vc_redist_needed (): Boolean; +var + sRegKey: string; + v1: Cardinal; + v2: Cardinal; + v3: Cardinal; + v4: Cardinal; +begin + sRegKey := 'SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\arm64'; + if (RegQueryDWordValue (HKEY_LOCAL_MACHINE, sRegKey, 'Major', v1) and + RegQueryDWordValue (HKEY_LOCAL_MACHINE, sRegKey, 'Minor', v2) and + RegQueryDWordValue (HKEY_LOCAL_MACHINE, sRegKey, 'Bld', v3) and + RegQueryDWordValue (HKEY_LOCAL_MACHINE, sRegKey, 'RBld', v4)) then + begin + Log ('VC Redist version: ' + IntToStr (v1) + + '.' + IntToStr (v2) + '.' + IntToStr (v3) + + '.' + IntToStr (v4)); + { Version info was found. Return true if later or equal to our + minimal required version RTL_MIN_Vx } + Result := not ( + (v1 > VCRTL_MIN_V1) or ((v1 = VCRTL_MIN_V1) and + ((v2 > VCRTL_MIN_V2) or ((v2 = VCRTL_MIN_V2) and + ((v3 > VCRTL_MIN_V3) or ((v3 = VCRTL_MIN_V3) and + (v4 >= VCRTL_MIN_V4))))))); + end + else + Result := TRUE; +end; diff --git a/docs/development.md b/docs/development.md index cd6c41af5..e67689abc 100644 --- a/docs/development.md +++ b/docs/development.md @@ -148,3 +148,22 @@ In addition to the common Windows development tools described above, install AMD - [Strawberry Perl](https://strawberryperl.com/) Lastly, add `ninja.exe` included with MSVC to the system path (e.g. `C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja`). + +#### Windows arm64 + +The default `Developer PowerShell for VS 2022` may default to x86 which is not what you want. To ensure you get an arm64 development environment, start a plain PowerShell terminal and run: + +```powershell +import-module 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\Tools\\Microsoft.VisualStudio.DevShell.dll' +Enter-VsDevShell -Arch arm64 -vsinstallpath 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community' -skipautomaticlocation +``` + +You can confirm with `write-host $env:VSCMD_ARG_TGT_ARCH` + +Follow the instructions at https://www.msys2.org/wiki/arm64/ to set up an arm64 msys2 environment. Ollama requires gcc and mingw32-make to compile, which is not currently available on Windows arm64, but a gcc compatibility adapter is available via `mingw-w64-clang-aarch64-gcc-compat`. At a minimum you will need to install the following: + +``` +pacman -S mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-gcc-compat mingw-w64-clang-aarch64-make make +``` + +You will need to ensure your PATH includes go, cmake, gcc and clang mingw32-make to build ollama from source. (typically `C:\msys64\clangarm64\bin\`) \ No newline at end of file diff --git a/llm/ext_server/CMakeLists.txt b/llm/ext_server/CMakeLists.txt index 88c8b03d7..517302451 100644 --- a/llm/ext_server/CMakeLists.txt +++ b/llm/ext_server/CMakeLists.txt @@ -10,5 +10,6 @@ target_compile_definitions(${TARGET} PRIVATE target_link_libraries(${TARGET} PRIVATE ggml llama common llava ${CMAKE_THREAD_LIBS_INIT} ${LLAMA_SERVER_LDFLAGS}) if (WIN32) TARGET_LINK_LIBRARIES(${TARGET} PRIVATE ws2_32) + target_link_options(${TARGET} PRIVATE -municode -Wl,/subsystem:console) endif() target_compile_features(${TARGET} PRIVATE cxx_std_11) \ No newline at end of file diff --git a/llm/generate/gen_windows.ps1 b/llm/generate/gen_windows.ps1 index 225388516..29ff5ff62 100644 --- a/llm/generate/gen_windows.ps1 +++ b/llm/generate/gen_windows.ps1 @@ -19,6 +19,19 @@ function amdGPUs { function init_vars { + write-host "Checking for cmake..." + get-command cmake + write-host "Checking for ninja..." + $d=(get-command -ea 'silentlycontinue' ninja).path + if ($null -eq $d) { + $MSVC_INSTALL=(Get-CimInstance MSFT_VSInstance -Namespace root/cimv2/vs)[0].InstallLocation + $matches=(gci -path $MSVC_INSTALL -r -fi ninja.exe) + if ($matches.count -eq 0) { + throw "Unable to locate ninja" + } + $ninjaDir=($matches[0].FullName | split-path -parent) + $env:PATH="$env:PATH;$ninjaDir" + } if (!$script:SRC_DIR) { $script:SRC_DIR = $(resolve-path "..\..\") } @@ -145,7 +158,7 @@ function cleanup { } # Checkout each file - foreach ($file in $filePaths) { + foreach ($file in $filePaths) { git -C "${script:llamacppDir}" checkout $file } git -C "${script:llamacppDir}" checkout CMakeLists.txt @@ -162,12 +175,12 @@ function build_static() { if ((-not "${env:OLLAMA_SKIP_STATIC_GENERATE}") -and ((-not "${env:OLLAMA_CPU_TARGET}") -or ("${env:OLLAMA_CPU_TARGET}" -eq "static"))) { # GCC build for direct linking into the Go binary init_vars - # cmake will silently fallback to msvc compilers if mingw isn't in the path, so detect and fail fast - # as we need this to be compiled by gcc for golang to be able to link with itx - write-host "Checking for MinGW..." - # error action ensures we exit on failure - get-command gcc - get-command mingw32-make + + # cmake will silently fallback to msvc compilers if gcc isn't in the path, so detect and fail fast + # as we need this to be compiled by gcc for golang to be able to link with it + write-host "Checking for gcc..." + get-command gcc + get-command mingw32-make $oldTargets = $script:cmakeTargets $script:cmakeTargets = @("llama", "ggml") $script:cmakeDefs = @( @@ -191,11 +204,10 @@ function build_static() { } } -function build_cpu($gen_arch) { +function build_cpu_x64 { if ((-not "${env:OLLAMA_SKIP_CPU_GENERATE}" ) -and ((-not "${env:OLLAMA_CPU_TARGET}") -or ("${env:OLLAMA_CPU_TARGET}" -eq "cpu"))) { - # remaining llama.cpp builds use MSVC init_vars - $script:cmakeDefs = $script:commonCpuDefs + @("-A", $gen_arch, "-DGGML_AVX=off", "-DGGML_AVX2=off", "-DGGML_AVX512=off", "-DGGML_FMA=off", "-DGGML_F16C=off") + $script:cmakeDefs + $script:cmakeDefs = $script:commonCpuDefs + @("-A", "x64", "-DGGML_AVX=off", "-DGGML_AVX2=off", "-DGGML_AVX512=off", "-DGGML_FMA=off", "-DGGML_F16C=off") + $script:cmakeDefs $script:buildDir="../build/windows/${script:ARCH}/cpu" $script:distDir="$script:DIST_BASE\cpu" write-host "Building LCD CPU" @@ -207,6 +219,32 @@ function build_cpu($gen_arch) { } } +function build_cpu_arm64 { + if ((-not "${env:OLLAMA_SKIP_CPU_GENERATE}" ) -and ((-not "${env:OLLAMA_CPU_TARGET}") -or ("${env:OLLAMA_CPU_TARGET}" -eq "cpu"))) { + init_vars + write-host "Checking for clang..." + get-command clang + $env:CFLAGS="-march=armv8.7-a -fvectorize -ffp-model=fast -fno-finite-math-only" + $env:CXXFLAGS="$env:CFLAGS" + $env:LDFLAGS="-static-libstdc++" + $script:cmakeDefs = $script:commonCpuDefs + @( + "-DCMAKE_VERBOSE_MAKEFILE=on", + "-DCMAKE_C_COMPILER=clang.exe", + "-DCMAKE_CXX_COMPILER=clang++.exe", + "-DMSVC_RUNTIME_LIBRARY=MultiThreaded" + ) + $script:cmakeDefs + $script:buildDir="../build/windows/${script:ARCH}/cpu" + $script:distDir="$script:DIST_BASE\cpu" + write-host "Building LCD CPU" + build + sign + install + } else { + write-host "Skipping CPU generation step as requested" + } +} + + function build_cpu_avx() { if ((-not "${env:OLLAMA_SKIP_CPU_GENERATE}" ) -and ((-not "${env:OLLAMA_CPU_TARGET}") -or ("${env:OLLAMA_CPU_TARGET}" -eq "cpu_avx"))) { init_vars @@ -331,7 +369,7 @@ function build_rocm() { $script:buildDir="../build/windows/${script:ARCH}/rocm$script:ROCM_VARIANT" $script:distDir="$script:DIST_BASE\rocm$script:ROCM_VARIANT" $script:cmakeDefs += @( - "-G", "Ninja", + "-G", "Ninja", "-DCMAKE_C_COMPILER=clang.exe", "-DCMAKE_CXX_COMPILER=clang++.exe", "-DGGML_HIPBLAS=on", @@ -380,9 +418,9 @@ if ($($args.count) -eq 0) { apply_patches build_static if ($script:ARCH -eq "arm64") { - build_cpu("ARM64") + build_cpu_arm64 } else { # amd64 - build_cpu("x64") + build_cpu_x64 build_cpu_avx build_cpu_avx2 build_cuda @@ -396,5 +434,5 @@ if ($($args.count) -eq 0) { for ( $i = 0; $i -lt $args.count; $i++ ) { write-host "performing $($args[$i])" & $($args[$i]) - } + } } \ No newline at end of file diff --git a/llm/llm.go b/llm/llm.go index 6bb6591d8..6c6958894 100644 --- a/llm/llm.go +++ b/llm/llm.go @@ -5,7 +5,7 @@ package llm // #cgo darwin,arm64 LDFLAGS: -L${SRCDIR}/build/darwin/arm64_static -L${SRCDIR}/build/darwin/arm64_static/src -L${SRCDIR}/build/darwin/arm64_static/ggml/src -framework Accelerate -framework Metal // #cgo darwin,amd64 LDFLAGS: -L${SRCDIR}/build/darwin/x86_64_static -L${SRCDIR}/build/darwin/x86_64_static/src -L${SRCDIR}/build/darwin/x86_64_static/ggml/src // #cgo windows,amd64 LDFLAGS: -static-libstdc++ -static-libgcc -static -L${SRCDIR}/build/windows/amd64_static -L${SRCDIR}/build/windows/amd64_static/src -L${SRCDIR}/build/windows/amd64_static/ggml/src -// #cgo windows,arm64 LDFLAGS: -static-libstdc++ -static-libgcc -static -L${SRCDIR}/build/windows/arm64_static -L${SRCDIR}/build/windows/arm64_static/src -L${SRCDIR}/build/windows/arm64_static/ggml/src +// #cgo windows,arm64 LDFLAGS: -lllama -lggml -static-libstdc++ -static-libgcc -static -L${SRCDIR}/build/windows/arm64_static -L${SRCDIR}/build/windows/arm64_static/src -L${SRCDIR}/build/windows/arm64_static/ggml/src // #cgo linux,amd64 LDFLAGS: -L${SRCDIR}/build/linux/x86_64_static -L${SRCDIR}/build/linux/x86_64_static/src -L${SRCDIR}/build/linux/x86_64_static/ggml/src // #cgo linux,arm64 LDFLAGS: -L${SRCDIR}/build/linux/arm64_static -L${SRCDIR}/build/linux/arm64_static/src -L${SRCDIR}/build/linux/arm64_static/ggml/src // #include diff --git a/scripts/build_windows.ps1 b/scripts/build_windows.ps1 index eb8570c8f..ff74a5003 100644 --- a/scripts/build_windows.ps1 +++ b/scripts/build_windows.ps1 @@ -7,12 +7,12 @@ $ErrorActionPreference = "Stop" function checkEnv() { - $script:ARCH = $Env:PROCESSOR_ARCHITECTURE.ToLower() - $script:TARGET_ARCH=$Env:PROCESSOR_ARCHITECTURE.ToLower() + $script:ARCH = (([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture).ToString().ToLower()).Replace("x64", "amd64") + $script:TARGET_ARCH=$script:ARCH Write-host "Building for ${script:TARGET_ARCH}" write-host "Locating required tools and paths" $script:SRC_DIR=$PWD - if (!$env:VCToolsRedistDir) { + 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] } @@ -28,9 +28,12 @@ function checkEnv() { $script:CUDA_DIRS=$cudaList } - $script:INNO_SETUP_DIR=(get-item "C:\Program Files*\Inno Setup*\")[0] + $inoSetup=(get-item "C:\Program Files*\Inno Setup*\") + if ($inoSetup.length -gt 0) { + $script:INNO_SETUP_DIR=$inoSetup[0] + } - $script:DEPS_DIR="${script:SRC_DIR}\dist\windows-${script:TARGET_ARCH}" + $script:DIST_DIR="${script:SRC_DIR}\dist\windows-${script:TARGET_ARCH}" $env:CGO_ENABLED="1" Write-Output "Checking version" if (!$env:VERSION) { @@ -130,7 +133,7 @@ function buildApp() { write-host "Building Ollama App" cd "${script:SRC_DIR}\app" & windres -l 0 -o ollama.syso ollama.rc - & 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" . + & 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" . if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} if ("${env:KEY_CONTAINER}") { & "${script:SignTool}" sign /v /fd sha256 /t http://timestamp.digicert.com /f "${script:OLLAMA_CERT}" ` @@ -140,24 +143,40 @@ function buildApp() { } function gatherDependencies() { - write-host "Gathering runtime dependencies" + 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:DEPS_DIR}\lib\ollama" -ea 0 > $null + 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 - cp "${env:VCToolsRedistDir}\x64\Microsoft.VC*.CRT\msvcp140*.dll" "${script:DEPS_DIR}\lib\ollama\" - cp "${env:VCToolsRedistDir}\x64\Microsoft.VC*.CRT\vcruntime140.dll" "${script:DEPS_DIR}\lib\ollama\" - cp "${env:VCToolsRedistDir}\x64\Microsoft.VC*.CRT\vcruntime140_1.dll" "${script:DEPS_DIR}\lib\ollama\" - foreach ($part in $("runtime", "stdio", "filesystem", "math", "convert", "heap", "string", "time", "locale", "environment")) { - cp "$env:VCToolsRedistDir\..\..\..\Tools\Llvm\x64\bin\api-ms-win-crt-${part}*.dll" "${script:DEPS_DIR}\lib\ollama\" + if ($script:TARGET_ARCH -eq "amd64") { + $depArch="x64" + } else { + $depArch=$script:TARGET_ARCH + } + if ($depArch -eq "amd64") { + 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 } cp "${script:SRC_DIR}\app\ollama_welcome.ps1" "${script:SRC_DIR}\dist\" if ("${env:KEY_CONTAINER}") { write-host "about to sign" - foreach ($file in (get-childitem "${script:DEPS_DIR}\lib\ollama\cu*.dll") + @("${script:SRC_DIR}\dist\ollama_welcome.ps1")){ + foreach ($file in (get-childitem "${script:DIST_DIR}\lib\ollama\cu*.dll") + @("${script:SRC_DIR}\dist\ollama_welcome.ps1")){ write-host "signing $file" & "${script:SignTool}" sign /v /fd sha256 /t http://timestamp.digicert.com /f "${script:OLLAMA_CERT}" ` /csp "Google Cloud KMS Provider" /kc ${env:KEY_CONTAINER} $file @@ -167,6 +186,10 @@ function gatherDependencies() { } function buildInstaller() { + if ($null -eq ${script:INNO_SETUP_DIR}) { + write-host "Inno Setup not present, skipping installer build" + return + } write-host "Building Ollama Installer" cd "${script:SRC_DIR}\app" $env:PKG_VERSION=$script:PKG_VERSION @@ -183,13 +206,20 @@ function distZip() { Compress-Archive -Path "${script:SRC_DIR}\dist\windows-${script:TARGET_ARCH}\*" -DestinationPath "${script:SRC_DIR}\dist\ollama-windows-${script:TARGET_ARCH}.zip" -Force } +checkEnv try { - checkEnv - buildOllama - buildApp - gatherDependencies - buildInstaller - distZip + if ($($args.count) -eq 0) { + buildOllama + buildApp + gatherDependencies + buildInstaller + distZip + } else { + for ( $i = 0; $i -lt $args.count; $i++ ) { + write-host "performing $($args[$i])" + & $($args[$i]) + } + } } catch { write-host "Build Failed" write-host $_ diff --git a/server/sched_test.go b/server/sched_test.go index be32065a6..fe5647c52 100644 --- a/server/sched_test.go +++ b/server/sched_test.go @@ -354,7 +354,7 @@ func TestRequestsMultipleLoadedModels(t *testing.T) { } func TestGetRunner(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 100*time.Millisecond) + ctx, done := context.WithTimeout(context.Background(), 200*time.Millisecond) defer done() a := newScenarioRequest(t, ctx, "ollama-model-1a", 10, &api.Duration{Duration: 2 * time.Millisecond}) @@ -395,7 +395,7 @@ func TestGetRunner(t *testing.T) { slog.Info("c") successCh1c, errCh1c := s.GetRunner(c.ctx, c.req.model, c.req.opts, c.req.sessionDuration) // Starts in pending channel, then should be quickly processsed to return an error - time.Sleep(20 * time.Millisecond) // Long enough for the "a" model to expire and unload + time.Sleep(50 * time.Millisecond) // Long enough for the "a" model to expire and unload require.Empty(t, successCh1c) s.loadedMu.Lock() require.Empty(t, s.loaded)