diff --git a/coin/provisioning/common/windows/zlib-helpers.ps1 b/coin/provisioning/common/windows/zlib-helpers.ps1 new file mode 100644 index 00000000..ea3a9ba6 --- /dev/null +++ b/coin/provisioning/common/windows/zlib-helpers.ps1 @@ -0,0 +1,80 @@ +# Copyright (C) 2025 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +. "$PSScriptRoot\helpers.ps1" + +function CpuArchToString { + param ( + [Parameter(Mandatory)] + [CpuArch] $Architecture + ) + + $arhitecture = switch ($Architecture) { + ([CpuArch]::arm64) { + 'arm64' + } + ([CpuArch]::x64) { + 'amd64' + } + default { + throw "Unsupported architecture: '$Architecture'" + } + } + + return $arhitecture +} + +function StringToCpuArch { + param ( + [Parameter(Mandatory)] + [string] $Architecture + ) + + $arhitecture = switch ($Architecture) { + 'arm64' { + [CpuArch]::arm64 + } + 'amd64' { + [CpuArch]::x64 + } + default { + throw "Unsupported architecture: '$Architecture'" + } + } + + return $arhitecture +} + +function GetZlibEnvironmentVariableName { + param ( + [Parameter(Mandatory)] + [CpuArch] $TargetArchitecture + ) + + $architecture = CpuArchToString -Architecture $TargetArchitecture + $environmentVariableName = "ZLIB_PATH_$architecture".ToUpper() + + return $environmentVariableName +} + +function GetZlibPathByCpuArch { + param ( + [Parameter(Mandatory)] + [CpuArch] $TargetArchitecture + ) + + $environmentVariableName = GetZlibEnvironmentVariableName -TargetArchitecture $TargetArchitecture + + return [System.Environment]::GetEnvironmentVariable($environmentVariableName, [System.EnvironmentVariableTarget]::Machine) +} + +function GetZlibPathByString { + param ( + [Parameter(Mandatory)] + [string] $TargetArchitecture + ) + + $targetArchitecture = StringToCpuArch -Architecture $TargetArchitecture + + return GetZlibPathByCpuArch -TargetArchitecture $targetArchitecture +} diff --git a/coin/provisioning/common/windows/zlib.ps1 b/coin/provisioning/common/windows/zlib.ps1 new file mode 100644 index 00000000..f725f8f6 --- /dev/null +++ b/coin/provisioning/common/windows/zlib.ps1 @@ -0,0 +1,204 @@ +# Copyright (C) 2025 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +# This script performs manual copying and patching of the zlib source to support +# multi-architecture builds on Windows using Microsoft's nmake and Makefile.msc. +# +# Reasons for this approach: +# +# 1. In-source build system: +# zlib's build system (Makefile.msc) writes all build artifacts directly into the source +# directory. To allow concurrent builds for different architectures (e.g., x64 and arm64), +# we copy the relevant source files into per-architecture build directories to isolate artifacts. +# +# 2. Incompatible linker base address: +# The default Makefile.msc contains a hardcoded image base address ('-base:0x5A4C0000') for the +# linker. This is invalid for ARM64 targets, which require base addresses above 4 GB. The script +# patches this line out to prevent linker errors. +# +# 3. Broken #include in zconf.h: +# Based on FFmpeg documentation (https://ffmpeg.org/platform.html#Microsoft-Visual-C_002b_002b-or-Intel-C_002b_002b-Compiler-for-Windows), +# zconf.h may erroneously include '', which doesn't exist on Windows. While Visual Studio 2022 +# builds tolerate this, we patch it out to ensure compatibility with older toolchains. +# +# These workarounds allow us to run reproducible, architecture-specific builds in CI without modifying +# the original source tree or requiring upstream changes. + +. "$PSScriptRoot\helpers.ps1" +. "$PSScriptRoot\zlib-helpers.ps1" + +$VERSION='1.3.1' +$SHA1='f535367b1a11e2f9ac3bec723fb007fbc0d189e5' + +$WIN32_DIRECTORY='win32' +$MAKEFILE="$WIN32_DIRECTORY\Makefile.msc" + +function BuildZlib { + param ( + [Parameter(Mandatory)] + [CpuArch] $HostArchitecture, + [Parameter(Mandatory)] + [CpuArch] $TargetArchitecture + ) + + PrepareBuildEnvironment -HostArchitecture $HostArchitecture -TargetArchitecture $TargetArchitecture + + nmake /f $MAKEFILE +} + +function CopySource { + param ( + [Parameter(Mandatory)] + [CpuArch] $TargetArchitecture + ) + + $testDirectory='test' + + $buildDirectory = GetBuildDirectory -TargetArchitecture $TargetArchitecture + $win32BuildDirectory = "$buildDirectory\$WIN32_DIRECTORY" + $testBuildDirectory = "$buildDirectory\$testDirectory" + + New-Item -Path $buildDirectory -ItemType 'Directory' + New-Item -Path $win32BuildDirectory -ItemType 'Directory' + New-Item -Path $testBuildDirectory -ItemType 'Directory' + + Copy-Item '*' -Include '*.c','*.h' -Destination $buildDirectory + Copy-Item "$WIN32_DIRECTORY\*" -Include '*.def','*.msc','*.rc' -Destination $win32BuildDirectory + Copy-Item "$testDirectory\*" -Include '*.c' -Destination $testBuildDirectory +} + +function GetBuildDirectory { + param ( + [Parameter(Mandatory)] + [CpuArch] $TargetArchitecture + ) + + $architectureDirectory = CpuArchToString -Architecture $TargetArchitecture + + return "build\$architectureDirectory" +} + +function GetSource { + $unzipDirectory = "C:\" + $zlibName="zlib-$VERSION" + + $zlibDirectory = "$unzipDirectory$zlibName" + + $urlCached="http://ci-files01-hki.ci.qt.io/input/zlib/zlib-$VERSION.tar.gz" + $urlPublic="https://github.com/madler/zlib/releases/download/v$VERSION/zlib-$VERSION.tar.gz" + + $downloadPath = "C:\Windows\Temp\$zlibName.tar.gz" + + Write-Host "Fetching zlib $VERSION..." + + Download $urlPublic $urlCached $downloadPath + Verify-Checksum $downloadPath $SHA1 + Extract-tar_gz $downloadPath $unzipDirectory + Remove $downloadPath + + return $zlibDirectory +} + +function GetTargetArchitectures { + param ( + [Parameter(Mandatory)] + [CpuArch] $HostArchitecture + ) + + $targetArhitectures = @([CpuArch]::arm64) + + if ($HostArchitecture -eq [CpuArch]::x64) { + $targetArhitectures += [CpuArch]::x64 + } + + return $targetArhitectures +} + +function PatchMakefile { + $pattern = '-base:\s*0x[0-9A-Fa-f]+' + + (Get-Content $MAKEFILE) | ForEach-Object { + $_ -replace $pattern, '' + } | Set-Content $MAKEFILE +} + +function PatchSource { + PatchZconf + PatchMakefile +} + +function PatchZconf { + $zconf = 'zconf.h' + $pattern = '#\s*include\s*' + + (Get-Content $zconf) | Where-Object { + $_ -notmatch $pattern + } | Set-Content $zconf +} + +function PrepareBuild { + param ( + [Parameter(Mandatory)] + [CpuArch] $TargetArchitecture + ) + + CopySource -TargetArchitecture $TargetArchitecture +} + +function PrepareBuildEnvironment { + param ( + [Parameter(Mandatory)] + [CpuArch] $HostArchitecture, + [Parameter(Mandatory)] + [CpuArch] $TargetArchitecture + ) + + $hostArhitecture = CpuArchToString -Architecture $HostArchitecture + $targetArhitecture = CpuArchToString -Architecture $TargetArchitecture + + if (-not $(EnterVSDevShell -HostArch $hostArhitecture -Arch $targetArhitecture)) { + throw "Failed to prepare build environment for ${hostArhitecture}_${targetArhitecture}" + } +} + +function SetZlibEnvironmentVariable { + param ( + [Parameter(Mandatory)] + [CpuArch] $TargetArchitecture, + [Parameter(Mandatory)] + [string] $ZlibDirectory + ) + + $buildDirectory = GetBuildDirectory -TargetArchitecture $TargetArchitecture + $environmentVariableName = GetZlibEnvironmentVariableName -TargetArchitecture $TargetArchitecture + $environmentVariableValue = "$ZlibDirectory\$buildDirectory" + + Set-EnvironmentVariable $environmentVariableName $environmentVariableValue +} + +$zlibDirectory = GetSource +$hostArchitecture = Get-CpuArchitecture +$targetArchitectures = GetTargetArchitectures -HostArchitecture $hostArchitecture + +Push-Location $zlibDirectory + +try { + foreach ($targetArchitecture in $targetArchitectures) { + PrepareBuild -TargetArchitecture $targetArchitecture + + $buildDirectory = GetBuildDirectory -TargetArchitecture $targetArchitecture + Push-Location $buildDirectory + + try { + PatchSource + BuildZlib -HostArchitecture $hostArchitecture -TargetArchitecture $targetArchitecture + SetZlibEnvironmentVariable -TargetArchitecture $targetArchitecture -ZlibDirectory $zlibDirectory + } + finally { + Pop-Location + } + } +} +finally { + Pop-Location +} diff --git a/coin/provisioning/qtci-windows-10-x86_64/89-zlib.ps1 b/coin/provisioning/qtci-windows-10-x86_64/89-zlib.ps1 new file mode 100644 index 00000000..90751c34 --- /dev/null +++ b/coin/provisioning/qtci-windows-10-x86_64/89-zlib.ps1 @@ -0,0 +1 @@ +. "$PSScriptRoot\..\common\windows\zlib.ps1" diff --git a/coin/provisioning/qtci-windows-10_21H2-x86_64/89-zlib.ps1 b/coin/provisioning/qtci-windows-10_21H2-x86_64/89-zlib.ps1 new file mode 100644 index 00000000..90751c34 --- /dev/null +++ b/coin/provisioning/qtci-windows-10_21H2-x86_64/89-zlib.ps1 @@ -0,0 +1 @@ +. "$PSScriptRoot\..\common\windows\zlib.ps1" diff --git a/coin/provisioning/qtci-windows-10_22H2-x86_64/89-zlib.ps1 b/coin/provisioning/qtci-windows-10_22H2-x86_64/89-zlib.ps1 new file mode 100644 index 00000000..90751c34 --- /dev/null +++ b/coin/provisioning/qtci-windows-10_22H2-x86_64/89-zlib.ps1 @@ -0,0 +1 @@ +. "$PSScriptRoot\..\common\windows\zlib.ps1" diff --git a/coin/provisioning/qtci-windows-11_21H2-x86_64/89-zlib.ps1 b/coin/provisioning/qtci-windows-11_21H2-x86_64/89-zlib.ps1 new file mode 100644 index 00000000..90751c34 --- /dev/null +++ b/coin/provisioning/qtci-windows-11_21H2-x86_64/89-zlib.ps1 @@ -0,0 +1 @@ +. "$PSScriptRoot\..\common\windows\zlib.ps1" diff --git a/coin/provisioning/qtci-windows-11_22H2-aarch64/89-zlib.ps1 b/coin/provisioning/qtci-windows-11_22H2-aarch64/89-zlib.ps1 new file mode 100644 index 00000000..90751c34 --- /dev/null +++ b/coin/provisioning/qtci-windows-11_22H2-aarch64/89-zlib.ps1 @@ -0,0 +1 @@ +. "$PSScriptRoot\..\common\windows\zlib.ps1" diff --git a/coin/provisioning/qtci-windows-11_22H2-x86_64/89-zlib.ps1 b/coin/provisioning/qtci-windows-11_22H2-x86_64/89-zlib.ps1 new file mode 100644 index 00000000..90751c34 --- /dev/null +++ b/coin/provisioning/qtci-windows-11_22H2-x86_64/89-zlib.ps1 @@ -0,0 +1 @@ +. "$PSScriptRoot\..\common\windows\zlib.ps1" diff --git a/coin/provisioning/qtci-windows-11_23H2-aarch64/89-zlib.ps1 b/coin/provisioning/qtci-windows-11_23H2-aarch64/89-zlib.ps1 new file mode 100644 index 00000000..90751c34 --- /dev/null +++ b/coin/provisioning/qtci-windows-11_23H2-aarch64/89-zlib.ps1 @@ -0,0 +1 @@ +. "$PSScriptRoot\..\common\windows\zlib.ps1" diff --git a/coin/provisioning/qtci-windows-11_23H2-x86_64/89-zlib.ps1 b/coin/provisioning/qtci-windows-11_23H2-x86_64/89-zlib.ps1 new file mode 100644 index 00000000..90751c34 --- /dev/null +++ b/coin/provisioning/qtci-windows-11_23H2-x86_64/89-zlib.ps1 @@ -0,0 +1 @@ +. "$PSScriptRoot\..\common\windows\zlib.ps1" diff --git a/coin/provisioning/qtci-windows-11_24H2-x86_64/89-zlib.ps1 b/coin/provisioning/qtci-windows-11_24H2-x86_64/89-zlib.ps1 new file mode 100644 index 00000000..90751c34 --- /dev/null +++ b/coin/provisioning/qtci-windows-11_24H2-x86_64/89-zlib.ps1 @@ -0,0 +1 @@ +. "$PSScriptRoot\..\common\windows\zlib.ps1"