Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enable building msix package #340

Merged
merged 7 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Cargo.lock
target
bin/
.DS_Store
*.msix

# Node.js generated files for tree-sitter
build/
Expand Down
231 changes: 172 additions & 59 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ param(
[ValidateSet('current','aarch64-pc-windows-msvc','x86_64-pc-windows-msvc','aarch64-apple-darwin','x86_64-apple-darwin','aarch64-unknown-linux-gnu','aarch64-unknown-linux-musl','x86_64-unknown-linux-gnu','x86_64-unknown-linux-musl')]
$architecture = 'current',
[switch]$Clippy,
[switch]$SkipBuild,
[switch]$Msix,
[switch]$Test,
[switch]$GetPackageVersion,
[switch]$SkipLinkCheck
Expand Down Expand Up @@ -52,7 +54,7 @@ function Find-LinkExe {
}
}

if (!$SkipLinkCheck -and $IsWindows -and !(Get-Command 'link.exe' -ErrorAction Ignore)) {
if (!$SkipBuild -and !$SkipLinkCheck -and $IsWindows -and !(Get-Command 'link.exe' -ErrorAction Ignore)) {
if (!(Test-Path $BuildToolsPath)) {
Write-Verbose -Verbose "link.exe not found, installing C++ build tools"
Invoke-WebRequest 'https://aka.ms/vs/17/release/vs_BuildTools.exe' -OutFile 'temp:/vs_buildtools.exe'
Expand Down Expand Up @@ -83,7 +85,6 @@ if (!$SkipLinkCheck -and $IsWindows -and !(Get-Command 'link.exe' -ErrorAction I
#$env:PATH += ";$linkexe"
}

## Create the output folder
$configuration = $Release ? 'release' : 'debug'
$flags = @($Release ? '-r' : $null)
if ($architecture -eq 'current') {
Expand All @@ -98,13 +99,14 @@ else {
$target = Join-Path $PSScriptRoot 'bin' $architecture $configuration
}

if (Test-Path $target) {
Remove-Item $target -Recurse -ErrorAction Stop
}
New-Item -ItemType Directory $target > $null
if (!$SkipBuild) {
if (Test-Path $target) {
Remove-Item $target -Recurse -ErrorAction Stop
}
New-Item -ItemType Directory $target > $null

# make sure dependencies are built first so clippy runs correctly
$windows_projects = @("pal", "ntreg", "ntstatuserror", "ntuserinfo", "registry")
# make sure dependencies are built first so clippy runs correctly
$windows_projects = @("pal", "ntreg", "ntstatuserror", "ntuserinfo", "registry")

# projects are in dependency order
$projects = @(
Expand All @@ -125,74 +127,73 @@ $pedantic_unclean_projects = @("ntreg")
$clippy_unclean_projects = @("tree-sitter-dscexpression")
$skip_test_projects_on_windows = @("tree-sitter-dscexpression")

if ($IsWindows) {
$projects += $windows_projects
}
if ($IsWindows) {
$projects += $windows_projects
}

$failed = $false
foreach ($project in $projects) {
## Build format_json
Write-Host -ForegroundColor Cyan "Building $project ... for $architecture"
try {
Push-Location "$PSScriptRoot/$project" -ErrorAction Stop
$failed = $false
foreach ($project in $projects) {
## Build format_json
Write-Host -ForegroundColor Cyan "Building $project ... for $architecture"
try {
Push-Location "$PSScriptRoot/$project" -ErrorAction Stop

if ($project -eq 'tree-sitter-dscexpression') {
./build.ps1
}
if ($project -eq 'tree-sitter-dscexpression') {
./build.ps1
}

if (Test-Path "./Cargo.toml")
{
if ($Clippy) {
if ($clippy_unclean_projects -contains $project) {
Write-Verbose -Verbose "Skipping clippy for $project"
}
elseif ($pedantic_unclean_projects -contains $project) {
Write-Verbose -Verbose "Running clippy for $project"
cargo clippy @flags -- -Dwarnings
if (Test-Path "./Cargo.toml")
{
if ($Clippy) {
if ($clippy_unclean_projects -contains $project) {
Write-Verbose -Verbose "Skipping clippy for $project"
}
elseif ($pedantic_unclean_projects -contains $project) {
Write-Verbose -Verbose "Running clippy for $project"
cargo clippy @flags -- -Dwarnings
}
else {
Write-Verbose -Verbose "Running clippy with pedantic for $project"
cargo clippy @flags --% -- -Dwarnings -Dclippy::pedantic
}
}
else {
Write-Verbose -Verbose "Running clippy with pedantic for $project"
cargo clippy @flags --% -- -Dwarnings -Dclippy::pedantic
cargo build @flags
}
}
else {
cargo build @flags
}
}

if ($LASTEXITCODE -ne 0) {
$failed = $true
}
if ($LASTEXITCODE -ne 0) {
$failed = $true
}

$binary = Split-Path $project -Leaf
$binary = Split-Path $project -Leaf

if ($IsWindows) {
Copy-Item "$path/$binary.exe" $target -ErrorAction Ignore
}
else {
Copy-Item "$path/$binary" $target -ErrorAction Ignore
}
if ($IsWindows) {
Copy-Item "$path/$binary.exe" $target -ErrorAction Ignore
}
else {
Copy-Item "$path/$binary" $target -ErrorAction Ignore
}

if (Test-Path "./copy_files.txt") {
Get-Content "./copy_files.txt" | ForEach-Object {
Copy-Item $_ $target -Force -ErrorAction Ignore
if (Test-Path "./copy_files.txt") {
Get-Content "./copy_files.txt" | ForEach-Object {
Copy-Item $_ $target -Force -ErrorAction Ignore
}
}
}

Copy-Item "*.dsc.resource.json" $target -Force -ErrorAction Ignore
Copy-Item "*.dsc.resource.json" $target -Force -ErrorAction Ignore

} finally {
Pop-Location
} finally {
Pop-Location
}
}
}

if ($failed) {
Write-Host -ForegroundColor Red "Build failed"
exit 1
if ($failed) {
Write-Host -ForegroundColor Red "Build failed"
exit 1
}
}

Copy-Item $PSScriptRoot/tools/add-path.ps1 $target -Force -ErrorAction Ignore

$relative = Resolve-Path $target -Relative
if (!$Clippy) {
Write-Host -ForegroundColor Green "`nEXE's are copied to $target ($relative)"
Expand Down Expand Up @@ -221,7 +222,7 @@ if (!$Clippy) {

if (!$found) {
Write-Host -ForegroundCOlor Yellow "Adding $target to `$env:PATH"
$env:PATH += [System.IO.Path]::PathSeparator + $target
$env:PATH = $target + [System.IO.Path]::PathSeparator + $env:PATH
}
}

Expand Down Expand Up @@ -293,4 +294,116 @@ if ($Test) {
Invoke-Pester -ErrorAction Stop
}

if ($Msix) {
if (!$IsWindows) {
throw "MSIX is only supported on Windows"
}

if ($architecture -eq 'current') {
throw 'MSIX requires a specific architecture'
}

$makeappx = Get-Command makeappx -CommandType Application -ErrorAction Ignore
if ($null -eq $makeappx) {
# try to find
if ($architecture -eq 'aarch64-pc-windows-msvc') {
$arch = 'arm64'
}
else {
$arch = 'x64'
}

$makeappx = Get-ChildItem -Recurse -Path (Join-Path ${env:ProgramFiles(x86)} 'Windows Kits\10\bin\*\' $arch) -Filter makeappx.exe | Sort-Object FullName -Descending | Select-Object -First 1
if ($null -eq $makeappx) {
throw "makeappx not found, please install Windows SDK"
}
}

$makepri = Get-Item (Join-Path $makeappx.Directory "makepri.exe") -ErrorAction Stop
$displayName = "DesiredStateConfiguration"
$productVersion = ((Get-Content $PSScriptRoot/dsc/Cargo.toml) -match '^version\s*=\s*') -replace 'version\s*=\s*"(.*?)"', '$1'
$isPreview = $productVersion -like '*-*'
$productName = "DesiredStateConfiguration"
if ($isPreview) {
Write-Verbose -Verbose "Preview version detected"
$productName += "-Preview"
# save preview number
$previewNumber = $productVersion -replace '.*?-[a-z]+\.([0-9]+)', '$1'
# remove label from version
$productVersion = $productVersion.Split('-')[0]
# replace revision number with preview number
$productVersion = $productVersion -replace '(\d+)$', "$previewNumber.0"
$displayName += "-Preview"
}
Write-Verbose -Verbose "Product version is $productVersion"
$arch = if ($architecture -eq 'aarch64-pc-windows-msvc') { 'arm64' } else { 'x64' }

# Appx manifest needs to be in root of source path, but the embedded version needs to be updated
# cp-459155 is 'CN=Microsoft Windows Store Publisher (Store EKU), O=Microsoft Corporation, L=Redmond, S=Washington, C=US'
# authenticodeFormer is 'CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US'
$releasePublisher = 'CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US'

$appxManifest = Get-Content "$PSScriptRoot\packaging\msix\AppxManifest.xml" -Raw
$appxManifest = $appxManifest.Replace('$VERSION$', $ProductVersion).Replace('$ARCH$', $Arch).Replace('$PRODUCTNAME$', $productName).Replace('$DISPLAYNAME$', $displayName).Replace('$PUBLISHER$', $releasePublisher)
$msixTarget = Join-Path $PSScriptRoot 'bin' $architecture 'msix'
if (Test-Path $msixTarget) {
Remove-Item $msixTarget -Recurse -ErrorAction Stop
}

New-Item -ItemType Directory $msixTarget > $null
Set-Content -Path "$msixTarget\AppxManifest.xml" -Value $appxManifest -Force

$filesForMsix = @(
'dsc.exe',
'assertion.dsc.resource.json',
'group.dsc.resource.json',
'parallel.dsc.resource.json',
'powershellgroup.dsc.resource.json',
'powershellgroup.resource.ps1',
'wmigroup.dsc.resource.json.optout',
'wmigroup.resource.ps1'
)

foreach ($file in $filesForMsix) {
Copy-Item "$target\$file" $msixTarget -ErrorAction Stop
}

# Necessary image assets need to be in source assets folder
$assets = @(
'Square150x150Logo'
'Square64x64Logo'
'Square44x44Logo'
'Square44x44Logo.targetsize-48'
'Square44x44Logo.targetsize-48_altform-unplated'
'StoreLogo'
)

New-Item -ItemType Directory "$msixTarget\assets" > $null
foreach ($asset in $assets) {
Copy-Item "$PSScriptRoot\packaging\assets\$asset.png" "$msixTarget\assets" -ErrorAction Stop
}

Write-Verbose "Creating priconfig.xml" -Verbose
& $makepri createconfig /o /cf (Join-Path $msixTarget "priconfig.xml") /dq en-US
if ($LASTEXITCODE -ne 0) {
throw "Failed to create priconfig.xml"
}

Write-Verbose "Creating resources.pri" -Verbose
Push-Location $msixTarget
& $makepri new /v /o /pr $msixTarget /cf (Join-Path $msixTarget "priconfig.xml")
Pop-Location
if ($LASTEXITCODE -ne 0) {
throw "Failed to create resources.pri"
}

Write-Verbose "Creating msix package" -Verbose
$packageName = "$productName-$productVersion-$arch"
& $makeappx pack /o /v /h SHA256 /d $msixTarget /p (Join-Path -Path (Get-Location) -ChildPath "$packageName.msix")
if ($LASTEXITCODE -ne 0) {
throw "Failed to create msix package"
}
Write-Verbose "Created $packageName.msix" -Verbose
}

$env:RUST_BACKTRACE=1
38 changes: 28 additions & 10 deletions dsc_lib/src/discovery/command_discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::fs::File;
use std::io::BufReader;
use std::path::Path;
use std::time::Duration;
use tracing::{debug, error, warn};
use tracing::{debug, error, trace, warn};

pub struct CommandDiscovery {
}
Expand All @@ -28,6 +28,7 @@ impl CommandDiscovery {
#[allow(clippy::too_many_lines)]
fn search_for_resources(required_resource_types: &[String]) -> Result<BTreeMap<String, DscResource>, DscError>
{
debug!("Searching for resources: {:?}", required_resource_types);
let return_all_resources = required_resource_types.len() == 1 && required_resource_types[0] == "*";

let multi_progress_bar = MultiProgress::new();
Expand All @@ -53,20 +54,37 @@ impl CommandDiscovery {
let mut resources: BTreeMap<String, DscResource> = BTreeMap::new();
let mut adapter_resources: Vec<String> = Vec::new();
let mut remaining_required_resource_types = required_resource_types.to_owned();
let mut using_custom_path = false;

// try DSC_RESOURCE_PATH env var first otherwise use PATH
let path_env = match env::var_os("DSC_RESOURCE_PATH") {
Some(value) => value,
None => {
match env::var_os("PATH") {
Some(value) => value,
None => {
return Err(DscError::Operation("Failed to get PATH environment variable".to_string()));
}
let path_env = if let Some(value) = env::var_os("DSC_RESOURCE_PATH") {
debug!("Using DSC_RESOURCE_PATH: {:?}", value.to_string_lossy());
using_custom_path = true;
value
} else {
trace!("DSC_RESOURCE_PATH not set, trying PATH");
match env::var_os("PATH") {
Some(value) => {
debug!("Using PATH: {:?}", value.to_string_lossy());
value
},
None => {
return Err(DscError::Operation("Failed to get PATH environment variable".to_string()));
}
}
};

for path in env::split_paths(&path_env) {
let mut paths = env::split_paths(&path_env).collect::<Vec<_>>();

// add exe home to start of path
if !using_custom_path {
if let Some(exe_home) = env::current_exe()?.parent() {
debug!("Adding exe home to path: {}", exe_home.to_string_lossy());
paths.insert(0, exe_home.to_path_buf());
}
}

for path in paths {
if path.exists() && path.is_dir() {
for entry in path.read_dir().unwrap() {
let entry = entry.unwrap();
Expand Down
Binary file added packaging/assets/Square150x150Logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packaging/assets/Square44x44Logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packaging/assets/Square64x64Logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packaging/assets/StoreLogo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading