1*f540a430SEd Maste # Copyright (c) 2021 Yubico AB. All rights reserved. 2*f540a430SEd Maste # Use of this source code is governed by a BSD-style 3*f540a430SEd Maste # license that can be found in the LICENSE file. 4*f540a430SEd Maste 50afa8e06SEd Maste param( 60afa8e06SEd Maste [string]$CMakePath = "C:\Program Files\CMake\bin\cmake.exe", 70afa8e06SEd Maste [string]$GitPath = "C:\Program Files\Git\bin\git.exe", 80afa8e06SEd Maste [string]$SevenZPath = "C:\Program Files\7-Zip\7z.exe", 90afa8e06SEd Maste [string]$GPGPath = "C:\Program Files (x86)\GnuPG\bin\gpg.exe", 100afa8e06SEd Maste [string]$WinSDK = "", 11*f540a430SEd Maste [string]$Config = "Release", 12*f540a430SEd Maste [string]$Arch = "x64", 13*f540a430SEd Maste [string]$Type = "dynamic", 140afa8e06SEd Maste [string]$Fido2Flags = "" 150afa8e06SEd Maste ) 160afa8e06SEd Maste 17*f540a430SEd Maste $ErrorActionPreference = "Stop" 180afa8e06SEd Maste [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 190afa8e06SEd Maste 20*f540a430SEd Maste . "$PSScriptRoot\const.ps1" 210afa8e06SEd Maste 22*f540a430SEd Maste Function ExitOnError() { 23*f540a430SEd Maste if ($LastExitCode -ne 0) { 24*f540a430SEd Maste throw "A command exited with status $LastExitCode" 25*f540a430SEd Maste } 26*f540a430SEd Maste } 270afa8e06SEd Maste 28*f540a430SEd Maste Function GitClone(${REPO}, ${BRANCH}, ${DIR}) { 29*f540a430SEd Maste Write-Host "Cloning ${REPO}..." 30*f540a430SEd Maste & $Git -c advice.detachedHead=false clone --quiet --depth=1 ` 31*f540a430SEd Maste --branch "${BRANCH}" "${REPO}" "${DIR}" 32*f540a430SEd Maste Write-Host "${REPO}'s ${BRANCH} HEAD is:" 33*f540a430SEd Maste & $Git -C "${DIR}" show -s HEAD 340afa8e06SEd Maste } 350afa8e06SEd Maste 360afa8e06SEd Maste # Find Git. 37*f540a430SEd Maste $Git = $(Get-Command git -ErrorAction Ignore | ` 38*f540a430SEd Maste Select-Object -ExpandProperty Source) 390afa8e06SEd Maste if ([string]::IsNullOrEmpty($Git)) { 400afa8e06SEd Maste $Git = $GitPath 410afa8e06SEd Maste } 42*f540a430SEd Maste if (-Not (Test-Path $Git)) { 43*f540a430SEd Maste throw "Unable to find Git at $Git" 44*f540a430SEd Maste } 45*f540a430SEd Maste 46*f540a430SEd Maste # Find CMake. 47*f540a430SEd Maste $CMake = $(Get-Command cmake -ErrorAction Ignore | ` 48*f540a430SEd Maste Select-Object -ExpandProperty Source) 49*f540a430SEd Maste if ([string]::IsNullOrEmpty($CMake)) { 50*f540a430SEd Maste $CMake = $CMakePath 51*f540a430SEd Maste } 52*f540a430SEd Maste if (-Not (Test-Path $CMake)) { 53*f540a430SEd Maste throw "Unable to find CMake at $CMake" 54*f540a430SEd Maste } 550afa8e06SEd Maste 560afa8e06SEd Maste # Find 7z. 57*f540a430SEd Maste $SevenZ = $(Get-Command 7z -ErrorAction Ignore | ` 58*f540a430SEd Maste Select-Object -ExpandProperty Source) 590afa8e06SEd Maste if ([string]::IsNullOrEmpty($SevenZ)) { 600afa8e06SEd Maste $SevenZ = $SevenZPath 610afa8e06SEd Maste } 62*f540a430SEd Maste if (-Not (Test-Path $SevenZ)) { 63*f540a430SEd Maste throw "Unable to find 7z at $SevenZ" 64*f540a430SEd Maste } 650afa8e06SEd Maste 660afa8e06SEd Maste # Find GPG. 67*f540a430SEd Maste $GPG = $(Get-Command gpg -ErrorAction Ignore | ` 68*f540a430SEd Maste Select-Object -ExpandProperty Source) 690afa8e06SEd Maste if ([string]::IsNullOrEmpty($GPG)) { 700afa8e06SEd Maste $GPG = $GPGPath 710afa8e06SEd Maste } 72*f540a430SEd Maste if (-Not (Test-Path $GPG)) { 73*f540a430SEd Maste throw "Unable to find GPG at $GPG" 74*f540a430SEd Maste } 750afa8e06SEd Maste 760afa8e06SEd Maste # Override CMAKE_SYSTEM_VERSION if $WinSDK is set. 770afa8e06SEd Maste if (-Not ([string]::IsNullOrEmpty($WinSDK))) { 780afa8e06SEd Maste $CMAKE_SYSTEM_VERSION = "-DCMAKE_SYSTEM_VERSION='$WinSDK'" 790afa8e06SEd Maste } else { 800afa8e06SEd Maste $CMAKE_SYSTEM_VERSION = '' 810afa8e06SEd Maste } 820afa8e06SEd Maste 83*f540a430SEd Maste Write-Host "WinSDK: $WinSDK" 84*f540a430SEd Maste Write-Host "Config: $Config" 85*f540a430SEd Maste Write-Host "Arch: $Arch" 86*f540a430SEd Maste Write-Host "Type: $Type" 870afa8e06SEd Maste Write-Host "Git: $Git" 880afa8e06SEd Maste Write-Host "CMake: $CMake" 890afa8e06SEd Maste Write-Host "7z: $SevenZ" 900afa8e06SEd Maste Write-Host "GPG: $GPG" 910afa8e06SEd Maste 92*f540a430SEd Maste # Create build directories. 93*f540a430SEd Maste New-Item -Type Directory "${BUILD}" -Force 94*f540a430SEd Maste New-Item -Type Directory "${BUILD}\${Arch}" -Force 95*f540a430SEd Maste New-Item -Type Directory "${BUILD}\${Arch}\${Type}" -Force 96*f540a430SEd Maste New-Item -Type Directory "${STAGE}\${LIBRESSL}" -Force 97*f540a430SEd Maste New-Item -Type Directory "${STAGE}\${LIBCBOR}" -Force 98*f540a430SEd Maste New-Item -Type Directory "${STAGE}\${ZLIB}" -Force 990afa8e06SEd Maste 100*f540a430SEd Maste # Create output directories. 101*f540a430SEd Maste New-Item -Type Directory "${OUTPUT}" -Force 102*f540a430SEd Maste New-Item -Type Directory "${OUTPUT}\${Arch}" -Force 103*f540a430SEd Maste New-Item -Type Directory "${OUTPUT}\${Arch}\${Type}" -force 104*f540a430SEd Maste 105*f540a430SEd Maste # Fetch and verify dependencies. 1060afa8e06SEd Maste Push-Location ${BUILD} 1070afa8e06SEd Maste try { 108*f540a430SEd Maste if (-Not (Test-Path .\${LIBRESSL})) { 1090afa8e06SEd Maste if (-Not (Test-Path .\${LIBRESSL}.tar.gz -PathType leaf)) { 1100afa8e06SEd Maste Invoke-WebRequest ${LIBRESSL_URL}/${LIBRESSL}.tar.gz ` 1110afa8e06SEd Maste -OutFile .\${LIBRESSL}.tar.gz 1120afa8e06SEd Maste } 1130afa8e06SEd Maste if (-Not (Test-Path .\${LIBRESSL}.tar.gz.asc -PathType leaf)) { 1140afa8e06SEd Maste Invoke-WebRequest ${LIBRESSL_URL}/${LIBRESSL}.tar.gz.asc ` 1150afa8e06SEd Maste -OutFile .\${LIBRESSL}.tar.gz.asc 1160afa8e06SEd Maste } 1170afa8e06SEd Maste 1180afa8e06SEd Maste Copy-Item "$PSScriptRoot\libressl.gpg" -Destination "${BUILD}" 1190afa8e06SEd Maste & $GPG --list-keys 120*f540a430SEd Maste & $GPG --quiet --no-default-keyring --keyring ./libressl.gpg ` 1210afa8e06SEd Maste --verify .\${LIBRESSL}.tar.gz.asc .\${LIBRESSL}.tar.gz 1220afa8e06SEd Maste if ($LastExitCode -ne 0) { 1230afa8e06SEd Maste throw "GPG signature verification failed" 1240afa8e06SEd Maste } 1250afa8e06SEd Maste & $SevenZ e .\${LIBRESSL}.tar.gz 1260afa8e06SEd Maste & $SevenZ x .\${LIBRESSL}.tar 1270afa8e06SEd Maste Remove-Item -Force .\${LIBRESSL}.tar 1280afa8e06SEd Maste } 129*f540a430SEd Maste if (-Not (Test-Path .\${LIBCBOR})) { 130*f540a430SEd Maste GitClone "${LIBCBOR_GIT}" "${LIBCBOR_BRANCH}" ".\${LIBCBOR}" 131*f540a430SEd Maste } 1320afa8e06SEd Maste if (-Not (Test-Path .\${ZLIB})) { 133*f540a430SEd Maste GitClone "${ZLIB_GIT}" "${ZLIB_BRANCH}" ".\${ZLIB}" 1340afa8e06SEd Maste } 1350afa8e06SEd Maste } catch { 1360afa8e06SEd Maste throw "Failed to fetch and verify dependencies" 1370afa8e06SEd Maste } finally { 1380afa8e06SEd Maste Pop-Location 1390afa8e06SEd Maste } 1400afa8e06SEd Maste 141*f540a430SEd Maste # Build LibreSSL. 142*f540a430SEd Maste Push-Location ${STAGE}\${LIBRESSL} 143*f540a430SEd Maste try { 144*f540a430SEd Maste & $CMake ..\..\..\${LIBRESSL} -A "${Arch}" ` 1450afa8e06SEd Maste -DBUILD_SHARED_LIBS="${SHARED}" -DLIBRESSL_TESTS=OFF ` 146*f540a430SEd Maste -DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" ` 147*f540a430SEd Maste -DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE}" ` 148*f540a430SEd Maste -DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; ` 149*f540a430SEd Maste ExitOnError 150*f540a430SEd Maste & $CMake --build . --config ${Config} --verbose; ExitOnError 151*f540a430SEd Maste & $CMake --build . --config ${Config} --target install --verbose; ` 152*f540a430SEd Maste ExitOnError 153*f540a430SEd Maste } catch { 154*f540a430SEd Maste throw "Failed to build LibreSSL" 155*f540a430SEd Maste } finally { 1560afa8e06SEd Maste Pop-Location 1570afa8e06SEd Maste } 1580afa8e06SEd Maste 159*f540a430SEd Maste # Build libcbor. 160*f540a430SEd Maste Push-Location ${STAGE}\${LIBCBOR} 161*f540a430SEd Maste try { 162*f540a430SEd Maste & $CMake ..\..\..\${LIBCBOR} -A "${Arch}" ` 163*f540a430SEd Maste -DWITH_EXAMPLES=OFF ` 1640afa8e06SEd Maste -DBUILD_SHARED_LIBS="${SHARED}" ` 165*f540a430SEd Maste -DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" ` 166*f540a430SEd Maste -DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE}" ` 167*f540a430SEd Maste -DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; ` 168*f540a430SEd Maste ExitOnError 169*f540a430SEd Maste & $CMake --build . --config ${Config} --verbose; ExitOnError 170*f540a430SEd Maste & $CMake --build . --config ${Config} --target install --verbose; ` 171*f540a430SEd Maste ExitOnError 172*f540a430SEd Maste } catch { 173*f540a430SEd Maste throw "Failed to build libcbor" 174*f540a430SEd Maste } finally { 1750afa8e06SEd Maste Pop-Location 1760afa8e06SEd Maste } 1770afa8e06SEd Maste 178*f540a430SEd Maste # Build zlib. 179*f540a430SEd Maste Push-Location ${STAGE}\${ZLIB} 180*f540a430SEd Maste try { 181*f540a430SEd Maste & $CMake ..\..\..\${ZLIB} -A "${Arch}" ` 1820afa8e06SEd Maste -DBUILD_SHARED_LIBS="${SHARED}" ` 183*f540a430SEd Maste -DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" ` 184*f540a430SEd Maste -DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE}" ` 185*f540a430SEd Maste -DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; ` 186*f540a430SEd Maste ExitOnError 187*f540a430SEd Maste & $CMake --build . --config ${Config} --verbose; ExitOnError 188*f540a430SEd Maste & $CMake --build . --config ${Config} --target install --verbose; ` 189*f540a430SEd Maste ExitOnError 190*f540a430SEd Maste # Patch up zlib's resulting names when built with --config Debug. 191*f540a430SEd Maste if ("${Config}" -eq "Debug") { 192*f540a430SEd Maste if ("${Type}" -eq "Dynamic") { 193*f540a430SEd Maste Copy-Item "${PREFIX}/lib/zlibd.lib" ` 194*f540a430SEd Maste -Destination "${PREFIX}/lib/zlib.lib" -Force 195*f540a430SEd Maste Copy-Item "${PREFIX}/bin/zlibd1.dll" ` 196*f540a430SEd Maste -Destination "${PREFIX}/bin/zlib1.dll" -Force 197*f540a430SEd Maste } else { 198*f540a430SEd Maste Copy-Item "${PREFIX}/lib/zlibstaticd.lib" ` 199*f540a430SEd Maste -Destination "${PREFIX}/lib/zlib.lib" -Force 200*f540a430SEd Maste } 201*f540a430SEd Maste } 202*f540a430SEd Maste } catch { 203*f540a430SEd Maste throw "Failed to build zlib" 204*f540a430SEd Maste } finally { 2050afa8e06SEd Maste Pop-Location 206*f540a430SEd Maste } 2070afa8e06SEd Maste 208*f540a430SEd Maste # Build libfido2. 209*f540a430SEd Maste Push-Location ${STAGE} 210*f540a430SEd Maste try { 211*f540a430SEd Maste & $CMake ..\..\.. -A "${Arch}" ` 212*f540a430SEd Maste -DCMAKE_BUILD_TYPE="${Config}" ` 2130afa8e06SEd Maste -DBUILD_SHARED_LIBS="${SHARED}" ` 214*f540a430SEd Maste -DCBOR_INCLUDE_DIRS="${PREFIX}\include" ` 215*f540a430SEd Maste -DCBOR_LIBRARY_DIRS="${PREFIX}\lib" ` 216*f540a430SEd Maste -DCBOR_BIN_DIRS="${PREFIX}\bin" ` 217*f540a430SEd Maste -DZLIB_INCLUDE_DIRS="${PREFIX}\include" ` 218*f540a430SEd Maste -DZLIB_LIBRARY_DIRS="${PREFIX}\lib" ` 219*f540a430SEd Maste -DZLIB_BIN_DIRS="${PREFIX}\bin" ` 220*f540a430SEd Maste -DCRYPTO_INCLUDE_DIRS="${PREFIX}\include" ` 221*f540a430SEd Maste -DCRYPTO_LIBRARY_DIRS="${PREFIX}\lib" ` 222*f540a430SEd Maste -DCRYPTO_BIN_DIRS="${PREFIX}\bin" ` 223*f540a430SEd Maste -DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG} ${Fido2Flags}" ` 224*f540a430SEd Maste -DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE} ${Fido2Flags}" ` 225*f540a430SEd Maste -DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; ` 226*f540a430SEd Maste ExitOnError 227*f540a430SEd Maste & $CMake --build . --config ${Config} --verbose; ExitOnError 228*f540a430SEd Maste & $CMake --build . --config ${Config} --target install --verbose; ` 229*f540a430SEd Maste ExitOnError 230*f540a430SEd Maste # Copy DLLs. 2310afa8e06SEd Maste if ("${SHARED}" -eq "ON") { 232*f540a430SEd Maste "cbor.dll", "crypto-46.dll", "zlib1.dll" | ` 233*f540a430SEd Maste %{ Copy-Item "${PREFIX}\bin\$_" ` 234*f540a430SEd Maste -Destination "examples\${Config}" } 2350afa8e06SEd Maste } 236*f540a430SEd Maste } catch { 237*f540a430SEd Maste throw "Failed to build libfido2" 238*f540a430SEd Maste } finally { 2390afa8e06SEd Maste Pop-Location 240*f540a430SEd Maste } 241