msquic/scripts/build.ps1

598 строки
18 KiB
PowerShell

<#
.SYNOPSIS
This script provides helpers for building msquic.
.PARAMETER Config
The debug or release configuration to build for.
.PARAMETER Arch
The CPU architecture to build for.
.PARAMETER Platform
Specify which platform to build for.
.PARAMETER Static
Specify a static library is preferred (shared is the default).
.PARAMETER Tls
The TLS library to use.
.PARAMETER DisableLogs
Disables log collection.
.PARAMETER LoggingType
Set logging type
.PARAMETER SanitizeAddress
Enables address sanitizer.
.PARAMETER CodeCheck
Enables static code checkers.
.PARAMETER DisableTools
Don't build the tools directory.
.PARAMETER DisableTest
Don't build the test directory.
.PARAMETER DisablePerf
Don't build the perf directory.
.PARAMETER Clean
Deletes all previous build and configuration.
.PARAMETER InstallOutput
Installs the build output to the current machine.
.PARAMETER Parallel
Enables CMake to build in parallel, where possible.
.PARAMETER DynamicCRT
Builds msquic with dynamic C runtime (Windows-only).
.PARAMETER StaticCRT
Builds msquic with static C runtime (Windows-only).
.PARAMETER PGO
Builds msquic with profile guided optimization support (Windows-only).
.PARAMETER Generator
Specifies a specific cmake generator (Only supported on unix)
.PARAMETER SkipPdbAltPath
Skip setting PDBALTPATH into built binaries on Windows. Without this flag, the PDB must be in the same directory as the DLL or EXE.
.PARAMETER SkipSourceLink
Skip generating sourcelink and inserting it into the PDB.
.PARAMETER Clang
Build with Clang if available
.PARAMETER UpdateClog
Build allowing clog to update the sidecar.
.PARAMETER ConfigureOnly
Run configuration only.
.PARAMETER CI
Build is occuring from CI
.PARAMETER OfficialRelease
Build is for an official (tag) release.
.PARAMETER EnableTelemetryAsserts
Enables telemetry asserts in release builds.
.PARAMETER UseSystemOpenSSLCrypto
Use system provided OpenSSL libcrypto rather then statically linked. Only affects OpenSSL Linux builds
.PARAMETER EnableHighResolutionTimers
Configures the system to use high resolution timers.
.PARAMETER UseXdp
Use XDP for the datapath instead of system socket APIs.
.PARAMETER ExtraArtifactDir
Add an extra classifier to the artifact directory to allow publishing alternate builds of same base library
.PARAMETER LibraryName
Renames the library to whatever is passed in
.PARAMETER SysRoot
Directory with cross-compilation tools
.PARAMETER OneBranch
Build is occuring from Onebranch pipeline.
.EXAMPLE
build.ps1
.EXAMPLE
build.ps1 -Config Release
#>
param (
[Parameter(Mandatory = $false)]
[ValidateSet("Debug", "Release")]
[string]$Config = "Debug",
[Parameter(Mandatory = $false)]
[ValidateSet("x86", "x64", "arm", "arm64", "arm64ec")]
[string]$Arch = "",
[Parameter(Mandatory = $false)]
[ValidateSet("gamecore_console", "uwp", "windows", "linux", "macos", "android", "ios")] # For future expansion
[string]$Platform = "",
[Parameter(Mandatory = $false)]
[switch]$Static = $false,
[Parameter(Mandatory = $false)]
[ValidateSet("schannel", "openssl", "openssl3")]
[string]$Tls = "",
[Parameter(Mandatory = $false)]
[switch]$DisableLogs = $false,
[Parameter(Mandatory = $false)]
[string]$LoggingType = "",
[Parameter(Mandatory = $false)]
[switch]$SanitizeAddress = $false,
[Parameter(Mandatory = $false)]
[switch]$CodeCheck = $false,
[Parameter(Mandatory = $false)]
[switch]$DisableTools = $false,
[Parameter(Mandatory = $false)]
[switch]$DisableTest = $false,
[Parameter(Mandatory = $false)]
[switch]$DisablePerf = $false,
[Parameter(Mandatory = $false)]
[switch]$Clean = $false,
[Parameter(Mandatory = $false)]
[int32]$Parallel = -2,
[Parameter(Mandatory = $false)]
[switch]$DynamicCRT = $false,
[Parameter(Mandatory = $false)]
[switch]$StaticCRT = $false,
[Parameter(Mandatory = $false)]
[switch]$PGO = $false,
[Parameter(Mandatory = $false)]
[string]$Generator = "",
[Parameter(Mandatory = $false)]
[switch]$SkipPdbAltPath = $false,
[Parameter(Mandatory = $false)]
[switch]$SkipSourceLink = $false,
[Parameter(Mandatory = $false)]
[switch]$Clang = $false,
[Parameter(Mandatory = $false)]
[switch]$UpdateClog = $false,
[Parameter(Mandatory = $false)]
[switch]$ConfigureOnly = $false,
[Parameter(Mandatory = $false)]
[switch]$CI = $false,
[Parameter(Mandatory = $false)]
[switch]$OfficialRelease = $false,
[Parameter(Mandatory = $false)]
[switch]$EnableTelemetryAsserts = $true,
[Parameter(Mandatory = $false)]
[switch]$UseSystemOpenSSLCrypto = $false,
[Parameter(Mandatory = $false)]
[switch]$EnableHighResolutionTimers = $false,
[Parameter(Mandatory = $false)]
[switch]$UseXdp = $false,
[Parameter(Mandatory = $false)]
[string]$ExtraArtifactDir = "",
[Parameter(Mandatory = $false)]
[string]$LibraryName = "msquic",
[Parameter(Mandatory = $false)]
[string]$SysRoot = "/",
[Parameter(Mandatory = $false)]
[switch]$OneBranch = $false,
[Parameter(Mandatory = $false)]
[string]$ToolchainFile = ""
)
Set-StrictMode -Version 'Latest'
$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
if ($Parallel -lt -1) {
if ($IsWindows) {
$Parallel = -1
} else {
$Parallel = 0
}
}
$BuildConfig = & (Join-Path $PSScriptRoot get-buildconfig.ps1) -Platform $Platform -Tls $Tls -Arch $Arch -ExtraArtifactDir $ExtraArtifactDir -Config $Config
$Platform = $BuildConfig.Platform
$Tls = $BuildConfig.Tls
$Arch = $BuildConfig.Arch
$ArtifactsDir = $BuildConfig.ArtifactsDir
if ($Generator -eq "") {
if (!$IsWindows) {
$Generator = "Unix Makefiles"
}
}
if (!$IsWindows -And $Platform -eq "uwp") {
Write-Error "[$(Get-Date)] Cannot build uwp on non windows platforms"
exit
}
if (!$IsWindows -And ($Platform -eq "gamecore_console")) {
Write-Error "[$(Get-Date)] Cannot build gamecore on non windows platforms"
exit
}
if ($Arch -ne "x64" -And ($Platform -eq "gamecore_console")) {
Write-Error "[$(Get-Date)] Cannot build gamecore for non-x64 platforms"
exit
}
if ($Arch -eq "arm64ec") {
if (!$IsWindows) {
Write-Error "Arm64EC is only supported on Windows"
}
if ($Tls -eq "openssl" -Or $Tls -eq "openssl3") {
Write-Error "Arm64EC does not support openssl"
}
}
if ($Platform -eq "ios" -and !$Static) {
$Static = $true
Write-Host "iOS can only be built as static"
}
if ($OfficialRelease) {
# We only actually try to do official release if there is a matching git tag.
# Clear the flag and then only set it if we find a tag.
$OfficialRelease = $false
try {
$env:GIT_REDIRECT_STDERR = '2>&1'
# Thanks to https://stackoverflow.com/questions/3404936/show-which-git-tag-you-are-on
# for this magic git command!
$Output = git describe --exact-match --tags $(git log -n1 --pretty='%h')
if (!$Output.Contains("fatal: no tag exactly matches")) {
Write-Host "Configuring OfficialRelease for tag build"
$OfficialRelease = $true
}
} catch { }
$global:LASTEXITCODE = 0
}
# Root directory of the project.
$RootDir = Split-Path $PSScriptRoot -Parent
# Important directory paths.
$BaseArtifactsDir = Join-Path $RootDir "artifacts"
$BaseBuildDir = Join-Path $RootDir "build"
$BuildDir = Join-Path $BaseBuildDir $Platform
$BuildDir = Join-Path $BuildDir "$($Arch)_$($Tls)"
if ($Clean) {
# Delete old build/config directories.
if (Test-Path $ArtifactsDir) { Remove-Item $ArtifactsDir -Recurse -Force | Out-Null }
if (Test-Path $BuildDir) { Remove-Item $BuildDir -Recurse -Force | Out-Null }
}
# Initialize directories needed for building.
if (!(Test-Path $BaseArtifactsDir)) {
New-Item -Path $BaseArtifactsDir -ItemType Directory -Force | Out-Null
}
if (!(Test-Path $BuildDir)) { New-Item -Path $BuildDir -ItemType Directory -Force | Out-Null }
if ($Clang) {
if ($IsWindows) {
Write-Error "Clang is not supported on windows currently"
}
$env:CC = 'clang'
$env:CXX = 'clang++'
}
# Workaround for perl openssl build warnings.
$env:TERM='ansi'
function Log($msg) {
Write-Host "[$(Get-Date)] $msg"
}
# Executes cmake with the given arguments.
function CMake-Execute([String]$Arguments) {
Log "cmake $($Arguments)"
$process = Start-Process cmake $Arguments -PassThru -NoNewWindow -WorkingDirectory $BuildDir
$handle = $process.Handle # Magic work around. Don't remove this line.
$process.WaitForExit();
if ($process.ExitCode -ne 0) {
Write-Error "[$(Get-Date)] CMake exited with status code $($process.ExitCode)"
}
}
# Uses cmake to generate the build configuration files.
function CMake-Generate {
$Arguments = ""
if ($Generator.Contains(" ")) {
$Generator = """$Generator"""
}
if ($IsWindows) {
if ($Generator.Contains("Visual Studio") -or [string]::IsNullOrWhiteSpace($Generator)) {
if ($Generator.Contains("Visual Studio")) {
$Arguments += " -G $Generator"
}
$Arguments += " -A "
switch ($Arch) {
"x86" { $Arguments += "Win32" }
"x64" { $Arguments += "x64" }
"arm" { $Arguments += "arm" }
"arm64" { $Arguments += "arm64" }
"arm64ec" { $Arguments += "arm64ec" }
}
} else {
Write-Host "Non VS based generators must be run from a Visual Studio Developer Powershell Prompt matching the passed in architecture"
$Arguments += " -G $Generator"
}
} else {
$Arguments += "-G $Generator"
}
if ($Platform -eq "ios") {
$IosTCFile = Join-Path $RootDir cmake toolchains ios.cmake
$Arguments += " -DCMAKE_TOOLCHAIN_FILE=""$IosTCFile"" -DDEPLOYMENT_TARGET=""13.0"" -DENABLE_ARC=0 -DCMAKE_OSX_DEPLOYMENT_TARGET=""13.0"""
switch ($Arch) {
"x64" { $Arguments += " -DPLATFORM=SIMULATOR64"}
"arm64" { $Arguments += " -DPLATFORM=OS64"}
}
}
if ($Platform -eq "macos") {
switch ($Arch) {
"x64" { $Arguments += " -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_DEPLOYMENT_TARGET=""12"""}
"arm64" { $Arguments += " -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_DEPLOYMENT_TARGET=""11.0"""}
}
}
if ($Platform -eq "linux") {
$Arguments += " $Generator"
$HostArch = "$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture)".ToLower()
if ($HostArch -ne $Arch) {
if ($OneBranch) {
$Arguments += " -DONEBRANCH=1"
if ($ToolchainFile -eq "") {
switch ($Arch) {
"arm" { $ToolchainFile = "cmake/toolchains/arm-linux.cmake" }
"arm64" { $ToolchainFile = "cmake/toolchains/aarch64-linux.cmake" }
}
}
}
$Arguments += " -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER -DCMAKE_CROSSCOMPILING=1 -DCMAKE_SYSROOT=$SysRoot"
switch ($Arch) {
"arm64" { $Arguments += " -DCMAKE_CXX_COMPILER_TARGET=aarch64-linux-gnu -DCMAKE_C_COMPILER_TARGET=aarch64-linux-gnu -DCMAKE_TARGET_ARCHITECTURE=arm64" }
"arm" { $Arguments += " -DCMAKE_CXX_COMPILER_TARGET=arm-linux-gnueabihf -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DCMAKE_TARGET_ARCHITECTURE=arm" }
}
}
}
if ($ToolchainFile -ne "") {
$Arguments += " -DCMAKE_TOOLCHAIN_FILE=""$ToolchainFile"""
}
if($Static) {
$Arguments += " -DQUIC_BUILD_SHARED=off"
}
$Arguments += " -DQUIC_TLS=" + $Tls
$Arguments += " -DQUIC_OUTPUT_DIR=""$ArtifactsDir"""
if ($IsLinux) {
$Arguments += " -DQUIC_LINUX_LOG_ENCODER=lttng"
}
if (!$DisableLogs) {
$Arguments += " -DQUIC_ENABLE_LOGGING=on"
}
if ($LoggingType -ne "") {
$Arguments += " -DQUIC_ENABLE_LOGGING=on -DQUIC_LOGGING_TYPE=" + $LoggingType
}
if ($SanitizeAddress) {
$Arguments += " -DQUIC_ENABLE_SANITIZERS=on"
}
if ($CodeCheck) {
$Arguments += " -DQUIC_CODE_CHECK=on"
}
if ($Platform -ne "uwp" -and $Platform -ne "gamecore_console") {
if (!$DisableTools) {
$Arguments += " -DQUIC_BUILD_TOOLS=on"
}
if (!$DisableTest) {
$Arguments += " -DQUIC_BUILD_TEST=on"
}
if (!$DisablePerf) {
$Arguments += " -DQUIC_BUILD_PERF=on"
}
}
if (!$IsWindows) {
$ConfigToBuild = $Config;
if ($Config -eq "Release") {
$ConfigToBuild = "RelWithDebInfo"
}
$Arguments += " -DCMAKE_BUILD_TYPE=" + $ConfigToBuild
}
if ($IsWindows) {
if ($DynamicCRT) {
$Arguments += " -DQUIC_STATIC_LINK_CRT=off -DQUIC_STATIC_LINK_PARTIAL_CRT=off"
}
if ($StaticCRT) {
$Arguments += " -DQUIC_STATIC_LINK_CRT=on -DQUIC_STATIC_LINK_PARTIAL_CRT=off"
}
}
if ($PGO) {
$Arguments += " -DQUIC_PGO=on"
}
if ($Platform -eq "uwp") {
$Arguments += " -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0 -DQUIC_UWP_BUILD=on"
}
if ($Platform -eq "gamecore_console") {
$Arguments += " -DCMAKE_SYSTEM_VERSION=10.0 -DQUIC_GAMECORE_BUILD=on"
}
if ($SkipPdbAltPath) {
$Arguments += " -DQUIC_PDBALTPATH=OFF"
}
if ($SkipSourceLink) {
$Arguments += " -DQUIC_SOURCE_LINK=OFF"
}
if ($CI) {
$Arguments += " -DQUIC_CI=ON"
if ($Platform -eq "android" -or $ToolchainFile -ne "") {
$Arguments += " -DQUIC_SKIP_CI_CHECKS=ON"
}
$Arguments += " -DQUIC_VER_BUILD_ID=$env:BUILD_BUILDID"
$Arguments += " -DQUIC_VER_SUFFIX=-official"
}
if ($OfficialRelease) {
$Arguments += " -DQUIC_OFFICIAL_RELEASE=ON"
}
if ($EnableTelemetryAsserts) {
$Arguments += " -DQUIC_TELEMETRY_ASSERTS=on"
}
if ($UseSystemOpenSSLCrypto) {
$Arguments += " -DQUIC_USE_SYSTEM_LIBCRYPTO=on"
}
if ($EnableHighResolutionTimers) {
$Arguments += " -DQUIC_HIGH_RES_TIMERS=on"
}
if ($UseXdp) {
$Arguments += " -DQUIC_USE_XDP=on"
}
if ($Platform -eq "android") {
$env:PATH = "$env:ANDROID_NDK_LATEST_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$env:PATH"
switch ($Arch) {
"x86" { $Arguments += " -DANDROID_ABI=x86"}
"x64" { $Arguments += " -DANDROID_ABI=x86_64" }
"arm" { $Arguments += " -DANDROID_ABI=armeabi-v7a" }
"arm64" { $Arguments += " -DANDROID_ABI=arm64-v8a" }
}
$Arguments += " -DANDROID_PLATFORM=android-29"
$NDK = $env:ANDROID_NDK_LATEST_HOME
$env:ANDROID_NDK_HOME = $env:ANDROID_NDK_LATEST_HOME
$NdkToolchainFile = "$NDK/build/cmake/android.toolchain.cmake"
$Arguments += " -DANDROID_NDK=""$NDK"""
$Arguments += " -DCMAKE_TOOLCHAIN_FILE=""$NdkToolchainFile"""
}
$Arguments += " -DQUIC_LIBRARY_NAME=$LibraryName"
$Arguments += " ../../.."
Write-Host "Executing: $Arguments"
CMake-Execute $Arguments
}
# Uses cmake to generate the build configuration files.
function CMake-Build {
$Arguments = "--build ."
if ($Parallel -gt 0) {
$Arguments += " --parallel $($Parallel)"
} elseif ($Parallel -eq 0) {
$Arguments += " --parallel"
}
if ($IsWindows) {
$Arguments += " --config " + $Config
} else {
$Arguments += " -- VERBOSE=1"
}
Write-Host "Running: $Arguments"
CMake-Execute $Arguments
if ($IsWindows) {
Copy-Item (Join-Path $BuildDir "obj" $Config "$LibraryName.lib") $ArtifactsDir
if ($SanitizeAddress -or ($PGO -and $Config -eq "Release")) {
$CacheFile = Join-Path $BuildDir "CMakeCache.txt"
$LinkerMatches = Select-String -Path $CacheFile -Pattern "CMAKE_LINKER:FILEPATH=(.+)"
if ($LinkerMatches.Matches.Length -eq 1 -and $LinkerMatches.Matches[0].Groups.Count -eq 2) {
$Linker = $LinkerMatches.Matches[0].Groups[1].Value
$VCToolsPath = Split-Path -Path $Linker -Parent
if ($PGO) {
Copy-Item (Join-Path $VCToolsPath "pgort140.dll") $ArtifactsDir
Copy-Item (Join-Path $VCToolsPath "pgodb140.dll") $ArtifactsDir
Copy-Item (Join-Path $VCToolsPath "mspdbcore.dll") $ArtifactsDir
Copy-Item (Join-Path $VCToolsPath "tbbmalloc.dll") $ArtifactsDir
Copy-Item (Join-Path $VCToolsPath "pgomgr.exe") $ArtifactsDir
}
if ($SanitizeAddress) {
Copy-Item (Join-Path $VCToolsPath "clang_rt.asan_dbg_dynamic-x86_64.dll") $ArtifactsDir
Copy-Item (Join-Path $VCToolsPath "clang_rt.asan_dynamic-x86_64.dll") $ArtifactsDir
}
} else {
Log "Failed to find VC Tools path!"
}
}
} elseif ($IsLinux -and $OneBranch) {
# archive the build artifacts for packaging to persist symlinks and permissons.
$ArtifactsParentDir = Split-Path $ArtifactsDir -Parent
$ArtifactsLeafDir = Split-Path $ArtifactsDir -Leaf
tar -cvf "$ArtifactsDir.tar" -C $ArtifactsParentDir "./$ArtifactsLeafDir"
}
# Package debug symbols on macos
if ($Platform -eq "macos") {
$BuiltArtifacts = Get-ChildItem $ArtifactsDir -File
foreach ($Artifact in $BuiltArtifacts) {
if (Test-Path $Artifact) {
dsymutil $Artifact
}
}
}
}
##############################################################
# Main Execution #
##############################################################
if ($UpdateClog) {
$env:CLOG_DEVELOPMENT_MODE=1
}
# Generate the build files.
Log "Generating files..."
CMake-Generate
if (!$ConfigureOnly) {
# Build the code.
Log "Building..."
CMake-Build
}
Log "Done."
if ($UpdateClog) {
$env:CLOG_DEVELOPMENT_MODE=0
}