Files
eigen/ci/scripts/build.windows.script.ps1

139 lines
6.1 KiB
PowerShell

# Find Visual Studio installation directory. -products * includes Build
# Tools installs, which vswhere's default product filter skips; without it a
# Build Tools-only runner gets an empty path here, vcvarsall never runs, and
# the configure step fails with "No CMAKE_CXX_COMPILER could be found".
# SPDX-FileCopyrightText: The Eigen Authors
# SPDX-License-Identifier: MPL-2.0
$VS_INSTALL_DIR = &"${Env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -property installationPath
# Run VCVarsAll.bat initialization script and extract environment variables.
# http://allen-mack.blogspot.com/2008/03/replace-visual-studio-command-prompt.html
cmd.exe /c "`"${VS_INSTALL_DIR}\VC\Auxiliary\Build\vcvarsall.bat`" $EIGEN_CI_MSVC_ARCH -vcvars_ver=$EIGEN_CI_MSVC_VER & set" |
foreach {
if ($_ -match "^([^=]+)=(.*)$") {
set-item -force -LiteralPath "ENV:\$($Matches[1])" -value "$($Matches[2])"
}
}
# Create and enter build directory.
$rootdir = Get-Location
if (-Not (Test-Path ${EIGEN_CI_BUILDDIR})) {
mkdir $EIGEN_CI_BUILDDIR
}
cd $EIGEN_CI_BUILDDIR
# We need to split EIGEN_CI_ADDITIONAL_ARGS, otherwise they are interpreted
# as a single argument. Split by space, unless double-quoted.
$split_args = [regex]::Split(${EIGEN_CI_ADDITIONAL_ARGS}, ' (?=(?:[^"]|"[^"]*")*$)' )
# Locate ccache when the job enables it (mirrors build.linux.script.sh: the
# GitLab cache holds ${CCACHE_DIR}, keyed on file content and compiler, so it
# hits even after a re-checkout re-stamps every source mtime). Prefer a
# runner-installed ccache, then the copy restored from the .ccache-bin cache;
# otherwise download the release pinned below and cache it for subsequent
# jobs on this runner. Trust is established at every use, not at download
# time: a runner-installed ccache must report at least the version required
# for MSVC support (older ones would break compiles rather than degrade), and
# a restored or freshly extracted binary must match the pinned SHA-256 — the
# GitLab cache is writable job output, so restoring it does not authenticate
# it. Re-verifying per use also means a version bump below invalidates stale
# cached copies by itself. Any failure only means building without ccache,
# never running an unverified binary. Only /Z7 or no debug information is
# cacheable by ccache; these MinSizeRel builds emit none.
$ccache_exe = ""
if ("${EIGEN_CI_CCACHE}" -eq "on") {
$ccache_version = "4.13.6"
$ccache_zip_sha256 = "3d7cebb05850ad704e197b3f1d3f0f924ab6c9fdfc561578e146184fe9d89380"
$ccache_exe_sha256 = "1f285645553e61463b000c6c440301724894b4ba0174dbef6b4818d54b54b68d"
# Caching MSVC needs ccache >= 4.8.
$ccache_min_version = [version]"4.8"
$ccache_bindir = Join-Path ${rootdir} ".ccache-bin"
$cached_exe = Join-Path $ccache_bindir "ccache.exe"
$system_ccache = Get-Command ccache -ErrorAction SilentlyContinue
if ($system_ccache) {
$system_version = ""
try {
$system_version = (& $system_ccache.Source --version | Select-Object -First 1)
} catch {}
if (($system_version -match "ccache version (\d+(\.\d+)+)") -and
([version]$Matches[1] -ge $ccache_min_version)) {
$ccache_exe = $system_ccache.Source
} else {
Write-Warning ("Ignoring system ccache at $($system_ccache.Source) " +
"('${system_version}'; need >= ${ccache_min_version}).")
}
}
if ((-Not $ccache_exe) -and (Test-Path $cached_exe)) {
if ((Get-FileHash $cached_exe -Algorithm SHA256).Hash -eq $ccache_exe_sha256) {
$ccache_exe = $cached_exe
} else {
Write-Warning "Discarding cached ccache.exe that failed SHA-256 verification."
Remove-Item $cached_exe -Force
}
}
if (-Not $ccache_exe) {
$zip = Join-Path ([System.IO.Path]::GetTempPath()) "ccache-${ccache_version}.zip"
try {
$ProgressPreference = "SilentlyContinue"
Invoke-WebRequest "https://github.com/ccache/ccache/releases/download/v${ccache_version}/ccache-${ccache_version}-windows-x86_64.zip" -OutFile $zip
if ((Get-FileHash $zip -Algorithm SHA256).Hash -eq $ccache_zip_sha256) {
$unpack = Join-Path ([System.IO.Path]::GetTempPath()) "ccache-unpack"
Expand-Archive $zip -DestinationPath $unpack -Force
New-Item -ItemType Directory -Force -Path $ccache_bindir | Out-Null
Copy-Item (Join-Path $unpack "ccache-${ccache_version}-windows-x86_64/ccache.exe") $cached_exe
if ((Get-FileHash $cached_exe -Algorithm SHA256).Hash -eq $ccache_exe_sha256) {
$ccache_exe = $cached_exe
} else {
Write-Warning "Extracted ccache.exe failed SHA-256 verification; building without ccache."
Remove-Item $cached_exe -Force
}
} else {
Write-Warning "ccache download failed SHA-256 verification; building without ccache."
}
} catch {
Write-Warning "ccache download failed ($_); building without ccache."
}
}
}
$launchers = @()
if ($ccache_exe) {
# Forward slashes: CMake treats the launcher as a path-valued cache entry.
$ccache_cmake = $ccache_exe -replace '\\', '/'
$launchers = "-DCMAKE_C_COMPILER_LAUNCHER=${ccache_cmake}",
"-DCMAKE_CXX_COMPILER_LAUNCHER=${ccache_cmake}"
& $ccache_exe --zero-stats
}
# Configure build.
cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel `
-DEIGEN_TEST_CUSTOM_CXX_FLAGS="${EIGEN_CI_TEST_CUSTOM_CXX_FLAGS}" `
${launchers} ${split_args} "${rootdir}"
$target = ""
if (${EIGEN_CI_BUILD_TARGET}) {
$target = "--target ${EIGEN_CI_BUILD_TARGET}"
}
# Windows builds sometimes fail due heap errors. In that case, try
# building the rest, then try to build again with a single thread.
cmake --build . ${target} -- -k0 || cmake --build . ${target} -- -k0 -j1
$success = $LASTEXITCODE
# Hit/miss summary for judging what the cache pays for on this job. Runs on
# failures too: the cache is pushed even then (cache:when: always), so the
# stats still describe what the next attempt can reuse.
if ($ccache_exe) {
& $ccache_exe --show-stats
}
# Return to root directory.
cd ${rootdir}
# Explicitly propagate exit code to indicate pass/failure of build command.
if($success -ne 0) { Exit $success }