1 # Copyright (c) 2021 Yubico AB. All rights reserved.
2 # Use of this source code is governed by a BSD-style
3 # license that can be found in the LICENSE file.
4
5 param(
6 [string]$CMakePath = "C:\Program Files\CMake\bin\cmake.exe",
7 [string]$GitPath = "C:\Program Files\Git\bin\git.exe",
8 [string]$SevenZPath = "C:\Program Files\7-Zip\7z.exe",
9 [string]$GPGPath = "C:\Program Files (x86)\GnuPG\bin\gpg.exe",
10 [string]$WinSDK = "",
11 [string]$Config = "Release",
12 [string]$Arch = "x64",
13 [string]$Type = "dynamic",
14 [string]$Fido2Flags = ""
15 )
16
17 $ErrorActionPreference = "Stop"
18 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
19
20 . "$PSScriptRoot\const.ps1"
21
ExitOnError()22 Function ExitOnError() {
23 if ($LastExitCode -ne 0) {
24 throw "A command exited with status $LastExitCode"
25 }
26 }
27
GitClone(${REPO}, ${BRANCH}, ${DIR})28 Function GitClone(${REPO}, ${BRANCH}, ${DIR}) {
29 Write-Host "Cloning ${REPO}..."
30 & $Git -c advice.detachedHead=false clone --quiet --depth=1 `
31 --branch "${BRANCH}" "${REPO}" "${DIR}"
32 Write-Host "${REPO}'s ${BRANCH} HEAD is:"
33 & $Git -C "${DIR}" show -s HEAD
34 }
35
36 # Find Git.
37 $Git = $(Get-Command git -ErrorAction Ignore | `
38 Select-Object -ExpandProperty Source)
39 if ([string]::IsNullOrEmpty($Git)) {
40 $Git = $GitPath
41 }
42 if (-Not (Test-Path $Git)) {
43 throw "Unable to find Git at $Git"
44 }
45
46 # Find CMake.
47 $CMake = $(Get-Command cmake -ErrorAction Ignore | `
48 Select-Object -ExpandProperty Source)
49 if ([string]::IsNullOrEmpty($CMake)) {
50 $CMake = $CMakePath
51 }
52 if (-Not (Test-Path $CMake)) {
53 throw "Unable to find CMake at $CMake"
54 }
55
56 # Find 7z.
57 $SevenZ = $(Get-Command 7z -ErrorAction Ignore | `
58 Select-Object -ExpandProperty Source)
59 if ([string]::IsNullOrEmpty($SevenZ)) {
60 $SevenZ = $SevenZPath
61 }
62 if (-Not (Test-Path $SevenZ)) {
63 throw "Unable to find 7z at $SevenZ"
64 }
65
66 # Find GPG.
67 $GPG = $(Get-Command gpg -ErrorAction Ignore | `
68 Select-Object -ExpandProperty Source)
69 if ([string]::IsNullOrEmpty($GPG)) {
70 $GPG = $GPGPath
71 }
72 if (-Not (Test-Path $GPG)) {
73 throw "Unable to find GPG at $GPG"
74 }
75
76 # Override CMAKE_SYSTEM_VERSION if $WinSDK is set.
77 if (-Not ([string]::IsNullOrEmpty($WinSDK))) {
78 $CMAKE_SYSTEM_VERSION = "-DCMAKE_SYSTEM_VERSION='$WinSDK'"
79 } else {
80 $CMAKE_SYSTEM_VERSION = ''
81 }
82
83 Write-Host "WinSDK: $WinSDK"
84 Write-Host "Config: $Config"
85 Write-Host "Arch: $Arch"
86 Write-Host "Type: $Type"
87 Write-Host "Git: $Git"
88 Write-Host "CMake: $CMake"
89 Write-Host "7z: $SevenZ"
90 Write-Host "GPG: $GPG"
91
92 # Create build directories.
93 New-Item -Type Directory "${BUILD}" -Force
94 New-Item -Type Directory "${BUILD}\${Arch}" -Force
95 New-Item -Type Directory "${BUILD}\${Arch}\${Type}" -Force
96 New-Item -Type Directory "${STAGE}\${LIBRESSL}" -Force
97 New-Item -Type Directory "${STAGE}\${LIBCBOR}" -Force
98 New-Item -Type Directory "${STAGE}\${ZLIB}" -Force
99
100 # Create output directories.
101 New-Item -Type Directory "${OUTPUT}" -Force
102 New-Item -Type Directory "${OUTPUT}\${Arch}" -Force
103 New-Item -Type Directory "${OUTPUT}\${Arch}\${Type}" -force
104
105 # Fetch and verify dependencies.
106 Push-Location ${BUILD}
107 try {
108 if (-Not (Test-Path .\${LIBRESSL})) {
109 if (-Not (Test-Path .\${LIBRESSL}.tar.gz -PathType leaf)) {
110 Invoke-WebRequest ${LIBRESSL_URL}/${LIBRESSL}.tar.gz `
111 -OutFile .\${LIBRESSL}.tar.gz
112 }
113 if (-Not (Test-Path .\${LIBRESSL}.tar.gz.asc -PathType leaf)) {
114 Invoke-WebRequest ${LIBRESSL_URL}/${LIBRESSL}.tar.gz.asc `
115 -OutFile .\${LIBRESSL}.tar.gz.asc
116 }
117
118 Copy-Item "$PSScriptRoot\libressl.gpg" -Destination "${BUILD}"
119 & $GPG --list-keys
120 & $GPG --quiet --no-default-keyring --keyring ./libressl.gpg `
121 --verify .\${LIBRESSL}.tar.gz.asc .\${LIBRESSL}.tar.gz
122 if ($LastExitCode -ne 0) {
123 throw "GPG signature verification failed"
124 }
125 & $SevenZ e .\${LIBRESSL}.tar.gz
126 & $SevenZ x .\${LIBRESSL}.tar
127 Remove-Item -Force .\${LIBRESSL}.tar
128 }
129 if (-Not (Test-Path .\${LIBCBOR})) {
130 GitClone "${LIBCBOR_GIT}" "${LIBCBOR_BRANCH}" ".\${LIBCBOR}"
131 }
132 if (-Not (Test-Path .\${ZLIB})) {
133 GitClone "${ZLIB_GIT}" "${ZLIB_BRANCH}" ".\${ZLIB}"
134 }
135 } catch {
136 throw "Failed to fetch and verify dependencies"
137 } finally {
138 Pop-Location
139 }
140
141 # Build LibreSSL.
142 Push-Location ${STAGE}\${LIBRESSL}
143 try {
144 & $CMake ..\..\..\${LIBRESSL} -A "${Arch}" `
145 -DBUILD_SHARED_LIBS="${SHARED}" -DLIBRESSL_TESTS=OFF `
146 -DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" `
147 -DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE}" `
148 -DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
149 ExitOnError
150 & $CMake --build . --config ${Config} --verbose; ExitOnError
151 & $CMake --build . --config ${Config} --target install --verbose; `
152 ExitOnError
153 } catch {
154 throw "Failed to build LibreSSL"
155 } finally {
156 Pop-Location
157 }
158
159 # Build libcbor.
160 Push-Location ${STAGE}\${LIBCBOR}
161 try {
162 & $CMake ..\..\..\${LIBCBOR} -A "${Arch}" `
163 -DWITH_EXAMPLES=OFF `
164 -DBUILD_SHARED_LIBS="${SHARED}" `
165 -DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" `
166 -DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE}" `
167 -DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
168 ExitOnError
169 & $CMake --build . --config ${Config} --verbose; ExitOnError
170 & $CMake --build . --config ${Config} --target install --verbose; `
171 ExitOnError
172 } catch {
173 throw "Failed to build libcbor"
174 } finally {
175 Pop-Location
176 }
177
178 # Build zlib.
179 Push-Location ${STAGE}\${ZLIB}
180 try {
181 & $CMake ..\..\..\${ZLIB} -A "${Arch}" `
182 -DBUILD_SHARED_LIBS="${SHARED}" `
183 -DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" `
184 -DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE}" `
185 -DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
186 ExitOnError
187 & $CMake --build . --config ${Config} --verbose; ExitOnError
188 & $CMake --build . --config ${Config} --target install --verbose; `
189 ExitOnError
190 # Patch up zlib's resulting names when built with --config Debug.
191 if ("${Config}" -eq "Debug") {
192 if ("${Type}" -eq "Dynamic") {
193 Copy-Item "${PREFIX}/lib/zlibd.lib" `
194 -Destination "${PREFIX}/lib/zlib.lib" -Force
195 Copy-Item "${PREFIX}/bin/zlibd1.dll" `
196 -Destination "${PREFIX}/bin/zlib1.dll" -Force
197 } else {
198 Copy-Item "${PREFIX}/lib/zlibstaticd.lib" `
199 -Destination "${PREFIX}/lib/zlib.lib" -Force
200 }
201 }
202 } catch {
203 throw "Failed to build zlib"
204 } finally {
205 Pop-Location
206 }
207
208 # Build libfido2.
209 Push-Location ${STAGE}
210 try {
211 & $CMake ..\..\.. -A "${Arch}" `
212 -DCMAKE_BUILD_TYPE="${Config}" `
213 -DBUILD_SHARED_LIBS="${SHARED}" `
214 -DCBOR_INCLUDE_DIRS="${PREFIX}\include" `
215 -DCBOR_LIBRARY_DIRS="${PREFIX}\lib" `
216 -DCBOR_BIN_DIRS="${PREFIX}\bin" `
217 -DZLIB_INCLUDE_DIRS="${PREFIX}\include" `
218 -DZLIB_LIBRARY_DIRS="${PREFIX}\lib" `
219 -DZLIB_BIN_DIRS="${PREFIX}\bin" `
220 -DCRYPTO_INCLUDE_DIRS="${PREFIX}\include" `
221 -DCRYPTO_LIBRARY_DIRS="${PREFIX}\lib" `
222 -DCRYPTO_BIN_DIRS="${PREFIX}\bin" `
223 -DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG} ${Fido2Flags}" `
224 -DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE} ${Fido2Flags}" `
225 -DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
226 ExitOnError
227 & $CMake --build . --config ${Config} --verbose; ExitOnError
228 & $CMake --build . --config ${Config} --target install --verbose; `
229 ExitOnError
230 # Copy DLLs.
231 if ("${SHARED}" -eq "ON") {
232 "cbor.dll", "crypto-46.dll", "zlib1.dll" | `
233 %{ Copy-Item "${PREFIX}\bin\$_" `
234 -Destination "examples\${Config}" }
235 }
236 } catch {
237 throw "Failed to build libfido2"
238 } finally {
239 Pop-Location
240 }
241