-
Notifications
You must be signed in to change notification settings - Fork 244
Improvements for the deploy windows script. #3680
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
52d5551
11e27c9
c29ed94
863e748
7159342
77895b3
e1d6d2f
fc1ffbe
281eb3a
a0e2ebd
70bd1ba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,11 @@ param ( | |
| # updates. Verify .github/workflows/bump-dependencies.yaml when changing those manually: | ||
| [string] $AsioSDKUrl = "https://download.steinberg.net/sdk_downloads/ASIO-SDK_2.3.4_2025-10-15.zip", | ||
| [string] $NsisUrl = "https://downloads.sourceforge.net/project/nsis/NSIS%203/3.12/nsis-3.12.zip", | ||
| [string] $BuildOption = "" | ||
| [string] $BuildOption = "", | ||
| # Toggles for debugging and targeted builds | ||
| [switch] $DebugMode, | ||
| [switch] $Skip64Bit, | ||
| [switch] $Skip32Bit | ||
| ) | ||
|
|
||
| # Fail early on all errors | ||
|
|
@@ -33,18 +37,74 @@ $DeployPath = "$RootPath\deploy" | |
| $WindowsPath ="$RootPath\windows" | ||
| $AppName = "Jamulus" | ||
|
|
||
| Function Write-Log { | ||
| param( | ||
| [Parameter(Position=0)] | ||
| [ValidateSet("INFO","WARN","ERROR","STEP","DEBUG","NATIVE","NATIVE-ERR")] | ||
| [string] $Level = "INFO", | ||
|
|
||
| [Parameter(Position=1, Mandatory=$true)] | ||
| [AllowNull()] | ||
| [AllowEmptyString()] | ||
| [string] $Message | ||
| ) | ||
|
|
||
| if ($null -eq $Message) { $Message = "" } | ||
| $Stamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") | ||
| $Log = "[$Stamp] [$Level] $Message" | ||
|
|
||
| switch ($Level) { | ||
| "INFO" { Write-Host $Log } | ||
| "STEP" { Write-Host "`n>>> [$Stamp] $Message" -ForegroundColor Cyan } | ||
| "WARN" { Write-Host $Log -ForegroundColor Yellow } | ||
| "ERROR" { Write-Host $Log -ForegroundColor Red } | ||
| "DEBUG" { if ($DebugMode) { Write-Host $Log -ForegroundColor DarkGray } } | ||
| "NATIVE" { Write-Host " $Message" -ForegroundColor DarkGray } | ||
| "NATIVE-ERR" { Write-Host " $Message" -ForegroundColor DarkYellow } | ||
| } | ||
| } | ||
|
|
||
| # Execute native command with errorlevel handling | ||
| Function Invoke-Native-Command { | ||
| param( | ||
| [string] $Command, | ||
| [string[]] $Arguments | ||
| [string[]] $Arguments, | ||
| [switch] $SuppressStdErr | ||
| ) | ||
|
|
||
| & "$Command" @Arguments | ||
| Write-Log "DEBUG" "Executing: $Command $($Arguments -join ' ')" | ||
| $Out = [Collections.Generic.List[string]]::new() | ||
|
|
||
| if ($LastExitCode -Ne 0) | ||
| { | ||
| Throw "Native command $Command returned with exit code $LastExitCode" | ||
| $PrevEA = $ErrorActionPreference | ||
| $ErrorActionPreference = "Continue" | ||
|
|
||
| try { | ||
| & "$Command" @Arguments 2>&1 | ForEach-Object { | ||
| $IsErr = $_ -is [Management.Automation.ErrorRecord] | ||
| if ($IsErr -and $SuppressStdErr) { return } | ||
|
|
||
| $Line = if ($IsErr) { $_.TargetObject -as [string] } else { $_.ToString() } | ||
| if ([string]::IsNullOrWhiteSpace($Line)) { return } | ||
|
|
||
| $Out.Add($Line) | ||
|
|
||
| if ($IsErr) { | ||
| Write-Log "NATIVE-ERR" $Line | ||
| } else { | ||
| Write-Log "NATIVE" $Line | ||
| } | ||
| } | ||
| } finally { | ||
| $ErrorActionPreference = $PrevEA | ||
| } | ||
|
|
||
| if ($LastExitCode -Ne 0) { | ||
| $Err = "Native command $Command returned with exit code $LastExitCode" | ||
| Write-Log "ERROR" $Err | ||
| if (-not $DebugMode) { | ||
| $Out.ForEach({ Write-Log "ERROR" $_ }) | ||
| } | ||
| Throw $Err | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -54,8 +114,8 @@ Function Clean-Build-Environment | |
| if (Test-Path -Path $BuildPath) { Remove-Item -Path $BuildPath -Recurse -Force } | ||
| if (Test-Path -Path $DeployPath) { Remove-Item -Path $DeployPath -Recurse -Force } | ||
|
|
||
| New-Item -Path $BuildPath -ItemType Directory | ||
| New-Item -Path $DeployPath -ItemType Directory | ||
| New-Item -Path $BuildPath -ItemType Directory | Out-Null | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out-Null seems like a smell to me. the deploy script should print as much as possible... |
||
| New-Item -Path $DeployPath -ItemType Directory | Out-Null | ||
| } | ||
|
|
||
| # For sourceforge links we need to get the correct mirror (especially NISIS) Thanks: https://www.powershellmagazine.com/2013/01/29/pstip-retrieve-a-redirected-url/ | ||
|
JaminShanti marked this conversation as resolved.
|
||
|
|
@@ -78,13 +138,13 @@ Function Get-RedirectedUrl { | |
| return | ||
| } catch { | ||
| if ($attempt -lt $numAttempts) { | ||
| Write-Warning "Caught error: $_" | ||
| Write-Warning "Get-RedirectedUrl: Fetch attempt #${attempt}/${numAttempts} for $url failed, trying again in ${sleepTime}s" | ||
| Write-Log "WARN" "Caught error: $_" | ||
| Write-Log "WARN" "Get-RedirectedUrl: Fetch attempt #${attempt}/${numAttempts} for $url failed, trying again in ${sleepTime}s" | ||
| Start-Sleep -Seconds $sleepTime | ||
| $sleepTime = [Math]::Min($sleepTime * 2, $maxSleepTime) | ||
| continue | ||
| } | ||
| Write-Error "Get-RedirectedUrl: All ${numAttempts} fetch attempts for $url failed, failing whole call" | ||
| Write-Log "ERROR" "Get-RedirectedUrl: All ${numAttempts} fetch attempts for $url failed, failing whole call" | ||
| throw | ||
| } | ||
| } | ||
|
|
@@ -94,7 +154,7 @@ function Initialize-Module-Here ($m) { # see https://stackoverflow.com/a/5169240 | |
|
|
||
| # If module is imported say that and do nothing | ||
| if (Get-Module | Where-Object {$_.Name -eq $m}) { | ||
| Write-Output "Module $m is already imported." | ||
| Write-Log "INFO" "Module $m is already imported." | ||
| } | ||
| else { | ||
|
|
||
|
|
@@ -112,7 +172,7 @@ function Initialize-Module-Here ($m) { # see https://stackoverflow.com/a/5169240 | |
| else { | ||
|
|
||
| # If module is not imported, not available and not in online gallery then abort | ||
| Write-Output "Module $m not imported, not available and not in online gallery, exiting." | ||
| Write-Log "ERROR" "Module $m not imported, not available and not in online gallery, exiting." | ||
| EXIT 1 | ||
| } | ||
| } | ||
|
|
@@ -131,7 +191,7 @@ Function Install-Dependency | |
|
|
||
| if (Test-Path -Path "$WindowsPath\$Destination") | ||
| { | ||
| echo "Using ${WindowsPath}\${Destination} from previous run (e.g. actions/cache)" | ||
| Write-Log "INFO" "Using ${WindowsPath}\${Destination} from previous run (e.g. actions/cache)" | ||
| return | ||
| } | ||
|
|
||
|
|
@@ -140,17 +200,19 @@ Function Install-Dependency | |
| $TempGuid = [System.Guid]::NewGuid() | ||
| # Create a unique empty directory to unpack into | ||
| $TempDir = (Join-Path $TempPath $TempGuid) | ||
| New-Item -ItemType Directory -Path $TempDir | ||
| New-Item -ItemType Directory -Path $TempDir | Out-Null | ||
|
|
||
| if ($Uri -Match "downloads.sourceforge.net") | ||
| { | ||
| $Uri = Get-RedirectedUrl -URL $Uri | ||
| } | ||
|
|
||
| Write-Log "INFO" "Downloading $Uri..." | ||
| Invoke-WebRequest -Uri $Uri -OutFile $TempFileName | ||
| echo $TempFileName | ||
| Write-Log "DEBUG" "Saved to: $TempFileName" | ||
| Expand-Archive -Path $TempFileName -DestinationPath $TempDir -Force | ||
| echo $WindowsPath\$Destination | ||
| Write-Log "DEBUG" "Extracting to: $WindowsPath\$Destination" | ||
|
|
||
| # Because we unpacked into a new directory, we can use * for the directory in the archive, | ||
| # so that we do not need to know the directory name the archive was packed from. | ||
| Move-Item -Path "$TempDir\*" -Destination "$WindowsPath\$Destination" -Force | ||
|
|
@@ -161,6 +223,7 @@ Function Install-Dependency | |
| # Install VSSetup (Visual Studio detection), ASIO SDK and NSIS Installer | ||
| Function Install-Dependencies | ||
| { | ||
| Write-Log "STEP" "Installing Dependencies..." | ||
| if (-not (Get-PackageProvider -Name nuget).Name -eq "nuget") { | ||
| Install-PackageProvider -Name "Nuget" -Scope CurrentUser -Force | ||
| } | ||
|
|
@@ -171,6 +234,8 @@ Function Install-Dependencies | |
| # Don't download ASIO SDK on Jamulus JACK builds to save | ||
| # resources and to be extra-sure license-wise. | ||
| Install-Dependency -Uri $AsioSDKUrl -Destination "..\libs\ASIOSDK2" | ||
| } else { | ||
| Write-Log "INFO" "Skipping ASIO SDK (JACK build detected)." | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -227,6 +292,39 @@ Function Initialize-Build-Environment | |
| Remove-Item -Path $EnvDump -Force | ||
| } | ||
|
|
||
| # Resolve Qt path by falling back to Registry lookups if the default path is missing | ||
| Function Resolve-Qt-Path | ||
| { | ||
| param( | ||
| [Parameter(Mandatory=$true)] | ||
| [string] $DefaultPath | ||
| ) | ||
|
|
||
| if (Test-Path -Path $DefaultPath) { return $DefaultPath } | ||
|
|
||
| Write-Log "DEBUG" "Qt path '$DefaultPath' not found. Searching registry..." | ||
| $QtVer = Split-Path $DefaultPath -Leaf | ||
| $RegPaths = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*", | ||
| "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*", | ||
| "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" | ||
|
|
||
| foreach ($Reg in $RegPaths) | ||
| { | ||
| $Installs = Get-ItemProperty $Reg -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -match "Qt" -and $_.InstallLocation } | ||
| foreach ($Inst in $Installs) | ||
| { | ||
| $TryPath = Join-Path $Inst.InstallLocation $QtVer | ||
| if (Test-Path -Path $TryPath) | ||
| { | ||
| Write-Log "INFO" "Discovered Qt at: $TryPath" | ||
| return $TryPath | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return $DefaultPath | ||
| } | ||
|
|
||
| # Setup Qt environment variables and build tool paths | ||
| Function Initialize-Qt-Build-Environment | ||
| { | ||
|
|
@@ -243,6 +341,29 @@ Function Initialize-Qt-Build-Environment | |
| Set-Item Env:QtQmakePath "$QtMsvcSpecPath\qmake.exe" | ||
| Set-Item Env:QtWinDeployPath "$QtMsvcSpecPath\windeployqt.exe" | ||
|
|
||
| if (Get-Command "jom.exe" -ErrorAction SilentlyContinue) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please explain the reasoning behind this here. |
||
| { | ||
| Set-Item Env:QtJomPath "jom.exe" | ||
| } | ||
| else | ||
| { | ||
| $QtRoot = Split-Path $QtInstallPath -Parent | ||
| $JomExes = "$QtRoot\Tools\QtCreator\bin\jom\jom.exe", | ||
| "$QtRoot\Tools\jom\jom.exe", | ||
| "C:\Qt\Tools\QtCreator\bin\jom\jom.exe", | ||
| "D:\Qt\Tools\QtCreator\bin\jom\jom.exe" | ||
|
|
||
| $FoundJom = $JomExes | Where-Object { Test-Path -Path $_ } | Select-Object -First 1 | ||
| if ($FoundJom) | ||
| { | ||
| Set-Item Env:QtJomPath $FoundJom | ||
| } | ||
| else | ||
| { | ||
| Set-Item Env:QtJomPath "" | ||
| } | ||
| } | ||
|
|
||
| "**********************************************************************" | ||
| "Using Qt binaries for Visual C++ located at" | ||
| $QtMsvcSpecPath | ||
|
|
@@ -267,27 +388,48 @@ Function Build-App | |
| [string] $BuildArch | ||
| ) | ||
|
|
||
| $QmkCfg = "CONFIG+=$BuildConfig $BuildArch $BuildOption" | ||
| if (-not $DebugMode) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we want any silent mode in the CI... |
||
| { | ||
| $QmkCfg += " silent" | ||
| } | ||
|
|
||
| Invoke-Native-Command -Command "$Env:QtQmakePath" ` | ||
| -Arguments ("$RootPath\$AppName.pro", "CONFIG+=$BuildConfig $BuildArch $BuildOption", ` | ||
| "-o", "$BuildPath\Makefile") | ||
| -Arguments ("$RootPath\$AppName.pro", $QmkCfg, "-o", "$BuildPath\Makefile") | ||
|
|
||
| Set-Location -Path $BuildPath | ||
| if (Get-Command "jom.exe" -ErrorAction SilentlyContinue) | ||
|
|
||
| $MkArgs = @("/NOLOGO", $BuildConfig) | ||
| if (-not $DebugMode) | ||
| { | ||
| $MkArgs += "/S" | ||
| } | ||
|
|
||
| if ($Env:QtJomPath) | ||
| { | ||
| echo "Building with jom /J ${Env:NUMBER_OF_PROCESSORS}" | ||
| Invoke-Native-Command -Command "jom" -Arguments ("/J", "${Env:NUMBER_OF_PROCESSORS}", "$BuildConfig") | ||
| $Cores = [Math]::Max(1, [Math]::Floor([int]$Env:NUMBER_OF_PROCESSORS / 2)) | ||
| Write-Log "INFO" "Building with jom /J $Cores (half of $Env:NUMBER_OF_PROCESSORS cores)" | ||
| Invoke-Native-Command -Command "$Env:QtJomPath" -Arguments (@("/J", "$Cores") + $MkArgs) | ||
| } | ||
| else | ||
| { | ||
| echo "Building with nmake (install Qt jom if you want parallel builds)" | ||
| Invoke-Native-Command -Command "nmake" -Arguments ("$BuildConfig") | ||
| Write-Log "INFO" "Building with nmake (install Qt jom if you want parallel builds)" | ||
| Invoke-Native-Command -Command "nmake" -Arguments $MkArgs | ||
| } | ||
|
|
||
| Invoke-Native-Command -Command "$Env:QtWinDeployPath" ` | ||
| -Arguments ("--$BuildConfig", "--compiler-runtime", "--dir=$DeployPath\$BuildArch", | ||
| "$BuildPath\$BuildConfig\$AppName.exe") | ||
|
|
||
| Move-Item -Path "$BuildPath\$BuildConfig\$AppName.exe" -Destination "$DeployPath\$BuildArch" -Force | ||
| Invoke-Native-Command -Command "nmake" -Arguments ("clean") | ||
|
|
||
| $CleanArgs = @("clean", "/NOLOGO") | ||
| if (-not $DebugMode) | ||
| { | ||
| $CleanArgs += "/S" | ||
| } | ||
| Invoke-Native-Command -Command "nmake" -Arguments $CleanArgs -SuppressStdErr | ||
|
|
||
| Set-Location -Path $RootPath | ||
| } | ||
|
|
||
|
|
@@ -296,16 +438,18 @@ function Build-App-Variants | |
| { | ||
| foreach ($_ in ("x86_64", "x86")) | ||
| { | ||
| if (($_ -eq "x86_64" -and $Skip64Bit) -or ($_ -eq "x86" -and $Skip32Bit)) { continue } | ||
|
|
||
| $OriginalEnv = Get-ChildItem Env: | ||
| if ($_ -eq "x86") | ||
| { | ||
| Initialize-Build-Environment -BuildArch $_ | ||
| Initialize-Qt-Build-Environment -QtInstallPath $QtInstallPath32 -QtCompile $QtCompile32 | ||
| Initialize-Qt-Build-Environment -QtInstallPath (Resolve-Qt-Path -DefaultPath $QtInstallPath32) -QtCompile $QtCompile32 | ||
| } | ||
| else | ||
| { | ||
| Initialize-Build-Environment -BuildArch $_ | ||
| Initialize-Qt-Build-Environment -QtInstallPath $QtInstallPath64 -QtCompile $QtCompile64 | ||
| Initialize-Qt-Build-Environment -QtInstallPath (Resolve-Qt-Path -DefaultPath $QtInstallPath64) -QtCompile $QtCompile64 | ||
| } | ||
| Build-App -BuildConfig "release" -BuildArch $_ | ||
| $OriginalEnv | % { Set-Item "Env:$($_.Name)" $_.Value } | ||
|
|
@@ -319,6 +463,14 @@ Function Build-Installer | |
| [string] $BuildOption | ||
| ) | ||
|
|
||
| # --- SAFETY GATE: Do not build if no executables were generated --- | ||
| $Has64 = Test-Path -Path "$DeployPath\x86_64\$AppName.exe" | ||
| $Has32 = Test-Path -Path "$DeployPath\x86\$AppName.exe" | ||
|
|
||
| if (-not $Has64 -and -not $Has32) { | ||
| Throw "Installer build aborted: No application binaries found." | ||
| } | ||
|
|
||
| foreach ($_ in Get-Content -Path "$RootPath\$AppName.pro") | ||
| { | ||
| if ($_ -Match "^VERSION *= *(.*)$") | ||
|
|
@@ -328,18 +480,20 @@ Function Build-Installer | |
| } | ||
| } | ||
|
|
||
| $NsisVerb = if ($DebugMode) { "/v4" } else { "/v2" } | ||
|
|
||
| if ($BuildOption -ne "") | ||
| { | ||
| Invoke-Native-Command -Command "$RootPath\libs\NSIS\NSIS-source\makensis" ` | ||
| -Arguments ("/v4", "/DAPP_NAME=$AppName", "/DAPP_VERSION=$AppVersion", ` | ||
| -Arguments ($NsisVerb, "/DAPP_NAME=$AppName", "/DAPP_VERSION=$AppVersion", ` | ||
| "/DROOT_PATH=$RootPath", "/DWINDOWS_PATH=$WindowsPath", "/DDEPLOY_PATH=$DeployPath", ` | ||
| "/DBUILD_OPTION=$BuildOption", ` | ||
| "$WindowsPath\installer.nsi") | ||
| } | ||
| else | ||
| { | ||
| Invoke-Native-Command -Command "$RootPath\libs\NSIS\NSIS-source\makensis" ` | ||
| -Arguments ("/v4", "/DAPP_NAME=$AppName", "/DAPP_VERSION=$AppVersion", ` | ||
| -Arguments ($NsisVerb, "/DAPP_NAME=$AppName", "/DAPP_VERSION=$AppVersion", ` | ||
| "/DROOT_PATH=$RootPath", "/DWINDOWS_PATH=$WindowsPath", "/DDEPLOY_PATH=$DeployPath", ` | ||
| "$WindowsPath\installer.nsi") | ||
| } | ||
|
|
@@ -350,7 +504,7 @@ Function Build-NSProcess | |
| { | ||
| if (!(Test-Path -path "$RootPath\libs\NSIS\nsProcess.dll")) { | ||
|
|
||
| echo "Building nsProcess..." | ||
| Write-Log "INFO" "Building nsProcess..." | ||
|
|
||
| $OriginalEnv = Get-ChildItem Env: | ||
| Initialize-Build-Environment -BuildArch "x86" | ||
|
|
@@ -370,3 +524,4 @@ Install-Dependencies | |
| Build-App-Variants | ||
| Build-NSProcess | ||
| Build-Installer -BuildOption $BuildOption | ||
| Write-Log "STEP" "Build process completed successfully." | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH I am unsure if we really need this..