Last active
October 23, 2023 08:13
-
-
Save loopyd/9dd6658f2e0eb3910996fc983ec97d2d to your computer and use it in GitHub Desktop.
[BlAse.ps1] Autonomous Single-File Aseprite Build Tool
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
################################################################################ | |
# | |
# BLASE - AUTOMATED AESPRITE BUILDING FOR WINDOWS | |
# | |
# Created by loopyd <loopyd@github.com> | |
# Version: 1.0.0 | |
# License: Unlicense (https://unlicense.org/) | |
# | |
# ============================================================================== | |
# Inferred from Blep - the draconic windows automation tool | |
# https://gist.github.com/loopyd/ae5f5a50b679b98e0899e4748e8f5ce0 | |
# ============================================================================== | |
# | |
# This script is designed to fully automate the building of Aseprite on | |
# Windows. It will install all dependencies, and then build Aseprite with | |
# the specified options. It is designed to be run on a fresh Windows | |
# installation, all the way up to a fully configured development environment. | |
# | |
# I couldn't find a plug-and-play solution for building Aseprite on Windows, | |
# so I decided to make one using parts of blep. This script is the result of | |
# that effort. This script expands on blep by adding a ton of new features, | |
# such as a customized LLVM build, a python version manager that doesn't | |
# depend on chocolatey, and a custom skia build using the Google Depot Tools | |
# without needing to include MozillaBuild. The resulting build is the most | |
# performant build of Aseprite you can get, as its built from scratch using | |
# the latest versions of all the dependencies, and is optimized for your CPU. | |
# | |
# From unit testing, the blAse-built Aseprite is 1.63x faster than the latest | |
# release you can pay $60 for. Making it ideal to work on large projects. | |
# | |
# ------------------------ | |
# CHANGES MADE TO THE HOST | |
# ------------------------ | |
# | |
# Under transparency, this script makes non-destructive modifications to your | |
# system. These changes are detailed below: | |
# | |
# - The script is required to be run as an Administrator, as it will install | |
# various packages and read from the registry. It does not modify the | |
# registry, however, to ensure that it is non-destructive. | |
# | |
# Learn more about Powershell 7 here: | |
# https://docs.microsoft.com/en-us/powershell/scripting/overview?view=powershell-7.1 | |
# | |
# - If you don't have Chocolatey installed, it will install it for you. | |
# Chocolatey is a useful package manager for Windows, and is used to | |
# automate the installation of some dependencies. | |
# | |
# You can learn more about Chocolatey here: https://chocolatey.org/ | |
# | |
# - If you don't have 7zip installed, it will install it for you. | |
# | |
# Discover 7zip here: https://www.7-zip.org/ | |
# | |
# - If you don't have the Windows SDK installed, it will install the | |
# appropriate version for you. Defaults to 10.0.18362.0, but can be | |
# changed with the -WindowsSdkVersion parameter. | |
# | |
# Learn more about the Windows SDK (Windows API) here: | |
# https://docs.microsoft.com/en-us/windows/win32/apiindex/windows-apisets | |
# | |
# - If you don't have Visual Studio installed, it will install the | |
# appropriate version for you. Defaults to 16.0, but can be changed | |
# with the -VisualStudioVersion parameter. | |
# | |
# Learn more about Visual Studio here: https://visualstudio.microsoft.com/ | |
# | |
# - LLVM-blAse is a specialized compiler used to build Aseprite. If you don't | |
# know, Aesprite's main bottleneck is the fact that it is built with MSVC, | |
# so blAse uses a customized version of LLVM-clang to build it instead that | |
# has unnessecary bloat removed, and is optimized for your CPU. | |
# | |
# Learn more about LLVM here: https://llvm.org/ | |
# | |
# - If you don't have Ninja installed, it will install the appropriate | |
# version for you. Ninja is a specialized build system used to | |
# facilitate build automation for multilanguage CMake projects | |
# | |
# Learn more about Ninja here: https://ninja-build.org/ | |
# | |
# - If you don't have CMake installed, it will install the appropriate | |
# version for you. CMake is a specialized build system used to | |
# automate the build process for C and C++ projects. | |
# | |
# Learn more about CMake here: https://cmake.org/ | |
# | |
# ------------------------ | |
# FAQ | |
# ------------------------ | |
# | |
# Q: Why is this script so long? | |
# | |
# A: Because it does a lot of things. It installs a lot of dependencies, and | |
# builds a lot of things from scratch. | |
# | |
# Q: Why does this script take so long to run? | |
# | |
# A: Becuase you have a slow computer, download more RAM today. The script | |
# takes approximately 4 hours to cook blAse-Aesprite on an i9-11700k. | |
# | |
# If you experience Page Faults or BSODs, you may need to increase your | |
# virtual memory allocation. | |
# | |
# Q: Are you going to make a Linux version? | |
# | |
# A: No. Well...maybe. If someone decides to port this entire script to | |
# bash, I'll consider it. But I'm not going to do it myself. | |
# writing over 25,000 lines of bash is not my idea of a good time. | |
# | |
# Q: Are you going to make a Mac version? | |
# | |
# A: You're funny. | |
# | |
# Q: What's all this on my system? | |
# | |
# A: The script installs a lot of dependencies. Its going to leave | |
# Visual Studio Community and the Windows SDK on your system, as | |
# well as Python. Becuase it would take me 24 hours each test | |
# to run the script where it uninstalls?reinstalls everything, | |
# and no one's got 500TB of monthly ISP bandwidth to waste on that. | |
# | |
# I like to avoid cease and desist letters from my ISP, GitHub, the | |
# Python Software Foundation, and Microsoft, so I'm not going to automate that | |
# by adding uninstallation/reinstallation of the big tools to the -Clean | |
# switch. If you want to uninstall them, you can do it yourself, and | |
# potentially deal with the consiquences of re-running the script | |
# many times over and pissing off the afformentioned entities. | |
# | |
# Downloads are cached in the configured -CachePath, to avoid repeated | |
# downloads. If you want to clear the cache, you can do so by passing | |
# the -Clean switch to the script. But this is NOT recommended on | |
# a slow internet connection, as it will force the script to re-download | |
# everything that is to be considered a dependency. | |
param( | |
[Parameter(Position = 0, Mandatory = $false)][string]$AseVersion = "v1.3-rc6", | |
[Parameter(Position = 1, Mandatory = $false)][string]$SkiaVersion = "aseprite-m102", | |
[Parameter(Position = 2, Mandatory = $false)][string]$WindowsSdkVersion = "10.0.18362", | |
[Parameter(Position = 3, Mandatory = $false)][string]$VisualStudioVersion = "17.0", | |
[Parameter(Position = 4, Mandatory = $false)][string]$LLVMVersion = "17.0.1", | |
[Parameter(Position = 5, Mandatory = $false)][string]$CmakeVersion = "3.28.0-rc2", | |
[Parameter(Position = 6, Mandatory = $false)][string]$GitVersion = "2.42.0", | |
[Parameter(Position = 7, Mandatory = $false)][string]$GitSubVersion = "2", | |
[Parameter(Position = 8, Mandatory = $false)][string]$CachePath = "$PWD\.cache", | |
[Parameter(Position = 9, Mandatory = $false)][switch]$SkiaUsePrebuilt, | |
[Parameter(Position = 10, Mandatory = $false)][switch]$Clean | |
) | |
<############################################## | |
# PRE-FLIGHT CHECKS | |
##############################################> | |
# Block non-admin execution of the script. We need admin to install chocolatey, winget, and scoop, to make registry changes, and to install some packages. | |
$IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") | |
if (-not $IsAdmin) { | |
Write-Error "You must run this script as an Administrator!" | |
exit 1 | |
} | |
# Check and ensure the script is running as Powershell 7, if it is not, install it silently and reloaunch the script as Powershell 7. We use a legacy Powershell version to install Powershell 7 if we need to, so we use some old backwards-compatible code to do this. | |
if ($PSVersionTable.PSVersion.Major -lt 7) { | |
if (-not (Test-Path pwsh)) { | |
Write-Host -ForegroundColor Green $("-" * 80) | |
Write-Warning -Message "Powershell 7 is not installed, and required by the script, attempting to install it now..." | |
$url = "https://github.com/PowerShell/PowerShell/releases/download/v7.3.6/PowerShell-7.3.6-win-x64.msi" | |
$output = "$env:TEMP\PPowerShell-7.3.6-win-x64.msi" | |
$client = New-Object System.Net.WebClient | |
$client.DownloadFile($url, $output) | |
$arguments = "/i `"$output`" /quiet /qn /norestart" | |
Start-Process "msiexec.exe" -ArgumentList $arguments -Wait | |
if ($LASTEXITCODE -ne 0) { | |
Write-Error -Message "Powershell 7 installation failed, exiting script" | |
Write-Host -ForegroundColor Green $("-" * 80) | |
exit 1 | |
} | |
} | |
Write-Warning -Message "This script requires Powershell 7 or higher to execute, attempting to relaunch script as Powershell 7..." | |
Write-Host -ForegroundColor Green $("-" * 80) | |
Start-Process pwsh -ArgumentList "-File $PSCommandPath" -Verb RunAs | |
exit $LASTEXITCODE | |
} | |
# Create a Powershell profile file if it doesn't exist. | |
if (-not $(Test-Path -Path "$PROFILE")) { | |
New-Item -ItemType File -Path "$PROFILE" | |
} | |
############################################## | |
# DRAGONS HEART - CORE FUNCTIONS | |
############################################## | |
<# | |
.SYNOPSIS | |
This function displays the splash logo for the script. | |
.DESCRIPTION | |
As the description says, this function displays the splash logo for the script. I have made it editable this time. Please be honest with any modifications and provide credit to the original author. | |
.NOTES | |
Not providing credit to the original author makes you a Donkey Dick. | |
I need to update this when I get around to it. If you're proficient with | |
ASCII art using NerdFonts and Powershell color commands, please reach out! | |
#> | |
function Display-Logo { | |
$logo = @" | |
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ | |
▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓ | |
▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓ B L A S E | Unilicensed | |
▓▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓▓▓ | |
▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓ A single-file PSSolution to liberate aesprite | |
▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓ for Windows, from scratch! | |
▓▓▓░░░░░░░░▓▓▓░░░░░░░░░░▓▓▓░░░░░░░░▓▓▓ | |
▓▓▓░░░░░░░░▓▓▓░░░░░░░░░░▓▓▓░░░░░░░░▓▓▓ LLVM-blAse | skia from src | Google Depot | |
▓▓▓░░░░░░░░▓▓▓░░░░░░░░░░▓▓▓░░░░░░░░▓▓▓ | |
▓▓▓░░░░░░░░▓▓▓░░░░░░░░░░▓▓▓░░░░░░░░▓▓▓ The most performant build of Asesprite known to | |
▓▓▓░░░░░░░░▓▓▓░░░░░░░░░░▓▓▓░░░░░░░░▓▓▓ the Brood using skia built with a custom version | |
▓▓▓░░░░░░░░▓▓▓░░░░░░░░░░▓▓▓░░░░░░░░▓▓▓ of LLVM-clang optimized for your CPU, and built | |
▓▓▓░░░░░░░░▒▒▒░░░░░░░░░░▒▒▒░░░░░░░░▓▓▓ from nothing! Asesprite-blAse is GAURENTEED | |
▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓ to run butter-smooth on your system! | |
▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓ | |
▓▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓▓▓ -=== + ===- | |
▓▓▓▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▒▓▓▓ | |
▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓ \. _|_ ./ {Powershell Gods} | |
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ \. .._.. ./ deitydragon | |
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ \ __________ / | |
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ | |
"@ | |
Clear-Host | |
Write-Host -ForegroundColor Red $logo | |
} | |
function Display-Success() { | |
param( | |
[Parameter(Mandatory=$true)] | |
[string]$ArtifactPath | |
) | |
Clear-Host | |
Write-Host -NoNewline -ForegroundColor Yellow -BackgroundColor DarkRed " 🐲💖🔥>~ BUILD SUCCESSFUL! ~<🔥💖🐲 " | |
Write-Host -NoNewline -ForegroundColor White "`n`n`r Your " | |
Write-Host -NoNewline -ForegroundColor Red "BlAse" | |
Write-Host -NoNewline -ForegroundColor Yellow "prite" | |
Write-Host -NoNewline -ForegroundColor White " build can be found at:`n`n`r" | |
Write-Host -NoNewline -ForegroundColor Cyan " $ArtifactPath`n`n`r" | |
Write-Host -NoNewline -ForegroundColor Yellow " 💫 Thank you" | |
Write-Host -NoNewline -ForegroundColor White " for using " | |
Write-Host -NoNewline -ForegroundColor Red "BlAse" | |
Write-Host -NoNewline -ForegroundColor White "!`n`n`r" | |
} | |
<# | |
.SYNOPSIS | |
Ridiculous Output Augmentation Routine - R. O. A. R. | |
.DESCRIPTION | |
This function invokes a command. It displays a timer with resource usage while the command is running. It also displays the command name, and entertains the user with an animation. | |
.PARAMETER Command | |
The command to invoke. | |
.PARAMETER Arguments | |
The arguments to pass to the command. | |
.PARAMETER Plain | |
If this switch is specified, the output will arrive sanitized with no ANSI escape codes. | |
.EXAMPLE | |
Invoke-Roar -Command "choco" -Arguments @("install", "7zip") | |
.NOTES | |
Roar XD | |
#> | |
function Roar { | |
param ( | |
[Parameter(Mandatory=$true)] | |
[string]$Command, | |
[Parameter(Mandatory=$false)] | |
[string[]]$Arguments, | |
[Parameter(Mandatory=$false)] | |
[switch]$Plain | |
) | |
# Initialize the queues for the stdout, stderr, and timer | |
$stdoutQueue = [System.Collections.Queue]::Synchronized((New-Object System.Collections.Queue)) | |
$stderrQueue = [System.Collections.Queue]::Synchronized((New-Object System.Collections.Queue)) | |
$timerQueue = [System.Collections.Queue]::Synchronized((New-Object System.Collections.Queue)) | |
# Create an initial session state with the current environment variables | |
$initialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() | |
$initialSessionState.Variables.Add( | |
[System.Management.Automation.Runspaces.SessionStateVariableEntry]::new( | |
"env", [System.Environment]::GetEnvironmentVariables(), "Environment variables" | |
) | |
) | |
# Command execution runspace | |
$cmdExecRunspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($initialSessionState) | |
$cmdExecRunspace.Open() | |
$cmdExecPowershell = [System.Management.Automation.PowerShell]::Create() | |
$cmdExecPowershell.Runspace = $cmdExecRunspace | |
$currentDirectory = Get-Location | |
$cmdExecPowershell = $cmdExecPowershell.AddScript({ | |
param( | |
[Parameter(Mandatory=$true)] | |
[string]$Command, | |
[Parameter(Mandatory=$false)] | |
[string]$argumentString, | |
[Parameter(Mandatory=$false)] | |
[string]$WorkingDirectory | |
) | |
$exitCode = $null | |
try { | |
if ($null -ne $WorkingDirectory) { | |
if (-not (Test-Path -Path $WorkingDirectory)) { | |
Write-Error "Working directory does not exist: $WorkingDirectory" | |
throw [System.IO.DirectoryNotFoundException]::new("Working directory does not exist: $WorkingDirectory") | |
} | |
Set-Location -Path $WorkingDirectory | |
} | |
Invoke-Expression "& `"$Command`" $argumentString 2>&1" | Write-Information | |
$exitCode = $LASTEXITCODE | |
} catch { | |
# Do nothing | |
} finally { | |
[PSCustomObject]@{ | |
ExitCode = $exitCode | |
} | |
} | |
}).AddArgument($Command).AddArgument($($Arguments -join ' ')).AddArgument($currentDirectory) | |
# Start the command execution runspace | |
$cmdExecAsync = $cmdExecPowershell.BeginInvoke() | |
# Set up the output processing runspace | |
$outputProcessingRunspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($initialSessionState) | |
$outputProcessingRunspace.Open() | |
$outputProcessingPowershell = [System.Management.Automation.PowerShell]::Create() | |
$outputProcessingPowershell.Runspace = $outputProcessingRunspace | |
$outputProcessingPowershell = $outputProcessingPowershell.AddScript({ | |
param( | |
[System.IAsyncResult]$ResultAsync, | |
[System.Management.Automation.PowerShell]$powershell, | |
[System.Collections.Queue]$StdoutQueue, | |
[System.Collections.Queue]$StderrQueue | |
) | |
while (-not $ResultAsync.IsCompleted) { | |
# The only thing that we would format as an error is actually an error. | |
if ($powershell.Streams.Error.Count -gt 0) { | |
$powershell.Streams.Error.ReadAll().ForEach({ $_.Exception.Message.ToString() }) | ForEach-Object { | |
$stderrQueue.Enqueue(($_)) | |
} | |
$powershell.Streams.Error.Clear() | |
} | |
# The rest of it gets put on the standard pipeline. | |
if ($powershell.Streams.Information.Count -gt 0) { | |
$powershell.Streams.Information.ReadAll().ForEach({ $_.MessageData }) | ForEach-Object { | |
$stdoutQueue.Enqueue(($_.ToString() -replace '\x1B\[[0-9;]*m' -replace "`r`n", "")) | |
} | |
$powershell.Streams.Information.Clear() | |
} | |
if ($powershell.Streams.Verbose.Count -gt 0) { | |
$powershell.Streams.Verbose.ReadAll().ForEach({ $_.Message }) | ForEach-Object { | |
$stdoutQueue.Enqueue(($_.ToString() -replace '\x1B\[[0-9;]*m' -replace "`r`n", "")) | |
} | |
$powershell.Streams.Verbose.Clear() | |
} | |
if ($powershell.Streams.Warning.Count -gt 0) { | |
$powershell.Streams.Warning.ReadAll().ForEach({ $_.Message }) | ForEach-Object { | |
$stdoutQueue.Enqueue(($_.ToString() -replace '\x1B\[[0-9;]*m' -replace "`r`n", "")) | |
} | |
$powershell.Streams.Warning.Clear() | |
} | |
if ($powershell.Streams.Debug.Count -gt 0) { | |
$powershell.Streams.Debug.ReadAll().ForEach({ $_.Message }) | ForEach-Object { | |
$stdoutQueue.Enqueue(($_.ToString() -replace '\x1B\[[0-9;]*m' -replace "`r`n", "")) | |
} | |
$powershell.Streams.Debug.Clear() | |
} | |
} | |
}).AddArgument($cmdExecAsync).AddArgument($cmdExecPowershell).AddArgument($stdoutQueue).AddArgument($stderrQueue) | |
# Start the output processing runspace | |
$outputProcessingAsync = $outputProcessingPowershell.InvokeAsync() | |
# Set up the display runspace with the timer queue | |
$displayRunspace = [runspacefactory]::CreateRunspace() | |
$displayRunspace.Open() | |
$displayPowershell = [System.Management.Automation.PowerShell]::Create() | |
$displayPowershell.Runspace = $displayRunspace | |
$displayPowershell = $displayPowershell.AddScript({ | |
param($Command, $queue) | |
$executableName = [System.IO.Path]::GetFileName($Command) | |
$executableName = $executableName.Substring(0, [Math]::Min(32, $executableName.Length)) | |
$executableName = $executableName.PadRight(32) | |
$cursorStates = '|/-\' | |
$cursorIndex = 0 | |
$startTime = Get-Date | |
$dragonCycle = 4000 | |
$fireCycle = 1000 | |
$boomCycle = 300 | |
$sequenceCycle = $dragonCycle + $fireCycle + $boomCycle | |
while ($true) { | |
$elapsed = [datetime]::Now - $startTime | |
$sequencePosition = $elapsed.Milliseconds % $sequenceCycle | |
$queue.Enqueue(@{ | |
Cursor = $cursorStates[$cursorIndex % $cursorStates.Length] | |
ElapsedStr = $("{0:D2}:{1:D2}:{2:D2}.{3:D3}" -f $elapsed.Hours, $elapsed.Minutes, $elapsed.Seconds, $elapsed.Milliseconds) | |
ExecutableName = $executableName | |
DragonEmoji = if ($sequencePosition % $dragonCycle -lt $dragonCycle / 4 -and $sequencePosition % 500 -lt 250) { "🐉" } else { " " } | |
FireEmoji = if ($sequencePosition % $fireCycle -lt $fireCycle / 1.25 -and $sequencePosition % 500 -lt 250 ) { "🔥" } else { " " } | |
BoomEmoji = if ($sequencePosition % $boomCycle -lt $boomCycle / 4 -and $sequencePosition % 250 -lt 125) { "💥" } else { " " } | |
Roaring = if ($elapsed.Milliseconds % 1000 -lt 500) { "blep!" } else { " " } | |
}) | |
$cursorIndex++ | |
Start-Sleep -Milliseconds 1 | |
} | |
}).AddArgument($Command).AddArgument($timerQueue) | |
# Start the display runspace | |
$displayPowershellAsync = $displayPowershell.InvokeAsync() | |
# Main thread (draws the HUD and waits for the command to complete) | |
Write-Host "`n`n`r" -NoNewline | |
$Top = [System.Console]::CursorTop - 2 | |
[System.Console]::CursorVisible = $false | |
while (-not $cmdExecAsync.IsCompleted -or $stdoutQueue.Count -gt 0 -or $stderrQueue.Count -gt 0) { | |
while ($stdoutQueue.Count -gt 0) { | |
$output = $stdoutQueue.Dequeue() | |
if (-not $Plain) { | |
[System.Console]::SetCursorPosition([System.Console]::CursorLeft, $Top) | |
Write-Host -NoNewline $("`r" + (" " * ([Console]::BufferWidth - 1)) + "`r") | |
Write-Host -NoNewline -ForegroundColor Magenta $($output.Substring(0, [Math]::Min($output.Length, [Console]::BufferWidth - 2)) + "`r") | |
} else { | |
Write-Host -ForegroundColor Magenta $output | |
} | |
} | |
while ($stderrQueue.Count -gt 0) { | |
$output = $stderrQueue.Dequeue() | |
if (-not $Plain) { | |
[System.Console]::SetCursorPosition([System.Console]::CursorLeft, $Top) | |
Write-Host -NoNewline $("`r" + (" " * ([Console]::BufferWidth - 1)) + "`r") | |
Write-Host -NoNewline -ForegroundColor Red $($output.Substring(0, [Math]::Min($output.Length, [Console]::BufferWidth - 2)) + "`r") | |
} else { | |
Write-Host -ForegroundColor Red $output | |
} | |
} | |
while ($timerQueue.Count -gt 0) { | |
$outputHashTable = $timerQueue.Dequeue() | |
if (-not $Plain) { | |
[System.Console]::SetCursorPosition([System.Console]::CursorLeft, $Top + 1) | |
Write-Host -NoNewline -ForegroundColor White -BackgroundColor Red " $([string]::Format("{0,1}", $outputHashTable.Cursor)) " | |
Write-Host -NoNewline -ForegroundColor Yellow -BackgroundColor DarkRed " $([string]::Format('{0,6}', $outputHashTable.Roaring)) " | |
Write-Host -NoNewline -ForegroundColor Black -BackgroundColor DarkRed " $([string]::Format('{0,20}', $outputHashTable.ExecutableName)) " | |
Write-Host -NoNewline -ForegroundColor White -BackgroundColor DarkRed " $([string]::Format('{0,12}', $outputHashTable.ElapsedStr)) " | |
Write-Host -NoNewline -ForegroundColor Yellow -BackgroundColor Red " $([string]::Format('{0,1}', $outputHashTable.DragonEmoji))" | |
Write-Host -NoNewline -ForegroundColor Yellow -BackgroundColor Red " $([string]::Format('{0,1}', $outputHashTable.FireEmoji))" | |
Write-Host -NoNewline -ForegroundColor Yellow -BackgroundColor Red " $([string]::Format('{0,1}', $outputHashTable.BoomEmoji)) `r" | |
} else { | |
# No timer updates if in plain mode, we just flush the buffer. | |
} | |
} | |
} | |
if (-not $Plain) { | |
[System.Console]::SetCursorPosition([System.Console]::CursorLeft, $Top) | |
Write-Host -NoNewline $("`r" + (" " * ([Console]::BufferWidth - 1)) + "`r") | |
[System.Console]::SetCursorPosition([System.Console]::CursorLeft, $Top + 1) | |
Write-Host -NoNewline $("`r" + (" " * ([Console]::BufferWidth - 1)) + "`r") | |
[System.Console]::SetCursorPosition([System.Console]::CursorLeft, $Top) | |
} | |
[System.Console]::CursorVisible = $true | |
# Close the output processing runspace | |
$outputProcessingPowershell.Stop() | |
$outputProcessingPowershell.Dispose() | |
$outputProcessingRunspace.Close() | |
$outputProcessingRunspace.Dispose() | |
# Close the timer runspace | |
$displayPowershell.Stop() | |
$displayPowershell.Dispose() | |
$displayRunspace.Close() | |
$displayRunspace.Dispose() | |
# Stop the command execution runspace | |
$exitCodeResult = $cmdExecPowershell.EndInvoke($cmdExecAsync) | |
$exitCode = $null -eq $exitCodeResult.ExitCode ? 0 : $exitCodeResult.ExitCode | |
# Merge the changed environment variables from the runspace into the current environment | |
$runspaceEnvironment = $cmdExecPowershell.AddScript('[System.Environment]::GetEnvironmentVariables()').Invoke() | |
foreach ($key in $runspaceEnvironment[0].Keys) { | |
[System.Environment]::SetEnvironmentVariable($key, $runspaceEnvironment[0][$key], [System.EnvironmentVariableTarget]::Process) | |
} | |
# Close the command execution runspace | |
$cmdExecPowershell.Dispose() | |
$cmdExecRunspace.Close() | |
$cmdExecRunspace.Dispose() | |
# Destroy the queues | |
$stdoutQueue.Clear() | |
$stderrQueue.Clear() | |
$timerQueue.Clear() | |
# Send powershell instances to the garbage collector | |
$cmdExecPowershell = $null | |
$outputProcessingPowershell = $null | |
$displayPowershell = $null | |
[System.GC]::Collect() | |
# Return the exit code | |
return $exitCode | |
} | |
############################################## | |
# PACKAGE MANAGER API | |
############################################## | |
<# | |
.SYNOPSIS | |
This function allows you to install packages from various package managers. | |
.DESCRIPTION | |
This function allows you to install packages from various package managers. It will not install a package if it is already installed, instead, it will try to update it. Status will be displayed in the terminal, along with a results summary. This function can install packages from Chocolatey, Winget, and Scoop. | |
.PARAMETER Packages | |
A string array of packages to install. | |
.PARAMETER PackageType | |
The package manager to use. Valid values are: choco, winget, scoop | |
.EXAMPLE | |
$Packages = @( | |
"7zip", | |
"git", | |
"notepadplusplus", | |
"vscode" | |
) | |
Install-Packages -Packages $Packages -PackageType "choco" | |
.NOTES | |
This function does not offer the capability to uninstall packages, as it is designed around working non-destructively. | |
#> | |
function Install-Packages { | |
param ( | |
[string[]]$Packages, | |
[ValidateSet("choco", "winget", "scoop", IgnoreCase = $true)] | |
[string]$PackageType | |
) | |
$result = Install-PackageManager -PackageManager $PackageType | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "❌ An error occoured with the package manager check, the script will now exit." | |
return $false | |
} | |
$succeededPackages = @() | |
$failedPackages = @() | |
ForEach ($Package in $Packages) { | |
switch ($PackageType.ToLower()) { | |
"choco" { | |
if ($null -eq $(choco list --local-only | Where-Object { $_ -like "$PackageName*" } )) { | |
Write-Host -ForegroundColor Yellow "⏳ Installing $Package..." | |
choco install $Package --confirm | |
} else { | |
Write-Host -ForegroundColor Yellow "⚠️ Package $Package is already installed, attempting to upgrade it, instead." | |
choco upgrade $Package --confirm | |
} | |
} | |
"winget" { | |
if ($null -eq $(winget list | Where-Object { $_ -like "$PackageName*" } )) { | |
Write-Host -ForegroundColor Yellow "⏳ Installing $Package..." | |
winget install $Package --disable-interactivity | |
} else { | |
Write-Host -ForegroundColor Yellow "⚠️ Package $Package is already installed, attempting to upgrade it, instead." | |
winget upgrade $Package --disable-interactivity | |
} | |
} | |
"scoop" { | |
if ($null -eq $(scoop list | Where-Object { $_ -like "$PackageName*" } )) { | |
Write-Host -ForegroundColor Yellow "⏳ Installing $Package..." | |
scoop install $Package | |
} else { | |
Write-Host -ForegroundColor Yellow "⚠️ Package $Package is already installed, attempting to upgrade it, instead." | |
scoop update $Package | |
} | |
} | |
} | |
$exitCode = $LASTEXITCODE | |
if ($exitCode -ne 0) { | |
$exitCode = $LASTEXITCODE | |
if ($exitCode -ne 0) { | |
Write-Host -ForegroundColor Red "❌ Operation failed for $PackageType package: $Package" | |
$failedPackages += $Package | |
continue | |
} | |
} | |
$succeededPackages += $Package | |
refreshenv | |
. $PROFILE | |
} | |
if ($failedPackages.Count -gt 0) { | |
$errorString = "Failed to install $($failedPackages.Count) package(s): " | |
$failedPackages | ForEach-Object { $errorString += $($_ + " ") } | |
Write-Host -ForegroundColor Red "❌ $errorString" | |
return $false | |
} | |
if ($succeededPackages.Count -gt 0) { | |
$successString = "Succeeded installing $($succeededPackages.Count) package(s): " | |
$succeededPackages | ForEach-Object { $successString += $($_ + " ") } | |
Write-Host -ForegroundColor Green "✅ $successString" | |
return $true | |
} | |
} | |
<# | |
.SYNOPSIS | |
This function is able to install various package managers by using PowerShell. | |
.DESCRIPTION | |
This function is able to install various package managers by using PowerShell. It will not install a package manager if it is already installed. Status will be displayed in the terminal, along with a results summary. This function can install Chocolatey, Winget, and Scoop. | |
.PARAMETER PackageManager | |
The package manager to install. Valid values are: choco, winget, scoop | |
.EXAMPLE | |
Install-PackageManager -PackageManager "choco" | |
.NOTES | |
This function does not offer the capability to uninstall package managers, as it is designed around working non-destructively. | |
#> | |
function Install-PackageManager { | |
param ( | |
[ValidateSet("choco", "winget", "scoop", IgnoreCase = $true)] | |
[string]$PackageManager | |
) | |
try { | |
switch ($PackageManager) { | |
"scoop" { | |
if ($null -eq $(Get-Command -Name "scoop" -ErrorAction SilentlyContinue)) { | |
Write-Host -ForegroundColor Yellow "⏳ Scoop is not installed. Installing Scoop..." | |
Start-Process pwsh -Verb RunAs -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command `"& { iwr -useb get.scoop.sh | iex }`"" | |
if ($LASTEXITCODE -ne 0 -or $null -eq $(Get-Command -Name "scoop" -ErrorAction SilentlyContinue)) { | |
throw "Failed to install Scoop." | |
} | |
. $PROFILE | |
} else { | |
Write-Host -ForegroundColor Green "✅ Scoop is installed and ready to be used." | |
return $true | |
} | |
} | |
"choco" { | |
if ($null -eq $(Get-Command -Name "choco" -ErrorAction SilentlyContinue)) { | |
Write-Host -ForegroundColor Yellow "⏳ Chocolatey is not installed. Installing Chocolatey..." | |
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) | |
if ($LASTEXITCODE -ne 0 -or -not $(Test-Path -Path "$env:ChocolateyInstall")) { | |
throw "Failed to install Chocolatey" | |
} | |
Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1 | |
refreshenv | |
. $PROFILE | |
choco feature enable -n allowGlobalConfirmation | |
} else { | |
Write-Host -ForegroundColor Green "✅ Chocolatey is installed, proceeding" | |
Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1 | |
refreshenv | |
. $PROFILE | |
return $true | |
} | |
} | |
"winget" { | |
if ($null -eq $(Get-Command -Name "winget" -ErrorAction SilentlyContinue)) { | |
Write-Host -ForegroundColor Yellow "⏳ Winget is not installed. Installing Winget..." | |
Install-Module -Name Microsoft.WinGet.Client | |
if ($LASTEXITCODE -ne 0 -or $null -eq $(Get-Command -Name "winget" -ErrorAction SilentlyContinue)) { | |
throw "Failed to install Winget, the script will now exit." | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ Winget is installed and ready to be used." | |
return $true | |
} | |
} | |
} | |
} catch { | |
Write-Host -ForegroundColor Red "❌ $($_.Exception.Message)" | |
return $false | |
} | |
} | |
############################################## | |
# VISUAL STUDIO TOOLS | |
############################################## | |
<# | |
.SYNOPSIS | |
Get an available Windows SDK package name from Chocolatey. | |
.DESCRIPTION | |
This function searches Chocolatey for a Windows SDK package name that matches the version specified. It will return the package name if it is found, or null if it is not found. | |
.PARAMETER sdkVersion | |
The version of the Windows SDK to search for. | |
.PARAMETER WinDbg | |
This switch is used to indicate that the Windows SDK package should include WinDbg. | |
.EXAMPLE | |
Get-WindowsSdkPackage -sdkVersion "10.0.18362.0" -WinDbg | |
.NOTES | |
This function is used to get an available Windows SDK package name from Chocolatey. | |
#> | |
function Get-WindowsSdkPackage() { | |
param( | |
[string]$sdkVersion, | |
[switch]$WinDbg | |
) | |
$chocoOutput = choco search windows-sdk | Out-String | |
$versionPattern = [regex]::Escape($sdkVersion) | |
$winDbgPattern = $WinDbg ? "windbg" : "all" | |
$pattern = "(windows-sdk-.*($winDbgPattern)?)\s+($versionPattern)\s+\[Approved\].*" | |
if ($chocoOutput -match $pattern) { | |
$packageName = $matches[1] | |
$packageVersion = $matches[3] | |
Write-Host -ForegroundColor Green "✅ Found package $packageName version $packageVersion" | |
return $packageName | |
} else { | |
Write-Host -ForegroundColor Red "❌ No matching package found for SDK version $sdkVersion" | |
return $null | |
} | |
} | |
<# | |
.SYNOPSIS | |
Find the installation folder of a Windows SDK version. | |
.DESCRIPTION | |
This function searches the registry for a Windows SDK version, and returns the installation folder if it is found, or null if it is not found. | |
.PARAMETER SdkVersion | |
The version of the Windows SDK to search for. | |
.EXAMPLE | |
Find-WindowsSDK -SdkVersion "10.0.18362.0" | |
.NOTES | |
The fnction returns $null if the SDK version is not found. | |
#> | |
function Find-WindowsSDK() { | |
param( | |
[string]$SdkVersion | |
) | |
try { | |
if ($SdkVersion -match "\d+\.\d+\.\d+") { | |
$SdkVersion = $SdkVersion + ".0" | |
} | |
$sdkVersion = [Regex]::Replace($SdkVersion, '(\d+)(?=[^\d]*$)', '0') | |
$SdkVersions = Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" | |
$InstallationRoot = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots").KitsRoot10 | |
foreach ($version in $SdkVersions) { | |
$productVersion = $version.PSChildName | |
if ($productVersion -like "$sdkVersion*") { | |
$installationFolder = $("{0}bin\{1}" -f ($InstallationRoot, $productVersion)) | |
if ((Test-Path $installationFolder)) { | |
Write-Host -ForegroundColor Green "✅ Windows SDK Version found: $productVersion, Installation Folder: $installationFolder, Product Version: $productVersion" | |
return $installationFolder | |
} | |
} | |
} | |
Write-Host -ForegroundColor Red "❌ SDK version $sdkVersion not found." | |
return $null | |
} catch { | |
Write-Host -ForegroundColor Red "❌ SDK version $sdkVersion not found: $($_.Exception.Message)" | |
return $null | |
} | |
} | |
<# | |
.SYNOPSIS | |
Find the installation folder of a Visual Studio version. | |
.DESCRIPTION | |
This function searches the registry for a Visual Studio version, and returns the installation folder if it is found, or null if it is not found. | |
.PARAMETER VsVersion | |
The version of Visual Studio to search for. | |
.EXAMPLE | |
Find-VsInstallPath -VsVersion "16.0" | |
.NOTES | |
The function returns $null if the Visual Studio version is not found. For versions greater than 15.0, the function will use vswhere.exe to find the installation path. | |
#> | |
function Find-VsInstallPath { | |
param( | |
[string]$VsVersion | |
) | |
$regPaths = @( | |
"HKLM:\SOFTWARE\Microsoft\VisualStudio\$VsVersion", | |
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\$VsVersion", | |
"HKLM:\SOFTWARE\Microsoft\VisualStudio\$VsVersion\Setup\VS", | |
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\$VsVersion\Setup\VS" | |
) | |
try { | |
foreach ($regPath in $regPaths) { | |
if (Test-Path $regPath) { | |
$vsInstallPath = (Get-ItemProperty -Path $regPath).InstallDir | |
if ($vsInstallPath) { | |
return $vsInstallPath | |
} | |
} | |
} | |
# For VS 2017 and later | |
if ($VsVersion -ge "15.0") { | |
if (-not (Test-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe")) | |
{ | |
throw "vswhere.exe not found." | |
return $null | |
} | |
$VsVersionLow = $VsVersion -replace "\d+$", "0" | |
$VsVersionHigh = $VsVersion -replace "\d+$", "999" | |
$vswhereOutput = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -version "[${VsVersionLow},${VsVersionHigh}]" -property "installationPath" -nocolor -nologo -format value | |
if ($vswhereOutput) { | |
return $vswhereOutput | |
} | |
throw "vswhere.exe did not return a valid path." | |
} | |
} catch { | |
Write-Host -ForegroundColor Red "❌ Visual Studio $VsVersion not found: $($_.Exception.Message)" | |
return $null | |
} | |
} | |
<# | |
.SYNOPSIS | |
This function installs Visual Studio components using the Visual Studio Installer. | |
.DESCRIPTION | |
This function installs Visual Studio components. It will attempt to install the components, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.PARAMETER components | |
A string array of components to install. | |
.EXAMPLE | |
Install-VSComponents -components @("Microsoft.VisualStudio.Workload.NativeDesktop", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64") | |
.NOTES | |
This function does not offer the capability to uninstall Visual Studio components, as it is designed around working non-destructively. | |
#> | |
function Install-VSComponents { | |
param ( | |
[string[]]$Components | |
) | |
try { | |
$output = "$env:ASE_CACHEPATH\vs_community.exe" | |
if (-not (Test-Path $output)) { | |
Write-Host -ForegroundColor Yellow "⏳ Downloading Visual Studio Installer..." | |
Start-BitsTransfer -Source "http://aka.ms/vs/16/release/vs_community.exe" -Destination $output | |
} else { | |
Write-Host -ForegroundColor Green "✅ Visual Studio Installer download found in cache." | |
} | |
foreach ($component in $Components) { | |
$arguments = @( | |
"--quiet", | |
"--wait", | |
"--norestart", | |
"--nocache", | |
"--installPath `"$env:AES_VISUALSTUDIO`"", | |
"--add $component" | |
) | |
Write-Host -ForegroundColor Yellow "⏳ Installing Visual Studio component $component..." | |
Start-Process -FilePath "$env:ASE_CACHEPATH\vs_community.exe" -ArgumentList $arguments -Wait -NoNewWindow | |
if ($LASTEXITCODE -ne 0) { | |
throw "Visual Studio installation of component $component failed." | |
} | |
Write-Host -ForegroundColor Green "✅ Visual Studio component $component installed." | |
} | |
} catch { | |
Write-Host -ForegroundColor Red "❌ $($_.Exception.Message)" | |
return $false | |
} | |
return $true | |
} | |
############################################## | |
# PYTHON TOOLS | |
############################################## | |
<# | |
.SYNOPSIS | |
This function checks and returns information about a specific installed Python version | |
.DESCRIPTION | |
This function checks and returns information about a specific installed Python version. It will return a hashtable with the following keys: Path, ScriptsPath. If the Python version is not found, it will return $null. | |
.PARAMETER version | |
The version of Python to check for. | |
.EXAMPLE | |
Check-PythonInstallation -version "3.9" | |
#> | |
function Check-Python { | |
param ( | |
[Parameter(Mandatory=$true)] | |
[string]$version | |
) | |
# if the version includes a patch number, strip it off. | |
if ($Version -imatch '^\d+\.\d+\.\d+$') { | |
$SimpleVersion = $Version -replace "\.\d+$", "" | |
} else { | |
$SimpleVersion = $Version | |
} | |
# Check for the existance of the python registry key | |
$sourceKey = $null | |
$keysToSearch = @( | |
"HKLM:\SOFTWARE\WOW6432Node\Python\PythonCore\$SimpleVersion\InstallPath", | |
"HKLM:\SOFTWARE\WOW6432Node\Python\$SimpleVersion\InstallPath", | |
"HKLM:\SOFTWARE\Python\PythonCore\$SimpleVersion\InstallPath", | |
"HKLM:\SOFTWARE\Python\$SimpleVersion\InstallPath" | |
"HKCU:\SOFTWARE\WOW6432Node\Python\PythonCore\$SimpleVersion\InstallPath", | |
"HKCU:\SOFTWARE\WOW6432Node\Python\$SimpleVersion\InstallPath", | |
"HKCU:\SOFTWARE\Python\PythonCore\$SimpleVersion\InstallPath", | |
"HKCU:\SOFTWARE\Python\$SimpleVersion\InstallPath" | |
) | |
$keysToSearch | ForEach-Object { | |
if (Test-Path $_) { | |
$sourceKey = $_ | |
} | |
} | |
if ($null -eq $sourceKey) { | |
Write-Debug "Python $Version registry key not found." | |
return $null | |
} else { | |
Write-Debug "Python $Version registry key found at: $sourceKey" | |
$pythonInstalled = $true | |
} | |
# Check for the existance of the python installation folder and scripts folder. | |
$pythonPath = (Get-ItemProperty -Path "$sourceKey")."(Default)" | |
$pythonScriptsPath = Join-Path -Path $pythonPath -ChildPath "Scripts" | |
$pythonInstalled = ($pythonInstalled -eq $true) -and (Test-Path $pythonPath) -and (Test-Path $pythonScriptsPath) | |
if ($pythonInstalled -eq $true) { | |
Write-Debug "Python $Version installation folder and scripts folder exist." | |
} else { | |
Write-Debug "Python $Version installation folder and scripts folder do not exist." | |
return $null | |
} | |
# Check that the Python binary version matches the one we are testing for | |
$pythonVersion = $(Invoke-Expression "& `"$pythonPath\python.exe`" --version 2>&1") | |
$pythonInstalled = $pythonInstalled -eq $true -and $pythonVersion -like "Python $Version*" | |
if ($pythonInstalled -eq $true) { | |
Write-Debug "Python $Version binary exists and matches." | |
} else { | |
Write-Debug "Python $Version binary does not exist or does not match version $Version." | |
} | |
if ($pythonInstalled) { | |
return [hashtable]@{ | |
"Path" = $pythonPath | |
"ScriptsPath" = $pythonScriptsPath | |
} | |
} else { | |
return $null | |
} | |
} | |
<# | |
.SYNOPSIS | |
This function installs a specific version of Python. | |
.DESCRIPTION | |
This function installs a specific version of Python. It will attempt to install the Python version, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.PARAMETER version | |
The version of Python to install. | |
.EXAMPLE | |
Install-Python -version "3.9" | |
.NOTES | |
#> | |
function Install-Python() { | |
param( | |
[Parameter(Mandatory=$true)] | |
[string]$Version | |
) | |
# Attempt to find a Python installer by using different URLs from python's FTP server. | |
# | |
$installerPath = $null | |
$installerPaths = @( | |
[hashtable]@{ | |
CachePath = "$env:ASE_CACHEPATH\python-$Version-amd64.exe" | |
URL = "https://www.python.org/ftp/python/$Version/python-$Version-amd64.exe" | |
Type = "exe" | |
}, | |
[hashtable]@{ | |
CachePath = "$env:ASE_CACHEPATH\python-$Version-amd64.msi" | |
URL = "https://www.python.org/ftp/python/$Version/python-$Version-amd64.msi" | |
Type = "msi" | |
}, | |
[hashtable]@{ | |
CachePath = "$env:ASE_CACHEPATH\python-$Version.amd64.exe" | |
URL = "https://www.python.org/ftp/python/$Version/python-$Version.amd64.exe" | |
Type = "exe" | |
}, | |
[hashtable]@{ | |
CachePath = "$env:ASE_CACHEPATH\python-$Version.and64.msi" | |
URL = "https://www.python.org/ftp/python/$Version/python-$Version.amd64.msi" | |
Type = "msi" | |
} | |
) | |
foreach ($potentialPath in $installerPaths) { | |
if (Test-Path $potentialPath.CachePath) { | |
$installerPath = $potentialPath | |
Write-Host -ForegroundColor Green "✅ Python $Version installer found in cache at: $($installerPath.CachePath)" | |
break | |
} else { | |
Write-Host -ForegroundColor Yellow "⏳ Trying to download Python $Version installer..." | |
try { | |
Invoke-WebRequest -Uri $potentialPath.URL -OutFile $potentialPath.CachePath | |
$installerPath = $potentialPath | |
Write-Host -ForegroundColor Green "✅ Python $Version installer downloaded to cache at: $($installerPath.CachePath)" | |
break | |
} catch { | |
Write-Host -ForegroundColor Red "❌ Failed to download Python $Version installer: $($_.Exception.Message)" | |
continue | |
} | |
} | |
} | |
if ($null -eq $installerPath) { | |
Write-Host -ForegroundColor Red "❌ Python $Version installer could not be found or downloaded." | |
return $false | |
} | |
# Now we select appropriate command line arguments for the installation to proceed. | |
switch ($installerPath.Type) { | |
"exe" { | |
$command = "$($installerPath.CachePath)" | |
$arguments = @( | |
"/quiet", | |
"InstallAllUsers=1", | |
"PrependPath=1", | |
"Include_test=1" | |
) -join ' ' | |
break | |
} | |
"msi" { | |
$command = "msiexec.exe" | |
$arguments = @( | |
"/i" | |
"`"$($installerPath.CachePath)`"" | |
"/quiet", | |
"InstallAllUsers=1", | |
"PrependPath=1", | |
"Include_test=1" | |
) -join ' ' | |
break | |
} | |
default { | |
Write-Host -ForegroundColor Red "❌ Python $Version installer type is not supported." | |
return $false | |
} | |
} | |
# Run the installer, if this fails, return false. | |
Write-Host -ForegroundColor Yellow "⏳ Installing Python $Version..." | |
Start-Process -FilePath $command -ArgumentList $arguments -Wait -NoNewWindow | |
if ($LASTEXITCODE -ne 0) { | |
Write-Host -ForegroundColor Red "❌ Python $Version installation failed." | |
return $false | |
} else { | |
Write-Host -ForegroundColor Green "✅ Python $Version installed." | |
return $true | |
} | |
} | |
<# | |
.SYNOPSIS | |
This function sets the Python version to use for the build environment. | |
.DESCRIPTION | |
This function sets the Python version to use for the build environment. It will attempt to set the Python version, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.PARAMETER version | |
The version of Python to use. | |
.EXAMPLE | |
Set-PythonVersion -version "3.9" | |
.NOTES | |
None | |
#> | |
function Set-Python { | |
param ( | |
[string]$Version, | |
[switch]$Install | |
) | |
# Check if the Python version is installed. If we have the -Install switch, then install it | |
# automatically if it is not installed. | |
$pythonInfo = Check-Python -version $Version | |
if ($null -eq $pythonInfo) { | |
$env:ASE_PYTHONPATH = $null | |
if (-not $Install) { | |
Write-Host -ForegroundColor Red "❌ Could not select Python $Version" | |
return $null | |
} | |
$result = Install-Python -version $Version | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "❌ Python $Version could not be automatically installed." | |
return $null | |
} | |
} | |
# Check that the python version is installed properly. | |
$pythonInfo = Check-Python -version $Version | |
if ($null -eq $pythonInfo) { | |
Write-Host -ForegroundColor Red "❌ Could not select Python $Version" | |
return $null | |
} | |
# Set the environment variables, and update the script path. | |
$currentPath = $env:Path | |
$existingPythonPaths = $currentPath -split ";" | Where-Object { $_ -match "C:\\Python[0-9.]*" } | |
Mod-Path -Remove $existingPythonPaths -Add @($pythonInfo.Path, $pythonInfo.ScriptsPath) | |
$env:ASE_PYTHONPATH = $pythonInfo.Path | |
Write-Host -ForegroundColor Green "✅ Selected Python $Version." | |
return $pythonInfo | |
} | |
############################################## | |
# BUILD TOOLS | |
############################################## | |
<# | |
.SYNOPSIS | |
This function is used to enter or leave the Visual Studio development environment. | |
.DESCRIPTION | |
This function is used to enter or leave the Visual Studio development environment. It will attempt to enter or leave the environment, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.PARAMETER Action | |
The action to perform. Valid values are: enter, leave | |
.PARAMETER Compiler | |
The compiler to use. Valid values are: msvc, clang | |
.EXAMPLE | |
Toggle-DevelopmentEnvironment -Action "Enter" | |
.NOTES | |
None | |
#> | |
function Toggle-DevelopmentEnvironment { | |
param ( | |
[Parameter(Mandatory=$true)] | |
[ValidateSet("enter", "leave", IgnoreCase = $true)] | |
[string]$Action, | |
[Parameter(Mandatory=$true)] | |
[ValidateSet("msvc", "vsclang", "blaseclang", IgnoreCase = $true)] | |
[string]$Compiler | |
) | |
switch ($Action.ToLower()) { | |
"enter" { | |
try { | |
Import-Module (Get-ChildItem "$env:ASE_VISUALSTUDIOPATH" -Recurse -File -Filter Microsoft.VisualStudio.DevShell.dll).FullName | |
$devCmdArguments = '-no_logo' | |
$devCmdArguments += ' -arch=x64' | |
Enter-VsDevShell -VsInstallPath "$env:ASE_VISUALSTUDIOPATH" -SkipAutomaticLocation -DevCmdArguments $devCmdArguments | |
if ($Compiler.ToLower() -eq "msvc") { | |
$env:CC = "cl.exe" | |
$env:CXX = "cl.exe" | |
$env:CMAKE_C_COMPILER = "cl.exe" | |
$env:CMAKE_CXX_COMPILER = "cl.exe" | |
} elseif ($Compiler.ToLower() -eq "vsclang") { | |
$env:CC = "clang-cl.exe" | |
$env:CXX = "clang-cl.exe" | |
$env:CMAKE_C_COMPILER = "clang-cl.exe" | |
$env:CMAKE_CXX_COMPILER = "clang-cl.exe" | |
} elseif ($Compiler.ToLower() -eq "blaseclang") { | |
$env:CC = "$env:ASE_LLVMROOT\bin\clang-cl.exe" | |
$env:CXX = "$env:ASE_LLVMROOT\bin\clang-cl.exe" | |
$env:CMAKE_C_COMPILER = "$env:ASE_LLVMROOT\bin\clang-cl.exe" | |
$env:CMAKE_CXX_COMPILER = "$env:ASE_LLVMROOT\bin\clang-cl.exe" | |
} | |
return $true | |
} catch { | |
Write-Host -ForegroundColor Red "❌ $($_.Exception.Message)" | |
return $false | |
} | |
} | |
"leave" { | |
try { | |
Remove-Module Microsoft.VisualStudio.DevShell | |
$env:CC = $null | |
$env:CXX = $null | |
$env:CMAKE_C_COMPILER = $null | |
$env:CMAKE_CXX_COMPILER = $null | |
return $true | |
} catch { | |
Write-Host -ForegroundColor Red "❌ $($_.Exception.Message)" | |
return $false | |
} | |
} | |
} | |
} | |
<# | |
.SYNOPSIS | |
Modifies the PATH environment variable. | |
.DESCRIPTION | |
This function is used to modify the PATH environment variable. It will attempt to modify the PATH, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.PARAMETER Add | |
A string array of paths to add to the PATH environment variable. | |
.PARAMETER Remove | |
A string array of paths to remove from the PATH environment variable. | |
.EXAMPLE | |
Mod-Path -Add @("C:\Program Files\Git\bin", "C:\Program Files\Git\cmd") -Remove @("C:\Program Files\Git\bin", "C:\Program Files\Git\cmd") | |
.NOTES | |
Doesn't do any error checking, so be careful with it. | |
#> | |
function Mod-Path() { | |
param( | |
[string[]]$Add, | |
[string[]]$Remove, | |
[switch]$WhatIf | |
) | |
if ($null -eq $Add) { | |
$Add = @() | |
} | |
if ($null -eq $Remove) { | |
$Remove = @() | |
} | |
$path = $env:Path | |
$pathElements = $path.Split(";") | |
$pathElements = $pathElements | Where-Object { $_ -notin $Remove -and $(Test-Path $_)} | Sort-Object | |
$pathElements = $pathElements + $($Add | Where-Object { $(Test-Path $_) -and ($_ -notin $pathElements) }) | |
$newPath = $pathElements -join ";" | |
if ($WhatIf) { | |
Write-Host -ForegroundColor Yellow "🪳 WHATIF: Modifying PATH environment variable from:`m $path`n to:`n $newPath" | |
} | |
else { | |
$env:Path = $newPath | |
} | |
Write-Debug $env:Path | |
} | |
<# | |
.SYNOPSIS | |
This function is a wrapper around git clone, and is used to clone a repository. | |
.DESCRIPTION | |
This function is a wrapper around git clone, and is used to clone a repository. It will attempt to clone the repository, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.PARAMETER RepoUrl | |
The URL of the repository to clone. | |
.PARAMETER Tag | |
The tag to checkout after cloning the repository (optional) | |
.PARAMETER Branch | |
The branch to checkout after cloning the repository (optional) | |
.PARAMETER CommitHash | |
The commit hash to checkout after cloning the repository (optional) | |
.PARAMETER DeleteExisting | |
This switch is used to indicate that the existing repository should be deleted before cloning. | |
.PARAMETER OutputPath | |
The path to clone the repository to. | |
.PARAMETER Username | |
The username to use for the git clone operation (optional) | |
.PARAMETER Email | |
The email to use for the git clone operation (optional) | |
.PARAMETER CloneDepth | |
The depth to use for the git clone operation (optional) | |
.EXAMPLE | |
Invoke-GitClone -RepoUrl "https://loopyd.github.com/aseprite_build.git -Tag "v1.2.40" -OutputPath "C:\aseprite_build" | |
.NOTES | |
This code isn't optimized. I'm having ChatGFPT generate some things for | |
me because its the weekend and I have to work tomorrow. I will probably | |
go back in and give it a touch up at a later date. | |
#> | |
function Invoke-GitClone { | |
param ( | |
[Parameter(Mandatory = $true)][string]$RepoUrl, | |
[Parameter(Mandatory = $false)][string]$Tag, | |
[Parameter(Mandatory = $false)][string]$Branch, | |
[Parameter(Mandatory = $false)][string]$CommitHash, | |
[Parameter(Mandatory = $false)][switch]$DeleteExisting, | |
[Parameter(Mandatory = $false)][string]$OutputPath = "./", | |
[Parameter(Mandatory = $false)][string]$Username, | |
[Parameter(Mandatory = $false)][string]$Email, | |
[Parameter(Mandatory = $false)][int]$CloneDepth | |
) | |
try { | |
# Check if repository already exists at the output path | |
if ($DeleteExisting -and (Test-Path $OutputPath)) { | |
Write-Host -ForegroundColor Yellow "⏳ Deleting existing repository at $OutputPath..." | |
Remove-Item -Path $OutputPath -Recurse -Force | Out-Null | |
if (Test-Path $OutputPath) { | |
throw "Failed to delete existing repository at $OutputPath" | |
} | |
} | |
elseif ($CleanExisting -and (Test-Path $OutputPath)) { | |
Write-Host -ForegroundColor Yellow "⏳ Cleaning existing repository at $OutputPath..." | |
$CurrentDirectory = Get-Location | |
Set-Location -Path $OutputPath | |
$arguments = @( | |
"reset", | |
"--hard" | |
) | |
$lec = $(Roar -Command "$env:ASE_GITPATH\bin\git.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
Set-Location -Path $CurrentDirectory | |
throw "Failed to clean existing repository at $OutputPath" | |
} | |
$arguments = @( | |
"clean", | |
"-fd" | |
) | |
$lec = $(Roar -Command "$env:ASE_GITPATH\bin\git.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
Set-Location -Path $CurrentDirectory | |
throw "Failed to clean existing repository at $OutputPath" | |
} | |
Set-Location -Path $CurrentDirectory | |
} | |
if (-not $CleanExisting) { | |
# Build the git clone command | |
$gitArgs = @( | |
"clone", | |
"--progress", | |
"--recurse-submodules", | |
"--config core.autocrlf=false" | |
) | |
if ($CloneDepth) { | |
$gitArgs += "--depth", "$CloneDepth" | |
} | |
$gitArgs += "$RepoUrl", "." | |
# Execute git clone | |
Write-Host -ForegroundColor Yellow "⏳ Cloning repository $RepoUrl to $OutputPath..." | |
New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null | |
$CurrentDirectory = Get-Location | |
Set-Location -Path $OutputPath | |
$lec = $(Roar -Command "$env:ASE_GITPATH\bin\git.exe" -Arguments $gitArgs) | |
if ($lec -ne 0) { | |
throw "Failed to clone repository $RepoUrl to $OutputPath" | |
} | |
Set-Location -Path $CurrentDirectory | |
} | |
# Configure user credentials if provided | |
if ($Username -and $Email) { | |
Write-Host -ForegroundColor Yellow "⏳ Configuring git user credentials..." | |
$CurrentDirectory = Get-Location | |
Set-Location -Path $OutputPath | |
$arguments = @( | |
"config", | |
"--local", | |
"user.name", | |
$Username | |
) | |
$lec = $(Roar -Command "$env:ASE_GITPATH\bin\git.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
Set-Location -Path $CurrentDirectory | |
throw "Failed to configure git user credentials." | |
} | |
$arguments = @( | |
"config", | |
"--local", | |
"user.email", | |
) | |
$lec = $(Roar -Command "$env:ASE_GITPATH\bin\git.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
Set-Location -Path $CurrentDirectory | |
throw "Failed to configure git user credentials." | |
} | |
Set-Location -Path $CurrentDirectory | |
Write-Host -ForegroundColor Green "✅ Configured git user credentials." | |
} | |
# Checkout the specified tag, branch, or commit hash | |
if ($Tag) { | |
Write-Host -ForegroundColor Yellow "⏳ Checking out tag $Tag..." | |
$CurrentDirectory = Get-Location | |
Set-Location -Path $OutputPath | |
$arguments = @( | |
"checkout", | |
"tags/$Tag" | |
) | |
$lec = $(Roar -Command "$env:ASE_GITPATH\bin\git.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
Set-Location -Path $CurrentDirectory | |
throw "Failed to checkout tag $Tag" | |
} | |
Set-Location -Path $CurrentDirectory | |
Write-Host -ForegroundColor Green "✅ Checked out tag $Tag." | |
} | |
elseif ($Branch) { | |
Write-Host -ForegroundColor Yellow "⏳ Checking out branch $Branch..." | |
$CurrentDirectory = Get-Location | |
Set-Location -Path $OutputPath | |
$arguments = @( | |
"checkout", | |
$Branch | |
) | |
$lec = $(Roar -Command "$env:ASE_GITPATH\bin\git.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
Set-Location -Path $CurrentDirectory | |
throw "Failed to checkout branch $Branch" | |
} | |
Set-Location -Path $CurrentDirectory | |
Write-Host -ForegroundColor Green "✅ Checked out branch $Branch." | |
} | |
elseif ($CommitHash) { | |
Write-Host -ForegroundColor Yellow "⏳ Checking out commit hash $CommitHash..." | |
$CurrentDirectory = Get-Location | |
Set-Location -Path $OutputPath | |
$arguments = @( | |
"checkout", | |
$CommitHash | |
) | |
$lec = $(Roar -Command "$env:ASE_GITPATH\git.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
Set-Location -Path $CurrentDirectory | |
throw "Failed to checkout commit hash $CommitHash" | |
} | |
Set-Location -Path $CurrentDirectory | |
Write-Host -ForegroundColor Green "✅ Checked out commit hash $CommitHash." | |
} | |
return $true | |
} catch { | |
Write-Host "Error: $_" | |
throw | |
return $false | |
} | |
} | |
<# | |
.SYNOPSIS | |
This function creates a build artifact from a source directory. | |
.DESCRIPTION | |
This function creates a build artifact from a source directory. It will attempt to create the artifact, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.PARAMETER Version | |
The version of the artifact. | |
.PARAMETER Release | |
The release type of the artifact. | |
.PARAMETER Name | |
The name of the artifact. | |
.PARAMETER Include | |
The file types to include in the artifact as an array of glob patterns. | |
.PARAMETER Exclude | |
The file types to exclude from the artifact as an array of glob patterns. | |
.PARAMETER SourcePath | |
The path to the source directory. | |
.PARAMETER OutputPath | |
The path to the output directory. | |
.PARAMETER DeleteAfterComplete | |
If the switch is enabled, the source directory will be deleted after the artifact is created. | |
.PARAMETER DeleteExisting | |
If the switch is enabled, the existing artifact will be deleted before the new artifact is created. | |
.EXAMPLE | |
Make-Artifact -Version "1.2.3" -Release "1" -Name "MyArtifact" -Include @("*.dll", "*.exe") -Exclude @("*.pdb") -SourcePath "C:\MySource" -OutputPath "C:\MyOutput" -DeleteAfterComplete -DeleteExisting | |
.NOTES | |
Returns the path to the artifact if successful, otherwise returns null. | |
#> | |
function Emit-Artifact() { | |
param( | |
[Parameter(Mandatory = $true)][String]$Version, | |
[Parameter(Mandatory = $true)][String]$Release, | |
[Parameter(Mandatory = $true)][String]$Name, | |
[Parameter(Mandatory = $false)][String[]]$Include, | |
[Parameter(Mandatory = $false)][String[]]$Exclude, | |
[Parameter(Mandatory = $true)][String]$SourcePath, | |
[Parameter(Mandatory = $true)][String]$OutputPath, | |
[Parameter(Mandatory = $false)][switch]$DeleteAfterComplete, | |
[Parameter(Mandatory = $false)][switch]$DeleteExisting | |
) | |
if ($(Test-Path -Path "$OutputPath\$Name-$Version-$Release.zip") -eq $true -and -not $DeleteExisting) { | |
Write-Host -ForegroundColor Green "✅ Artifact already exists, nothing to do for: $OutputPath\$Name-$Version-$Release.zip" | |
return "$OutputPath\$Name-$Version-$Release.zip" | |
} | |
try { | |
# Produce a list of build artifacts to target based upon the include and exclude parameters | |
Write-Host -ForegroundColor Yellow "⏳ Validating build..." | |
$validFiles = @() | |
foreach ($item in $(Get-ChildItem -Path $SourcePath -Recurse -Force -ErrorAction SilentlyContinue)) { | |
# skip directories | |
if ($item.PSIsContainer) { | |
continue | |
} | |
# skip excluded files | |
$matchesString = $false | |
foreach ($excludeItem in $Exclude) { | |
if ($item.FullName -match $excludeItem) { | |
$matchesString = $true | |
} | |
} | |
if ($matchesString -eq $true) { | |
continue | |
} | |
# skip not included files | |
$matchesString = $false | |
foreach ($includeItem in $Include) { | |
if (-not ($item.FullName -match $includeItem)) { | |
$matchesString = $true | |
} | |
} | |
if ($matchesString -eq $true) { | |
continue | |
} | |
if (-not (Test-Path $item.FullName)) { | |
throw "Validation failed: File not found: $($item.FullName)" | |
} | |
$validFiles += $($item.FullName -replace [regex]::Escape($SourcePath), "") | |
} | |
# Delete existing build artifact if the switch is enabled | |
if ($DeleteExisting) { | |
Write-Host -ForegroundColor Yellow "⏳ Deleting existing artifact..." | |
Remove-Item -Path "$OutputPath\$Name-$Version-$Release.zip" -Force -ErrorAction SilentlyContinue | |
if ($LASTEXITCODE -ne 0) { | |
throw "Failed to delete existing artifact: $OutputPath\$Name-$Version-$Release.zip" | |
} | |
Write-Host -ForegroundColor Green "✅ Existing artifact deleted successfully." | |
} | |
# Append valid files to the artifact | |
try { | |
$currentDirectory = Get-Location | |
Set-Location -Path $SourcePath | |
foreach ($file in $validFiles) { | |
Write-Host -ForegroundColor Yellow "⏳ Adding file to build artifact: $file" | |
& "$env:ASE_ZIPPATH\7z.exe" a -tzip "$OutputPath\$Name-$Version-$Release.zip" $file 2>&1 | Out-Null | |
if ($LASTEXITCODE -ne 0) { | |
throw "Failed to add file to artifact: $file" | |
} | |
Write-Host -ForegroundColor Green "✅ File added to build artifact: $file" | |
} | |
Set-Location -Path $currentDirectory | |
} catch { | |
throw "$_.Exception.Message" | |
} | |
# Delete the source files if the switch is enabled | |
if ($DeleteAfterComplete) { | |
Write-Host -ForegroundColor Yellow "⏳ Deleting source: $SourcePath" | |
Remove-Item -Recurse -Force -Path $SourcePath | Out-Null | |
if ($LASTEXITCODE -ne 0) { | |
throw "Failed to delete source: $SourcePath" | |
} | |
Write-Host -ForegroundColor Green "✅ Source deleted successfully." | |
} | |
Write-Host -ForegroundColor Green "✅ Artifact: $OutputPath\$Name-$Version-$Release.zip emmited successfully." | |
return "$OutputPath\$Name-$Version-$Release.zip" | |
} | |
catch { | |
Set-Location -Path $SourcePath | |
Write-Host -ForegroundColor Red "❌ Failed: $($_.Exception.Message)" | |
return $null | |
} | |
} | |
<# | |
.SYNOPSIS | |
This function ensures the existance of a dependency on the host system. | |
.DESCRIPTION | |
This function checks for a dependency and sets the environment variable for it. It will attempt to call its sister function Install-Dependency if the dependency is not found, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.PARAMETER DependencyName | |
The dependency to check for. Valid values are: 7zip, windowssdk, visualstudio, llvm, ninja, cmake, cache, skia, asesprite, git, depot_tools, python2 | |
.PARAMETER PostOperation | |
This switch is used to indicate that the function should perform a post-operation check. This is used to ensure that the dependency was installed correctly. | |
.EXAMPLE | |
CheckDependency -DependencyName "7zip" | |
.NOTES | |
Simple wrapper around Install-Dependency, which is used to ensure the existance of a dependency on the host system. | |
#> | |
function Check-Dependency { | |
param ( | |
[ValidateSet("7zip", "windowssdk", "visualstudio", "llvm", "ninja", "cmake", "cache", "skia", "asesprite", "git", "depot_tools", "python", IgnoreCase = $true)] | |
[string]$DependencyName, | |
[switch]$PostOperation | |
) | |
try { | |
switch ($DependencyName.ToLower()) { | |
"7zip" { | |
$zipRegistryPath = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip' -ErrorAction SilentlyContinue | |
if ($zipRegistryPath -and (Test-Path $zipRegistryPath.InstallLocation)) { | |
$env:ASE_ZIPPATH = $zipRegistryPath.InstallLocation | |
Write-Host -ForegroundColor Green "✅ 7-Zip was found at: $env:ASE_ZIPPATH" | |
} else { | |
throw "7-Zip not found in the registry or its installation path is invalid." | |
} | |
return $true | |
} | |
"windowssdk" { | |
$windowsSdk = Find-WindowsSDK -SdkVersion $WindowsSdkVersion | |
if ($windowsSdk -eq $null) { | |
throw "Windows SDK not found." | |
} | |
$env:ASE_WINDOWSSDK = $windowsSdk | |
return $true | |
} | |
"visualstudio" { | |
$vsInstallPath = Find-VsInstallPath -VsVersion $env:ASE_VISUALSTUDIOVERSION | |
if ($vsInstallPath -eq $null) { | |
throw "Visual Studio $env:ASE_VISUALSTUDIOVERSION not found." | |
} | |
$env:ASE_VISUALSTUDIOPATH = $vsInstallPath | |
return $true | |
} | |
'llvm' { | |
if (-not (Test-Path "$env:ASE_LLVMPATH")) { | |
throw "LLVM source code not found." | |
} | |
Write-Host -ForegroundColor Green "✅ LLVM source code found at $env:ASE_LLVMPATH" | |
return $true | |
} | |
'ninja' { | |
if (-not (Test-Path "$env:ASE_NINJAPATH")) { | |
throw "Ninja source code not found." | |
} | |
Write-Host -ForegroundColor Green "✅ Ninja source code found at $env:ASE_NINJAPATH" | |
return $true | |
} | |
'cmake' { | |
if (-not (Test-Path "$env:ASE_CMAKEPATH") -or -not (Test-Path "$env:ASE_CMAKEPATH\bin\cmake.exe")) { | |
throw "Cmake installation not found." | |
} | |
Write-Host -ForegroundColor Green "✅ CMake was found at $env:ASE_CMAKEPATH" | |
return $true | |
} | |
'cache' { | |
if (-not (Test-Path $env:ASE_CACHEPATH)) { | |
throw "Cache path not found." | |
} else { | |
Write-Host -ForegroundColor Green "✅ Cache path found at $env:ASE_CACHEPATH" | |
if ($env:ASE_CACHECLEAN -eq $true) { | |
Write-Host -ForegroundColor Yellow "⏳ Cleaning cache..." | |
Remove-Item -Path $env:ASE_CACHEPATH -Recurse -Force | Out-Null | |
New-Item -Path $env:ASE_CACHEPATH -ItemType Directory | Out-Null | |
Write-Host -ForegroundColor Green "✅ Cache cleaned up." | |
} | |
} | |
return $true | |
} | |
"git" { | |
if (-not (Test-Path $env:ASE_GITPATH) -or -not (Test-Path "$env:ASE_GITPATH\bin\git.exe")) { | |
throw "Git not found." | |
} | |
Write-Host -ForegroundColor Green "✅ Git was found at $env:ASE_GITPATH" | |
return $true | |
} | |
"python" { | |
$versions = @( | |
"3.6.1" | |
"3.11.6" | |
"2.7.18" | |
) | |
$result = $true | |
$versions | ForEach-Object { | |
$pythonInfo = Check-Python -version $_ | |
if ($pythonInfo) { | |
Write-Host -ForegroundColor Green "✅ Python $_ was found at $($pythonInfo.Path)" | |
$result = $result -and $true | |
} else { | |
Write-Host -ForegroundColor Red "❌ Python $_ was not found." | |
$result = $result -and $false | |
} | |
} | |
if ($result -eq $false) { | |
throw "Python version requirements not met." | |
} | |
} | |
"depot_tools" { | |
if (-not (Test-Path $env:ASE_DEPOTTOOLSPATH)) { | |
throw "Google Depot Tools not found." | |
} | |
Write-Host -ForegroundColor Green "✅ Google Depot Tools was found at $env:ASE_DEPOTTOOLSPATH" | |
return $true | |
} | |
"skia" { | |
if (-not (Test-Path $env:ASE_SKIAPATH)) { | |
throw "Skia source code not found" | |
} | |
Write-Host -ForegroundColor Green "✅ Skia was found at $env:ASE_SKIAPATH" | |
return $true | |
} | |
"asesprite" { | |
if (-not (Test-Path $env:ASE_ASESPRITEPATH)) { | |
throw "Aseprite source code not found." | |
} | |
Write-Host -ForegroundColor Green "✅ Aseprite was found at $env:ASE_ASESPRITEPATH" | |
return $true | |
} | |
} | |
} catch { | |
Write-Host -ForegroundColor Red "❌ $($_.Exception.Message)" | |
if ($PostOperation) { | |
Write-Host -ForegroundColor Red "❌ Post-operation dependency check failed." | |
return $false | |
} | |
$result = $(Install-Dependency -DependencyName $DependencyName) | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "❌ Dependency installation failed." | |
return $false | |
} | |
$result = Check-Dependency -DependencyName $DependencyName -PostOperation | |
return $result | |
} | |
} | |
<# | |
.SYNOPSIS | |
This function installs a dependency on the host system. | |
.DESCRIPTION | |
This function installs a dependency on the host system. It will attempt to install the dependency, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.PARAMETER DependencyName | |
The dependency to install. Valid values are: 7zip, windowssdk, visualstudio, llvm, ninja, cmake, cache, skia, asesprite, git, depot_tools, python | |
.EXAMPLE | |
Install-Dependency -DependencyName "7zip" | |
#> | |
function Install-Dependency() { | |
param( | |
[ValidateSet("7zip", "windowssdk", "visualstudio", "llvm", "ninja", "cmake", "cache", "skia", "asesprite", "git", "depot_tools", "python", IgnoreCase = $true)] | |
[string]$DependencyName | |
) | |
try { | |
switch ($DependencyName) { | |
"7zip" { | |
Write-Host -ForegroundColor Yellow "⏳ Installing 7-Zip..." | |
$packageName = "7zip" | |
$result = $(Install-Packages -Packages @($packageName) -PackageType "choco") | |
if ($result -eq $false) { | |
throw "7-Zip installation failed." | |
} | |
return $true | |
} | |
"windowssdk" { | |
Write-Host -ForegroundColor Yellow "⏳ Installing Windows SDK..." | |
$packageName = Get-WindowsSdkPackage -sdkVersion $WindowsSdkVersion -WinDbg | |
if ($null -eq $packageName) { | |
throw "Windows SDK package not found." | |
} | |
$result = $(Install-Packages -Packages @($packageName) -PackageType "choco") | |
if ($result -eq $false) { | |
throw "Windows SDK installation failed." | |
} | |
return $true | |
} | |
"visualstudio" { | |
$result = Install-VSComponents -Components @( | |
"Microsoft.VisualStudio.Workload.NativeDesktop", | |
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64", | |
"Microsoft.VisualStudio.Component.VC.ATL", | |
"Microsoft.VisualStudio.Component.VC.CLI.Support", | |
"Microsoft.VisualStudio.Component.VC.Redist.14.Latest", | |
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Win81", | |
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Win10", | |
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.MSBuild", | |
"Microsoft.VisualStudio.Component.VC.ATLMFC" | |
) | |
if ($result -eq $false) { | |
throw "Visual Studio installation failed." | |
} | |
} | |
"cmake" { | |
if (-not $(Test-Path "$env:ASE_CACHEPATH\cmake.zip")) { | |
Write-Host -ForegroundColor Yellow "⏳ Downloading CMake..." | |
try { | |
Start-BitsTransfer -Source "https://github.com/Kitware/CMake/releases/download/v$env:ASE_CMAKEVERSION/cmake-$env:ASE_CMAKEVERSION-windows-x86_64.zip" -Destination "$env:ASE_CACHEPATH\cmake.zip" | |
} catch { | |
throw "Failed to download CMake." | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ CMake found in cache." | |
} | |
if (-not $(Test-Path "$env:ASE_CMAKEPATH")) { | |
Write-Host -ForegroundColor Yellow "⏳ Unzipping CMake..." | |
try { | |
$arguments = @( | |
"x", | |
"$env:ASE_CACHEPATH\cmake.zip", | |
"-o$env:ASE_CMAKEPATH" | |
) -join " " | |
Invoke-Expression "& `"$env:ASE_ZIPPATH\7z.exe`" $arguments" | |
if ($LASTEXITCODE -ne 0) { | |
throw "Failed to run 7-Zip to unzip CMake." | |
} | |
Move-Item -Path "$env:ASE_CMAKEPATH\cmake-$env:ASE_CMAKEVERSION-windows-x86_64\*" -Destination "$env:ASE_CMAKEPATH" -Force | |
Remove-Item -Path "$env:ASE_CMAKEPATH\cmake-$env:ASE_CMAKEVERSION-windows-x86_64" -Recurse -Force | |
if (-not $(Test-Path "$env:ASE_CMAKEPATH\bin\cmake.exe")) { | |
throw "Failed to unzip CMake." | |
} | |
} catch { | |
throw "Failed to unzip CMake." | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ CMake found at $env:ASE_CMAKEPATH" | |
} | |
return $true | |
} | |
"llvm" { | |
# Clone llvm | |
if (-not (Test-Path $env:ASE_LLVMPATH)) { | |
try { | |
$result = Invoke-GitClone -RepoUrl "https://github.com/llvm/llvm-project.git" -Tag "llvmorg-$env:ASE_LLVMVERSION" -OutputPath $env:ASE_LLVMPATH | |
if ($result -eq $false) { | |
throw "Failed to clone LLVM." | |
} | |
Write-Host -ForegroundColor Green "✅ LLVM cloned successfully." | |
return $true | |
} catch { | |
throw "$_.Exception.Message" | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ LLVM source code found at $env:ASE_LLVMPATH" | |
return $true | |
} | |
} | |
"ninja" { | |
if (-not $(Test-Path $env:ASE_NINJAPATH) ) { | |
try { | |
$result = Invoke-GitClone -RepoUrl "https://github.com/ninja-build/ninja.git" -OutputPath $env:ASE_NINJAPATH -Branch release | |
if ($result -eq $false) { | |
throw "Failed to clone Ninja." | |
} | |
} catch { | |
throw "$_.Exception.Message" | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ Ninja source code found at $env:ASE_NINJAPATH" | |
return $true | |
} | |
} | |
"cache" { | |
Write-Host -ForegroundColor Yellow "⏳ Creating cache folder..." | |
New-Item -ItemType Directory -Path $env:ASE_CACHEPATH | |
return $true | |
} | |
"git" { | |
if (-not $(Test-Path "$env:ASE_CACHEPATH\git.exe")) { | |
Write-Host -ForegroundColor Yellow "⏳ Downloading Git..." | |
try { | |
Start-BitsTransfer -Source "https://github.com/git-for-windows/git/releases/download/v$env:ASE_GITVERSION.windows.$env:ASE_GITSUBVERSION/PortableGit-$env:ASE_GITVERSION.$env:ASE_GITSUBVERSION-64-bit.7z.exe" -Destination "$env:ASE_CACHEPATH\git.exe" | |
if ($LASTEXITCODE -ne 0) { | |
throw "Failed to download Git." | |
} | |
} catch { | |
throw "$($_.Exception.Message)" | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ Git zip found in cache." | |
} | |
if (-not $(Test-Path "$env:ASE_GITPATH") -or -not $(Test-Path "$env:ASE_GITPATH\bin\git.exe")) { | |
Write-Host -ForegroundColor Yellow "⏳ Unzipping Git..." | |
try { | |
$arguments = @( | |
"x", | |
"$env:ASE_CACHEPATH\git.exe", | |
"-o$env:ASE_GITPATH" | |
) -join " " | |
Invoke-Expression "& `"$env:ASE_ZIPPATH\7z.exe`" $arguments" | |
if ($LASTEXITCODE -ne 0) { | |
throw "Failed to run 7-Zip to unzip Git." | |
} | |
if (-not $(Test-Path "$env:ASE_GITPATH\bin\git.exe")) { | |
throw "Failed to unzip Git." | |
} | |
} catch { | |
throw "Failed to unzip Git." | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ Git found at $env:ASE_GITPATH" | |
} | |
} | |
"python" { | |
Write-Host -ForegroundColor Yellow "⏳ Installing Python versions..." | |
$versions = @( | |
"3.6.1" | |
"3.11.6" | |
"2.7.18" | |
) | |
$versions | ForEach-Object { | |
$result = Check-Python -version $_ | |
if ($result) { | |
Write-Host -ForegroundColor Green "✅ Python $_ was found at $($result.Path)" | |
} else { | |
Write-Host -ForegroundColor Yellow "⏳ Installing Python $_..." | |
$result = Install-Python -Version $_ | |
if ($result -eq $false) { | |
throw "Python $_ installation failed." | |
} | |
} | |
} | |
return $true | |
} | |
"depot_tools" { | |
if (-not (Test-Path $env:ASE_DEPOTTOOLSPATH)) { | |
Write-Host -ForegroundColor Yellow "⌛ Google Depot Tools folder was not found." | |
try { | |
New-Item -ItemType Directory -Path $env:ASE_DEPOTTOOLSPATH -Force -ErrorAction SilentlyContinue | |
Write-Host -ForegroundColor Green "✅ Google Depot Tools folder created: $env:ASE_DEPOTTOOLSPATH" | |
} catch { | |
throw "Failed to create Google Depot Tools folder." | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ Google Depot Tools folder found: $env:ASE_DEPOTTOOLSPATH" | |
} | |
if (-not (Test-Path "$env:ASE_DEPOTTOOLSPATH\gclient.bat")) { | |
Write-Host -ForegroundColor Yellow "⌛ Clone Google Depot Tools from GitHub..." | |
try { | |
$result = Invoke-GitClone -RepoUrl 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' -OutputPath $env:ASE_DEPOTTOOLSPATH | |
if ($result -eq $false) { | |
throw "Failed to clone Google Depot Tools." | |
} | |
Write-Host -ForegroundColor Green "✅ Google Depot Tools cloned to: $env:ASE_DEPOTTOOLSPATH" | |
} catch { | |
throw "Failed to clone Google Depot Tools." | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ Google Depot Tools path found in cache." | |
} | |
return $true | |
} | |
"skia" { | |
if ($env:SKIAUSEPREBUILT -eq $true) { | |
# Using the prebuilt Skia library | |
if (-not (Test-Path "$env:ASE_CACHEPATH\skia.zip")) { | |
Write-Host -ForegroundColor Yellow "⏳ Downloading Skia..." | |
try { | |
Start-BitsTransfer -Source $env:ASE_SKIAURL -Destination "$env:ASE_CACHEPATH\skia.zip" | |
} catch { | |
throw "Failed to download Skia." | |
} | |
} else { | |
Write-Host "✅ Skia download found in cache." | |
} | |
if (-not (Test-Path $env:ASE_SKIAPATH)) { | |
Write-Host -ForegroundColor Yellow "⌛ Skia folder was not found, unzipping archive..." | |
try { | |
New-Item -ItemType Directory -Path $env:ASE_SKIAPATH -Force -ErrorAction SilentlyContinue | |
& "$env:ASE_ZIPPATH\7z.exe" x "$env:ASE_CACHEPATH\skia.zip" -o"$env:ASE_SKIAPATH" | |
Write-Host -ForegroundColor Green "✅ Skia unzipped to: $env:ASE_SKIAPATH" | |
} catch { | |
throw "Failed to unzip Skia." | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ Skia path found in cache." | |
} | |
} else { | |
if (-not (Test-Path $env:ASE_SKIAPATH)) { | |
Write-Host -ForegroundColor Yellow "⌛ Skia folder was not found, creating folder..." | |
try { | |
New-Item -ItemType Directory -Path $env:ASE_SKIAPATH -Force -ErrorAction SilentlyContinue | |
Write-Host -ForegroundColor Green "✅ Skia folder created: $env:ASE_SKIAPATH" | |
} catch { | |
throw "Failed to create Skia folder." | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ Skia folder found: $env:ASE_SKIAPATH" | |
} | |
if (-not (Test-Path "$env:ASE_SKIAPATH\.git")) { | |
try { | |
Write-Host -ForegroundColor Yellow "⏳ Cloning Skia from GitHub..." | |
# Tested, doesn't work (vanilla skia) | |
# $result = Invoke-GitClone -RepoUrl 'https://skia.googlesource.com/skia.git' -OutputPath $env:ASE_SKIAPATH -Branch "chrome/m102" | |
# Tested, doesn't work (has bugs) | |
# $result = Invoke-GitClone -RepoUrl 'https://github.com/aseprite/skia.git' -OutputPath $env:ASE_SKIAPATH -Branch "$env:ASE_SKIAVERSION" | |
# Tested, works (fixes bugs, PR pending to skia aesprite-m102) | |
$result = Invoke-GitClone -RepoUrl 'https://github.com/loopyd/skia.git' -OutputPath $env:ASE_SKIAPATH -Branch "$env:ASE_SKIAVERSION" | |
if ($result -eq $false) { | |
throw "Failed to clone Skia." | |
} | |
Write-Host -ForegroundColor Green "✅ Skia cloned successfully." | |
} catch { | |
throw "$_.Exception.Message" | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ Skia found." | |
} | |
} | |
} | |
"asesprite" { | |
if (-not (Test-Path $env:ASE_ASESPRITEPATH)) { | |
try { | |
New-Item -ItemType Directory -Path $env:ASE_ASESPRITEPATH -Force -ErrorAction SilentlyContinue | |
Write-Host -ForegroundColor Green "✅ Aseprite path created: $env:ASE_ASESPRITEPATH" | |
} catch { | |
throw "Failed to create Aesprite folder" | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ Aseprite path found at: $env:ASE_ASESPRITEPATH" | |
} | |
if (-not (Test-Path "$env:ASE_ASESPRITEPATH\.git")) { | |
try { | |
$result = Invoke-GitClone -RepoUrl 'https://github.com/aseprite/aseprite.git' -Tag $env:ASE_ASEVERSION -OutputPath $env:ASE_ASESPRITEPATH | |
if ($result -eq $false) { | |
throw "Failed to clone Aseprite." | |
} | |
Write-Host -ForegroundColor Green "✅ Aseprite cloned successfully." | |
} catch { | |
throw "$_.Exception.Message" | |
} | |
} else { | |
Write-Host -ForegroundColor Green "✅ Aseprite download found in cache." | |
} | |
} | |
} | |
} catch { | |
Write-Host -ForegroundColor Red "❌ $($_.Exception.Message)" | |
return $false | |
} | |
} | |
############################################## | |
# BUILDS | |
############################################## | |
<# | |
.SYNOPSIS | |
This function builds Ninja using the Blep API. It requires the Visual Studio development environment to be entered first. | |
.DESCRIPTION | |
This function builds Ninja using the Blep API. It will attempt to build Ninja, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.EXAMPLE | |
Build-Ninja | |
.NOTES | |
None | |
#> | |
function Build-Ninja() { | |
try { | |
if ($(Test-Path "$env:ASE_NINJAPATH") -and $(Test-Path "$env:ASE_NINJAPATH\build\Release\ninja.exe")) { | |
Write-Host -ForegroundColor Green "✅ Ninja already built! Skipping." | |
return $true | |
} | |
$result = Toggle-DevelopmentEnvironment enter -Compiler msvc | |
if ($result -eq $false) { | |
throw "Cannot enter development environment, so cannot build Ninja." | |
} | |
$result = Set-Python -Version "3.6.1" | |
if ($result -eq $false) { | |
throw "Cannot set Python version." | |
} | |
$currentDirectory = Get-Location | |
if ((Test-Path "$env:ASE_NINJAPATH\build")) { | |
Remove-Item -Path "$env:ASE_NINJAPATH\build" -Recurse -Force | Out-Null | |
if ($LASTEXITCODE -ne 0) { | |
throw "Failed to delete existing Ninja build directory." | |
} | |
Write-Host -ForegroundColor Green "✅ Existing Ninja build directory removed." | |
} | |
New-Item -ItemType Directory -Path "$env:ASE_NINJAPATH\build" -Force | Out-Null | |
if ($LASTEXITCODE -ne 0) { | |
throw "Failed to create new Ninja build directory." | |
} | |
Write-Host -ForegroundColor Yellow "⏳ Configuring Ninja build..." | |
Set-Location "$env:ASE_NINJAPATH" | |
$arguments = @( | |
"-B`"$env:ASE_NINJAPATH\build`"" | |
"-DCMAKE_INSTALL_PREFIX=`"$env:ASE_CMAKEPATH`"" | |
"-DCMAKE_MSVC_RUNTIME_LIBRARY=`"MultiThreaded`"" | |
"-DCMAKE_SYSTEM_NAME=Windows" | |
"." | |
) | |
$lec = $(Roar -Command "$env:ASE_CMAKEPATH\bin\cmake.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
throw "Failed to configure Ninja build." | |
} | |
Write-Host -ForegroundColor Green "✅ Ninja build configured successfully." | |
Write-Host -ForegroundColor Yellow "⏳ Building Ninja..." | |
$arguments = @( | |
"--build `"$env:ASE_NINJAPATH\build`"" | |
"--config Release" | |
"--target install" | |
) | |
$lec = $(Roar -Command "$env:ASE_CMAKEPATH\bin\cmake.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
throw "Failed to build Ninja." | |
} | |
Set-Location -Path $currentDirectory | |
Write-Host -ForegroundColor Green "✅ Ninja built successfully." | |
return $true | |
} catch { | |
Set-Location -Path $currentDirectory | |
Write-Host -ForegroundColor Red "❌ $($_.Exception.Message)" | |
return $false | |
} | |
} | |
<# | |
.SYNOPSIS | |
This function builds LLVM using the Blep API. It requires the Visual Studio development environment to be entered first. | |
.DESCRIPTION | |
This function builds LLVM using the Blep API. It will attempt to build LLVM, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.EXAMPLE | |
Build-LLVM | |
.NOTES | |
None | |
#> | |
function Build-LLVM() { | |
try { | |
if ((Test-Path "$env:ASE_LLVMPATH\build") -and $(Test-Path "$env:ASE_LLVMROOT") -eq $true) { | |
Write-Host -ForegroundColor Green "✅ LLVM-blAse already built! Skipping." | |
return $true | |
} | |
$result = Toggle-DevelopmentEnvironment enter -Compiler msvc | |
if ($result -eq $false) { | |
throw "Cannot enter development environment, so cannot build LLVM-blAse." | |
} | |
$result = Set-Python -Version "3.6.1" | |
if ($result -eq $false) { | |
throw "Cannot set Python version." | |
} | |
$currentDirectory = Get-Location | |
if ((Test-Path "$env:ASE_LLVMPATH\build")) { | |
Remove-Item -Path "$env:ASE_LLVMPATH\build" -Recurse -Force | Out-Null | |
if ($LASTEXITCODE -ne 0) { | |
throw "Failed to delete existing LLVM build directory." | |
} | |
Write-Host -ForegroundColor Green "✅ Existing LLVM build directory removed." | |
} | |
New-Item -ItemType Directory -Path "$env:ASE_LLVMPATH\build" -Force | Out-Null | |
if ($LASTEXITCODE -ne 0) { | |
throw "Failed to create new LLVM build directory." | |
} | |
Write-Host -ForegroundColor Yellow "⏳ Configuring LLVM-blAse build..." | |
Set-Location "$env:ASE_LLVMPATH\build" | |
$arguments = @( | |
"-G `"Ninja`"" | |
"-S `"$env:ASE_LLVMPATH\llvm`"" | |
"-B `"$env:ASE_LLVMPATH\build`"" | |
"-DCLANG_BUILD_EXAMPLES=Off" | |
"-DCLANG_ENABLE_ARCMT=Off" | |
"-DCLANG_ENABLE_STATIC_ANALYZER=On" | |
"-DCLANG_INCLUDE_DOCS=Off" | |
"-DCLANG_INCLUDE_TESTS=Off" | |
"-DCMAKE_BUILD_TYPE=Release" | |
"-DCMAKE_INSTALL_PREFIX=`"$env:ASE_LLVMROOT`"" | |
"-DCMAKE_MSVC_RUNTIME_LIBRARY=`"MultiThreaded`"" | |
"-DCMAKE_SYSTEM_NAME=Windows" | |
"-DCOMPILER_RT_BUILD_BUILTINS=Off" | |
"-DCOMPILER_RT_BUILD_GWP_ASAN=Off" | |
"-DCOMPILER_RT_BUILD_LIBFUZZER=On" | |
"-DCOMPILER_RT_BUILD_MEMPROF=Off" | |
"-DCOMPILER_RT_BUILD_ORC=Off" | |
"-DCOMPILER_RT_BUILD_PROFILE=On" | |
"-DCOMPILER_RT_BUILD_SANITIZERS=On" | |
"-DCOMPILER_RT_BUILD_XRAY_NO_PREINIT=Off" | |
"-DCOMPILER_RT_BUILD_XRAY=Off" | |
"-DCOMPILER_RT_ENABLE_CET=OFF" | |
"-DLLVM_BUILD_BENCHMARKS=Off" | |
"-DLLVM_BUILD_DOCS=Off" | |
"-DLLVM_BUILD_EXAMPLES=Off" | |
"-DLLVM_BUILD_LLVM_C_DYLIB=Off" | |
"-DLLVM_BUILD_SHARED_LIBS=Off" | |
"-DLLVM_BUILD_TESTS=Off" | |
"-DLLVM_ENABLE_ASSERTIONS=Off" | |
"-DLLVM_ENABLE_BACKTRACES=Off" | |
"-DLLVM_ENABLE_BINDINGS=Off" | |
"-DLLVM_ENABLE_CRASH_DUMPS=Off" | |
"-DLLVM_ENABLE_CRASH_OVERRIDES=Off" | |
"-DLLVM_ENABLE_CURL=Off" | |
"-DLLVM_ENABLE_DIA_SDK=1" | |
"-DLLVM_ENABLE_HTTPLIB=Off" | |
"-DLLVM_ENABLE_IDE=Off" | |
"-DLLVM_ENABLE_LIBEDIT=Off" | |
"-DLLVM_ENABLE_LIBEDIT=Off" | |
"-DLLVM_ENABLE_LIBPFM=Off" | |
"-DLLVM_ENABLE_LIBXML2=Off" | |
"-DLLVM_ENABLE_OCAMLDOC=Off" | |
"-DLLVM_ENABLE_PEDANTIC=Off" | |
"-DLLVM_ENABLE_PLUGINS=Off" | |
"-DLLVM_ENABLE_PROJECTS=`"clang;lld;lldb;compiler-rt;clang-tools-extra;polly`"" | |
"-DLLVM_ENABLE_RTTI=0" | |
"-DLLVM_ENABLE_TERMINFO=Off" | |
"-DLLVM_ENABLE_UNWIND_TABLES=Off" | |
"-DLLVM_ENABLE_WARNINGS=Off" | |
"-DLLVM_ENABLE_WERROR=Off" | |
"-DLLVM_ENABLE_Z3_SOLVER=Off" | |
"-DLLVM_ENABLE_ZLIB=Off" | |
"-DLLVM_ENABLE_ZSTD=Off" | |
"-DLLVM_INCLUDE_BENCHMARKS=Off" | |
"-DLLVM_INCLUDE_DOCS=Off" | |
"-DLLVM_INCLUDE_EXAMPLES=Off" | |
"-DLLVM_INCLUDE_TESTS=Off" | |
"-DLLVM_TARGETS_TO_BUILD=`"AArch64;ARM;WebAssembly;X86`"" | |
) | |
$lec = $(Roar -Command "$env:ASE_CMAKEPATH\bin\cmake.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
throw "Failed to configure LLVM-blAse build. Process returned exit code $lec." | |
} | |
Write-Host -ForegroundColor Green "✅ LLVM-blAse build configured successfully" | |
Write-Host -ForegroundColor Yellow "⏳ Compiling LLVM-blAse..." | |
$arguments = @( | |
"-j $env:ASE_CPUCOUNT" | |
"--verbose" | |
) | |
$lec = $(Roar -Command "$env:ASE_CMAKEPATH\bin\ninja.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
throw "Failed to compile LLVM-blAse: Process exited with code $lec." | |
} | |
Write-Host -ForegroundColor Green "✅ LLVM-blAse compiled successfully" | |
Write-Host -ForegroundColor Yellow "⏳ Installing LLVM-blAse..." | |
$arguments = @( | |
"install" | |
) | |
$lec = $(Roar -Command "$env:ASE_CMAKEPATH\bin\ninja.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
throw "Failed to install LLVM-blAse: Process exited with code $lec." | |
} | |
Write-Host -ForegroundColor Green "✅ LLVM-blAse installed successfully" | |
Set-Location $currentDirectory | |
$result = Toggle-DevelopmentEnvironment leave -Compiler vsclang | |
if ($result -eq $false) { | |
throw "Cannot leave development environment." | |
} | |
Write-Host -ForegroundColor Green "🎉 LLVM-blAse built successfully." | |
return $true | |
} catch { | |
Set-Location $currentDirectory | |
$result = Toggle-DevelopmentEnvironment leave -Compiler msvc | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "Cannot leave development environment, script in unexpected state." | |
return $false | |
} | |
Write-Host -ForegroundColor Red "❌ $($_.Exception.Message)" | |
return $false | |
} | |
} | |
<# | |
.SYNOPSIS | |
This function builds Google Depot Tools. | |
.DESCRIPTION | |
This function builds Google Depot Tools. It will attempt to build Google Depot Tools, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.EXAMPLE | |
Build-GoogleDepot | |
.NOTES | |
None | |
#> | |
function Build-GoogleDepot() { | |
try { | |
$result = Toggle-DevelopmentEnvironment -Action enter -Compiler msvc | |
if ($result -eq $false) { | |
throw "Cannot enter development environment" | |
} | |
$currentDirectory = Get-Location | |
Set-Location $env:ASE_DEPOTTOOLSPATH | |
Mod-Path -Add @( | |
"$env:ASE_DEPOTTOOLSPATH" | |
"$env:ASE_CMAKEPATH\bin" | |
) | |
Write-Host -ForegroundColor Yellow "⏳ Updating Google Depot Tools..." | |
try { | |
$arguments = @( | |
"sync" | |
) | |
$lec = $(Roar -Command "gclient" -Arguments $arguments) | |
if ($lec -ne 0 -and $lec -ne 1) { | |
throw "Failed to update Google Depot Tools. Process returned exit code $lec." | |
} | |
} catch { | |
throw "$($_.Exception.Message)" | |
} | |
Mod-Path -Remove @( | |
"$env:ASE_DEPOTTOOLSPATH" | |
"$env:ASE_CMAKEPATH\bin" | |
) | |
Set-Location $currentDirectory | |
$result = Toggle-DevelopmentEnvironment -Action leave -Compiler msvc | |
if ($result -eq $false) { | |
throw "Cannot leave development environment" | |
} | |
Write-Host -ForegroundColor Green "✅ Google Depot Tools updated successfully." | |
return $true | |
} catch { | |
Mod-Path -Remove @( | |
"$env:ASE_DEPOTTOOLSPATH" | |
"$env:ASE_CMAKEPATH\bin" | |
) | |
Set-Location $currentDirectory | |
Write-Host -ForegroundColor Red "❌ $($_.Exception.Message)" | |
return $false | |
} | |
} | |
<# | |
.SYNOPSIS | |
This function builds Skia using the Blep API. The skia graphics library used by Aseprite. | |
.DESCRIPTION | |
This function builds Skia using the Blep API. It will attempt to build Skia, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.EXAMPLE | |
Build-Skia | |
.NOTES | |
None | |
#> | |
function Build-Skia() { | |
param( | |
[ValidateSet("Release", "Debug", IgnoreCase = $true)] | |
[string]$BuildType = "Release" | |
) | |
try { | |
if ((Test-Path "$env:ASE_SKIAPATH\out") -and $(Test-Path "$env:ASE_SKIAPATH\out\$BuildType-x64") -eq $true) { | |
Write-Host -ForegroundColor Green "✅ Skia already built! Skipping." | |
return $true | |
} | |
# Enter Visual Studio development environment | |
$result = Toggle-DevelopmentEnvironment -Action enter -Compiler blaseclang | |
if ($result -eq $false) { | |
throw "Failed to enter development environment." | |
} | |
Mod-Path -Add @( | |
"$env:ASE_DEPOTTOOLSPATH" | |
"$env:ASE_CMAKEPATH\bin" | |
"$env:ASE_LLVMROOT\bin" | |
) | |
$env:GIT_EXECUTABLE = "$env:ASE_DEPOTTOOLSPATH\git.bat" | |
$env:EMSDK_POWERSHELL = "1" | |
# Update Skia dependencies | |
$currentLocation = Get-Location | |
Set-Location $env:ASE_SKIAPATH | |
Write-Host -ForegroundColor Yellow "⏳ Updating Skia..." | |
try { | |
$arguments = @( | |
"tools/git-sync-deps" | |
) | |
$lec = $(Roar -Command "$env:ASE_DEPOTTOOLSPATH\python3.bat" -Arguments $arguments) | |
if ($lastExitCode -ne 0) { | |
throw "Failed to update Skia. Process returned exit code $lastExitCode." | |
} | |
} catch { | |
throw "$($_.Exception.Message)" | |
} | |
Write-Host -ForegroundColor Green "✅ Skia updated successfully." | |
# Clean build directory | |
try { | |
if (-not (Test-Path "$env:ASE_SKIAPATH\out")) { | |
New-Item -ItemType Directory -Path "$env:ASE_SKIAPATH\out" -Force | Out-Null | |
} else { | |
Write-Host -ForegroundColor Yellow "⏳ Removing existing build directory..." | |
Remove-Item -Path "$env:ASE_SKIAPATH\out" -Recurse -Force | Out-Null | |
Write-Host -ForegroundColor Green "✅ Existing build directory removed." | |
New-Item -ItemType Directory -Path "$env:ASE_SKIAPATH\out" -Force | Out-Null | |
switch ($BuildType) { | |
"Release" { | |
New-Item -ItemType Directory -Path "$env:ASE_SKIAPATH\out\Release-x64" -Force | Out-Null | |
break | |
} | |
"Debug" { | |
New-Item -ItemType Directory -Path "$env:ASE_SKIAPATH\out\Debug-x64" -Force | Out-Null | |
break | |
} | |
default { | |
throw "Invalid build type: $BuildType" | |
} | |
} | |
} | |
} catch { | |
throw "Failed to clean build directory: $($_.Exception.Message)" | |
} | |
# Configure skia build | |
try { | |
switch ($BuildType) { | |
"Release" { | |
Write-Host -ForegroundColor Yellow "⏳ Configuring Release build using $env:ASE_DEPOTTOOLSPATH\gn.py..." | |
$arguments = @( | |
"is_debug=false", | |
"is_official_build=true", | |
"skia_use_system_expat=false", | |
"skia_use_system_icu=false", | |
"skia_use_system_libjpeg_turbo=false", | |
"skia_use_system_libpng=false", | |
"skia_use_system_libwebp=false", | |
"skia_use_system_zlib=false", | |
"skia_use_sfntly=false", | |
"skia_use_freetype=true", | |
"skia_use_harfbuzz=true", | |
"skia_pdf_subset_harfbuzz=true", | |
"skia_use_system_freetype2=false", | |
"skia_use_system_harfbuzz=false", | |
"target_cpu=""""x64""""", | |
"cc=""""$env:ASE_LLVMROOT\bin\clang.exe""""", | |
"cxx=""""$env:ASE_LLVMROOT\bin\clang++.exe""""", | |
"win_vc=""""$env:ASE_VISUALSTUDIOPATH\VC""""" | |
) -join " " | |
$packedArguments = @( | |
"`"$env:ASE_DEPOTTOOLSPATH\gn.py`"" | |
"gen", | |
"out/Release-x64", | |
"--args=`'$arguments`'" | |
) | |
$lec = $(Roar -Command "$env:ASE_DEPOTTOOLSPATH\python3.bat" -Arguments $packedArguments) | |
if ($lec -ne 0) { | |
throw "Configure failed." | |
} | |
Write-Host -ForegroundColor Green "✅ Build configured." | |
break | |
} | |
"Debug" { | |
Write-Host -ForegroundColor Yellow "⏳ Configuring Debug build using $env:ASE_DEPOTTOOLSPATH\gn.py..." | |
$arguments = @( | |
"is_debug=true", | |
"is_official_build=false", | |
"skia_use_system_expat=false", | |
"skia_use_system_icu=false", | |
"skia_use_system_libjpeg_turbo=false", | |
"skia_use_system_libpng=false", | |
"skia_use_system_libwebp=false", | |
"skia_use_system_zlib=false", | |
"skia_use_sfntly=false", | |
"skia_use_freetype=true", | |
"skia_use_harfbuzz=true", | |
"skia_pdf_subset_harfbuzz=true", | |
"skia_use_system_freetype2=false", | |
"skia_use_system_harfbuzz=false", | |
"target_cpu=""""x64""""", | |
"cc=""""$env:ASE_LLVMROOT\bin\clang.exe""""", | |
"cxx=""""$env:ASE_LLVMROOT\bin\clang++.exe""""", | |
"win_vc=""""$env:ASE_VISUALSTUDIOPATH\VC""""" | |
) -join " " | |
$packedArguments = @( | |
"""$env:ASE_DEPOTTOOLSPATH\gn.py""" | |
"gen", | |
"out/Debug-x64", | |
"--args=`'$arguments`'" | |
) | |
$lec = $(Roar -Command "$env:ASE_DEPOTTOOLSPATH\python3.bat" -Arguments $packedArguments) | |
if ($lec -ne 0) { | |
throw "Configure failed." | |
} | |
Write-Host -ForegroundColor Green "✅ Build configured." | |
break | |
} | |
default { | |
throw "Invalid build type: $BuildType" | |
} | |
} | |
} catch { | |
throw "Configure failed: $($_.Exception.Message)" | |
} | |
# Compile | |
try { | |
switch ($BuildType) { | |
"Release" { | |
Write-Host -ForegroundColor Yellow "⏳ Compiling Release build using $env:ASE_NINJAPATH..." | |
$arguments = @( | |
"-j", | |
"$env:ASE_CPUCOUNT", | |
"-C", | |
"out/Release-x64", | |
"skia", | |
"modules" | |
) | |
$lastExitCode = $(Roar -Command "$env:ASE_CMAKEPATH\bin\ninja.exe" -Arguments $arguments) | |
if ($lastExitCode -ne 0) { | |
throw "Failed to build skia Release." | |
} | |
Write-Host -ForegroundColor Green "✅ Build Release succeeded." | |
break | |
} | |
"Debug" { | |
Write-Host -ForegroundColor Yellow "⏳ Compiling Debug build using $env:ASE_NINJAPATH..." | |
$arguments = @( | |
"-j", | |
"$env:ASE_CPUCOUNT", | |
"-C", | |
"out/Debug-x64", | |
"skia", | |
"modules" | |
) | |
$lastExitCode = $(Roar -Command "$env:ASE_CMAKEPATH\bin\ninja.exe" -Arguments $arguments) | |
if ($lastExitCode -ne 0) { | |
throw "Failed to build skia Debug." | |
} | |
Write-Host -ForegroundColor Green "✅ Build Debug succeeded." | |
break | |
} | |
default { | |
throw "Invalid build type: $BuildType" | |
} | |
} | |
} catch { | |
throw "Build failed: $($_.Exception.Message)" | |
} | |
Write-Host -ForegroundColor Magenta "🎉 Skia build succeeded." | |
Set-Location $currentLocation | |
Mod-Path -Remove @( | |
"$env:ASE_DEPOTTOOLSPATH" | |
"$env:ASE_CMAKEPATH\bin" | |
"$env:ASE_LLVMROOT\bin" | |
) | |
$env:GIT_EXECUTABLE = $null | |
$result = Toggle-DevelopmentEnvironment -Action leave -Compiler blaseclang | |
if ($result -eq $false) { | |
throw "Failed to leave development environment" | |
} | |
return $true | |
} catch { | |
Write-Host -ForegroundColor Red "❌ $($_.Exception.Message)" | |
Set-Location $currentLocation | |
Mod-Path -Remove @( | |
"$env:ASE_DEPOTTOOLSPATH" | |
"$env:ASE_CMAKEPATH\bin" | |
"$env:ASE_LLVMROOT\bin" | |
) | |
$env:GIT_EXECUTABLE = $null | |
if ($result -eq $true) | |
{ | |
$result = Toggle-DevelopmentEnvironment -Action leave -Compiler blaseclang | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "❌ Failed to leave development environment, the script is in an unexpected state." | |
} | |
} | |
return $false | |
} | |
} | |
<# | |
.SYNOPSIS | |
This function builds Aseprite using the Blep API. It requires the Skia library to be built first. | |
.DESCRIPTION | |
This function builds Aseprite using the Blep API. It will attempt to build Aseprite, and then re-evaluate wth the -PostOperation switch enabled. If it then fails, it will return false. | |
.EXAMPLE | |
Build-Aseprite | |
.NOTES | |
None | |
#> | |
function Build-Aseprite() { | |
try { | |
if ((Test-Path "$env:ASE_ASESPRITEPATH\build") -and $(Test-Path "$env:ASE_ASESPRITEPATH\build\bin\aseprite.exe") -eq $true) { | |
Write-Host -ForegroundColor Green "✅ Aseprite already built! Skipping." | |
return $true | |
} | |
# Enter Visual Studio development environment | |
$result = Toggle-DevelopmentEnvironment -Action enter -Compiler msvc | |
if ($result -eq $false) { | |
throw "Failed to enter development environment." | |
} | |
# Enter build directory | |
$currentLocation = Get-Location | |
try { | |
$currentLocation = Get-Location | |
Set-Location -Path "$env:ASE_ASESPRITEPATH" | |
if (-not (Test-Path "build")) { | |
New-Item -ItemType Directory -Path "build" -Force | Out-Null | |
} else { | |
Remove-Item -Path "build" -Recurse -Force | |
New-Item -ItemType Directory -Path "build" -Force | Out-Null | |
Write-Host -ForegroundColor Green "✅ New Asesprite-blAse build directory created." | |
} | |
Set-Location -Path "$env:ASE_ASESPRITEPATH\build" | |
} catch { | |
throw "Failed to enter build directory: $($_.Exception.Message)" | |
} | |
# Configure build | |
try { | |
Write-Host -ForegroundColor Yellow "⏳ Configuring Asesprite-blAse..." | |
$arguments = @( | |
"-G Ninja" | |
"-DCMAKE_BUILD_TYPE=RelWithDebInfo" | |
"-DLAF_BACKEND=skia" | |
"-DENABLE_NEWS=OFF" | |
"-DENABLE_PSD=ON" | |
"-DENABLE_TAR=ON" | |
"-DENABLE_CAT=ON" | |
"-DENABLE_GIF=ON" | |
"-DENABLE_WEBP=ON" | |
"-DENABLE_APNG=ON" | |
"-DENABLE_UPDATER=OFF" | |
"-DGIFLIB_UTILS=ON" | |
"-DSKIA_DIR=""""$env:ASE_SKIAPATH""""" | |
"-DSKIA_LIBRARY_DIR=""""$env:ASE_SKIAPATH\out\Release-x64""""" | |
"-DSKIA_LIBRARY=""""$env:ASE_SKIAPATH\out\Release-x64\skia.lib""""" | |
"-DSKIA_OUT_DIR=""""$env:ASE_SKIAPATH\out\Release-x64""""" | |
".." | |
) -join " " | |
$lec = $(Roar -Command "$env:ASE_CMAKEPATH\bin\cmake.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
throw "Configure failed." | |
} | |
Write-Host -ForegroundColor Green "✅ Asesprite-blAse configured." | |
} catch { | |
Write-Host -ForegroundColor Red "❌ Configure failed: $($_.Exception.Message)" | |
throw "Configure failed: $($_.Exception.Message)" | |
} | |
# Compile | |
try { | |
Write-Host -ForegroundColor Yellow "⏳ Compiling Asesprite-blAse..." | |
$arguments = @( | |
"-j $env:ASE_CPUCOUNT" | |
"aseprite" | |
) -join " " | |
$lec = $(Roar -Command "$env:ASE_CMAKEPATH\bin\ninja.exe" -Arguments $arguments) | |
if ($lec -ne 0) { | |
throw "Failed to compile Asesprite-blAse." | |
} | |
Write-Host -ForegroundColor Green "✅ Asesprite-blAse compiled succeesfully." | |
} catch { | |
throw "Build failed: $($_.Exception.Message)" | |
} | |
Write-Host -ForegroundColor Magenta "🎉 Asesprite-blAse build succeeded." | |
Set-Location $currentLocation | |
$result = Toggle-DevelopmentEnvironment -Action leave -Compiler msvc | |
if ($result -eq $false) { | |
throw "Failed to leave development environment" | |
} | |
return $true | |
} catch { | |
Write-Host -ForegroundColor Red "❌ $($_.Exception.Message)" | |
Set-Location $currentLocation | |
if ($result -eq $true) | |
{ | |
$result = Toggle-DevelopmentEnvironment -Action leave -Compiler msvc | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "❌ Failed to leave development environment, the script is in an unexpected state." | |
} | |
} | |
return $false | |
} | |
} | |
############################################## | |
# ENVIRONMENT VARIABLES | |
############################################## | |
# Version numbers | |
$env:ASE_WINSDKVERSION = $WindowsSdkVersion | |
$env:ASE_SKIAVERSION = $SkiaVersion | |
$env:ASE_ASEVERSION = $AseVersion | |
$env:ASE_VISUALSTUDIOVERSION = $VisualStudioVersion | |
$env:ASE_LLVMVERSION = $LlvmVersion | |
$env:ASE_CMAKEVERSION = $CmakeVersion | |
$env:ASE_NINJAVERSION = $NinjaVersion | |
$env:ASE_GITVERSION = $GitVersion | |
$env:ASE_GITSUBVERSION = $GitSubVersion | |
# Paths | |
$env:ASE_CACHEPATH = $CachePath | |
$env:ASE_ASESPRITEPATH = "$CachePath\aesprite" | |
$env:ASE_SKIAPATH = "$CachePath\skia" | |
$env:ASE_DEPOTTOOLSPATH = "$CachePath\depot_tools" | |
$env:ASE_LLVMPATH = "$CachePath\llvm" | |
$env:ASE_LLVMROOT = "$CachePath\llvm\build\Release" | |
$env:ASE_NINJAPATH = "$CachePath\ninja" | |
$env:ASE_CMAKEPATH = "$CachePath\cmake" | |
$env:ASE_GITPATH = "$CachePath\git" | |
# Flags | |
$env:ASE_SKIAUSEPREBUILT = $SkiaUsePrebuilt | |
$env:ASE_CACHECLEAN = $Clean | |
# URLs (probably should move these....) | |
$env:ASE_SKIAURL = "https://github.com/aseprite/skia/releases/download/$env:ASE_SKIAVERSION/Skia-Windows-Release-x64.zip" | |
$env:ASE_AESURL = "https://github.com/aseprite/aseprite/releases/download/v$env:ASE_ASEVERSION/Aseprite-v$env:ASE_ASEVERSION-Source.zip" | |
# COMPILE TIME CPU COUNT | |
# | |
# The percentage below is used to calculate the number of logical cores used during compile | |
# time operations. This is to prevent the system from running out of resources during the build | |
# process, while still allowing the larger builds to complete in a reasonable amount of time. | |
# | |
# If you find yourself experiencing BSODs related to page faults during compile time operations, | |
# please reduce the percentage in the calculation below. Every host is different. | |
# | |
# WHY IS THIS HARDCODED? | |
# | |
# Because this is a setting that can potentially crash a lot of computers, its not been made | |
# a command-line argument like many others. If you want to change this value, you can do so | |
# by editing the "0.70" to reflect another percentage. For example, if you want to use 50% of | |
# your logical cores, you would change the value to "0.50". And for 30%, you would change the | |
# value to "0.30". | |
# | |
# ⚠️ It is HIGHLY DISCOURAGED to set this value >= 0.75 (75-100%), as this will cause system | |
# instability. If you don't like seeing smiley faces and memory dump screens, I highly | |
# recommend that you don't do that. :-) If you do, you're on your own with support. | |
# | |
$env:ASE_CPUCOUNT = [int][math]::Floor(((Get-CimInstance -ClassName Win32_ComputerSystem).NumberOfLogicalProcessors) * 0.50) | |
############################################## | |
# LOGO | |
############################################## | |
Display-Logo | |
############################################## | |
# DEPENDENCY VALIDATION | |
############################################## | |
Write-Host -ForegroundColor Cyan "⚙️ Checking dependencies..." | |
$Dependencies = @( | |
"cache", | |
'7zip', | |
"git", | |
"visualstudio", | |
"windowssdk", | |
"cmake", | |
"ninja", | |
"python", | |
"depot_tools", | |
"skia", | |
"asesprite", | |
"llvm" | |
) | |
$result = $true | |
ForEach ($Dependency in $Dependencies) { | |
$result = $result && $(Check-Dependency -DependencyName $Dependency) | |
} | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "⛔ One or more dependencies were not able to be met, the script will now exit." | |
exit 1 | |
} | |
Write-Host -ForegroundColor Cyan "✨ All dependencies were met, proceeding with the build." | |
$result = Build-Ninja | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "⛔ Ninja build failed, the script will now exit." | |
exit 1 | |
} | |
$result = Build-LLVM | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "⛔ LLVM build failed, the script will now exit." | |
exit 1 | |
} | |
$result = Build-GoogleDepot | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "⛔ Google Depot Tools build failed, the script will now exit." | |
exit 1 | |
} | |
$result = Build-Skia | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "⛔ Skia build failed, the script will now exit." | |
exit 1 | |
} | |
$result = Build-Aseprite | |
if ($result -eq $false) { | |
Write-Host -ForegroundColor Red "⛔ Aseprite build failed, the script will now exit." | |
exit 1 | |
} | |
Write-Host -ForegroundColor Magenta "🎉 All builds succeeded!" | |
############################################## | |
# POST-OPERATION | |
############################################## | |
$artifactPath = $(Emit-Artifact -Version "$env:ASE_ASEVERSION" -Release "Release" -Name "blASeprite" -Include @('.*$') -Exclude @('.*\.pdb$') -SourcePath "$env:ASE_ASESPRITEPATH\build\bin\" -OutputPath "$PWD") | |
if ($null -eq $artifactPath) { | |
Write-Host -ForegroundColor Red "⛔ Failed to emit artifact." | |
exit 1 | |
} | |
Display-Success -ArtifactPath $artifactPath | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
blAse - Single-File Aseprite Build Tool
Changelog
1.0.0
Release Notes