diff --git a/GenerateSingleSolution.ps1 b/GenerateSingleSolution.ps1 new file mode 100644 index 0000000..219efc4 --- /dev/null +++ b/GenerateSingleSolution.ps1 @@ -0,0 +1,227 @@ +<# +.SYNOPSIS + Uses the dotnet template tool to copy and rename project heads to run sample code for different platforms. + +.DESCRIPTION + This is used to centralize configuration and reduce duplication of copying these heads for every project. + This script also generates a solution for the project and will open Visual Studio. + +.PARAMETER componentPath + Folder for the project to copy the project heads to. + +.PARAMETER MultiTargets + Specifies the MultiTarget TFM(s) to include for building the components. The default value is 'uwp', 'wasm', 'wasdk'. + +.PARAMETER ExcludeMultiTargets + Specifies the MultiTarget TFM(s) to exclude for building the components. The default value excludes targets that require additional tooling or workloads to build. Run uno-check to install the required workloads. + +.PARAMETER Component + The name of the components to generate project and solution references for. Defaults to an empty string. + +.PARAMETER WinUIMajorVersion + Specifies the WinUI major version to use when building an Uno head. Also decides the package id and dependency variant. The default value is '2'. + +.PARAMETER UseDiagnostics + Add extra diagnostic output to running slngen, such as a binlog, etc... + +.EXAMPLE + C:\PS> .\GenerateSingleSampleHeads -componentPath components\testproj + Builds project heads for component in testproj directory. + +.NOTES + Author: Windows Community Toolkit Labs Team + Date: Feb 9, 2023 +#> +Param ( + [ValidateSet('all', 'wasm', 'uwp', 'wasdk', 'wpf', 'linuxgtk', 'macos', 'ios', 'android')] + [Alias("mt")] + [string[]]$MultiTargets = @('uwp', 'wasm', 'wasdk'), + + [string[]]$ExcludeMultiTargets = @(), + + [Alias("winui")] + [int]$WinUIMajorVersion = 3, + + [Alias("c")] + [string]$Component, + + [Parameter(HelpMessage = "The path to the containing folder for a component where sample heads should be generated.")] + [string]$componentPath, + + [Parameter(HelpMessage = "Add extra diagnostic output to slngen generator.")] + [switch]$UseDiagnostics = $false +) + +if ($null -ne $Env:Path -and $Env:Path.ToLower().Contains("msbuild") -eq $false) { + Write-Host + Write-Host -ForegroundColor Red "Please run from a command window that has MSBuild.exe on the PATH" + Write-Host + Write-Host "Press any key to continue" + [void]$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") + + Exit +} + +# If Component (name) is provided, use a known path to find componentPath +if ($null -ne $Component -and $Component -ne '') +{ + $componentPath = Get-Item "$PSScriptRoot/../components/$Component/" +} + +# If componentPath is not provided or is an empty string, use the current directory $pwd +if ($null -eq $componentPath -or $componentPath -eq '') +{ + $componentPath = $pwd +} + +# Component check +# ----------------- + +# Check that the component path exists +if (-not (Test-Path $componentPath -PathType Container)) +{ + Write-Error "Component path '$componentPath' does not exist." + Exit +} + +# Check that the path contains a src folder +if (-not (Test-Path "$componentPath/src" -PathType Container)) +{ + Write-Error "Provided path '$componentPath' does not contain a 'src' folder and may not be a component." + Exit +} + +# Multitarget handling +# ----------------- + +if ($MultiTargets.Contains('all')) { + $MultiTargets = @('wasm', 'uwp', 'wasdk', 'wpf', 'linuxgtk', 'macos', 'ios', 'android') +} + +if ($null -eq $ExcludeMultiTargets) +{ + $ExcludeMultiTargets = @() +} + +# Both uwp and wasdk share a targetframework. Both cannot be enabled at once. +# If both are supplied, remove one based on WinUIMajorVersion. +if ($MultiTargets.Contains('uwp') -and $MultiTargets.Contains('wasdk')) +{ + if ($WinUIMajorVersion -eq 2) + { + $ExcludeMultiTargets = $ExcludeMultiTargets + 'wasdk' + } + else + { + $ExcludeMultiTargets = $ExcludeMultiTargets + 'uwp' + } +} + +$MultiTargets = $MultiTargets | Where-Object { $_ -notin $ExcludeMultiTargets } + +# Generate required props for preferences +& $PSScriptRoot/MultiTarget/UseTargetFrameworks.ps1 -MultiTargets $MultiTargets +& $PSScriptRoot/MultiTarget/UseUnoWinUI.ps1 $WinUIMajorVersion + +# Head generation +# ----------------- + +$headsFolderName = "heads" +$componentName = (Get-Item $componentPath -ErrorAction Stop).Name + +$outputHeadsDir = "$componentPath\$headsFolderName"; + +# Remove existing heads directory to refresh +Write-Output "Removing existing heads directory: $outputHeadsDir" +Remove-Item -Recurse -Force $outputHeadsDir -ErrorAction SilentlyContinue; + +# Intall our heads as a temporary template +Write-Output "Installing SingleComponent template" +dotnet new --install "$PSScriptRoot/ProjectHeads/SingleComponent" --force + +# We need to copy files and run slngen from the target directory path +Push-Location $componentPath + +# Copy and rename projects +# Set output folder to 'heads' instead of default +Write-Output "Generating heads for $componentName in $outputHeadsDir" +dotnet new ct-tooling-heads -n $componentName -o $headsFolderName + +# Remove template, as just for script +Write-Output "Uninstalling SingleComponent template" +dotnet new --uninstall "$PSScriptRoot/ProjectHeads/SingleComponent" + +# Generate Solution +# ------------------ + +# Projects to include +$projects = [System.Collections.ArrayList]::new() + +# Include all projects in component folder +[void]$projects.Add(".\*\*.*proj") + +# Install slgnen +dotnet tool restore + +$generatedSolutionFilePath = "$componentPath/$componentName.sln" +$platforms = '"Any CPU;x64;x86;ARM64"' +$slngenConfig = "--folders true --collapsefolders true --ignoreMainProject" + +# Remove previous file if it exists +if (Test-Path -Path $generatedSolutionFilePath) +{ + Remove-Item $generatedSolutionFilePath + Write-Host "Removed previous solution file" +} + +# Deployable sample gallery heads +Write-Output "Generating solution for $componentName in $generatedSolutionFilePath" + +# All heads are included by default since they reside in the same folder as the component. +# Remove any heads that are not required for the solution. +# TODO: this handles separate project heads, but won't directly handle the unified Skia head from Uno. +# Once we have that, just do a transform on the csproj filename inside this loop to decide the same csproj for those separate MultiTargets. +foreach ($multitarget in $MultiTargets) { + # capitalize first letter, avoid case sensitivity issues on linux + $csprojFileNamePartForMultiTarget = $multitarget.substring(0,1).ToUpper() + $multitarget.Substring(1).ToLower() + + $path = "$outputHeadsDir\**\*$csprojFileNamePartForMultiTarget.csproj"; + + if (Test-Path $path) { + # iterate the wildcards caught by $path + foreach ($foundItem in Get-ChildItem $path) + { + $projects = $projects + $foundItem.FullName + } + } + else { + Write-Warning "No project head could be found at $path for MultiTarget $multitarget. Skipping." + } +} + +# Include common dependencies required for solution to build +$projects = $projects + "$PSScriptRoot\CommunityToolkit.App.Shared\**\*.*proj" +$projects = $projects + "$PSScriptRoot\CommunityToolkit.Tests.Shared\**\*.*proj" +$projects = $projects + "$PSScriptRoot\CommunityToolkit.Tooling.SampleGen\*.csproj" +$projects = $projects + "$PSScriptRoot\CommunityToolkit.Tooling.TestGen\*.csproj" +$projects = $projects + "$PSScriptRoot\CommunityToolkit.Tooling.XamlNamedPropertyRelay\*.csproj" + +if ($UseDiagnostics.IsPresent) +{ + $sdkoptions = " -d" + $diagnostics = '-bl:slngen.binlog --consolelogger:"ShowEventId;Summary;Verbosity=Detailed" --filelogger:"LogFile=slngen.log;Append;Verbosity=Diagnostic;Encoding=UTF-8" ' +} +else +{ + $sdkoptions = "" + $diagnostics = "" +} + +$cmd = "dotnet$sdkoptions tool run slngen -o $generatedSolutionFilePath $slngenConfig $diagnostics--platform $platforms $($projects -Join ' ')" + +Write-Output "Running Command: $cmd" + +Invoke-Expression $cmd + +# go back to main working directory +Pop-Location diff --git a/MultiTarget/Extra.props b/MultiTarget/Extra.props index 1896016..8fcffc6 100644 --- a/MultiTarget/Extra.props +++ b/MultiTarget/Extra.props @@ -10,6 +10,8 @@ <SupportedOSPlatformVersion>$(TargetPlatformMinVersion)</SupportedOSPlatformVersion> <TargetPlatformVersion Condition="'$(MultiTargetPlatformIdentifier)' == 'windows'">10.0.26100.0</TargetPlatformVersion> <TargetPlatformVersion Condition="'$(MultiTargetPlatformIdentifier)' != 'windows'">10.0.19041.0</TargetPlatformVersion> + + <Platforms>x86;x64;arm64</Platforms> </PropertyGroup> <!-- Workaround, improved error message when consuming from Uno projects with mismatched TFMs --> @@ -20,9 +22,7 @@ <None PackagePath="lib/net7.0-windows10.0.18362" Include="$(MSBuildThisFileDirectory)/_._" Pack="true" /> </ItemGroup> - <PropertyGroup Condition="'$(IsUwp)' == 'true'"> - <Platforms>x86;x64;arm64</Platforms> - + <PropertyGroup Condition="'$(IsUwp)' == 'true'"> <WindowsSdkPackageVersion Condition="'$(MultiTargetPlatformIdentifier)' == 'windows'">10.0.26100.57</WindowsSdkPackageVersion> <RuntimeIdentifiers Condition="'$(MultiTargetPlatformIdentifier)' == 'windows'">win-x86;win-x64;win-arm64</RuntimeIdentifiers> </PropertyGroup> diff --git a/ProjectHeads/GenerateSingleSampleHeads.ps1 b/ProjectHeads/GenerateSingleSampleHeads.ps1 index db2a826..0bbee40 100644 --- a/ProjectHeads/GenerateSingleSampleHeads.ps1 +++ b/ProjectHeads/GenerateSingleSampleHeads.ps1 @@ -34,10 +34,10 @@ Param ( [Alias("mt")] [string[]]$MultiTargets = @('uwp', 'wasm', 'wasdk'), - [string[]]$ExcludeMultiTargets, + [string[]]$ExcludeMultiTargets = @(), [Alias("winui")] - [int]$WinUIMajorVersion = 2, + [int]$WinUIMajorVersion = 3, [Parameter(HelpMessage = "The path to the containing folder for a component where sample heads should be generated.")] [string]$componentPath, @@ -46,147 +46,6 @@ Param ( [switch]$UseDiagnostics = $false ) -if ($null -ne $Env:Path -and $Env:Path.ToLower().Contains("msbuild") -eq $false) { - Write-Host - Write-Host -ForegroundColor Red "Please run from a command window that has MSBuild.exe on the PATH" - Write-Host - Write-Host "Press any key to continue" - [void]$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") - - Exit -} - -# If componentPath is not provided or is an empty string, use the $PSScriptRoot -if ($null -eq $componentPath -or $componentPath -eq '') -{ - $componentPath = $pwd -} - -# Multitarget handling -# ----------------- - -if ($MultiTargets.Contains('all')) { - $MultiTargets = @('wasm', 'uwp', 'wasdk', 'wpf', 'linuxgtk', 'macos', 'ios', 'android') -} - -if ($null -eq $ExcludeMultiTargets) -{ - $ExcludeMultiTargets = @() -} - -# Both uwp and wasdk share a targetframework. Both cannot be enabled at once. -# If both are supplied, remove one based on WinUIMajorVersion. -if ($MultiTargets.Contains('uwp') -and $MultiTargets.Contains('wasdk')) -{ - if ($WinUIMajorVersion -eq 2) - { - $ExcludeMultiTargets = $ExcludeMultiTargets + 'wasdk' - } - else - { - $ExcludeMultiTargets = $ExcludeMultiTargets + 'uwp' - } -} - -$MultiTargets = $MultiTargets | Where-Object { $_ -notin $ExcludeMultiTargets } - -# Generate required props for preferences -& $PSScriptRoot/../MultiTarget/UseTargetFrameworks.ps1 -MultiTargets $MultiTargets -& $PSScriptRoot/../MultiTarget/UseUnoWinUI.ps1 $WinUIMajorVersion - -# Head generation -# ----------------- - -$headsFolderName = "heads" -$componentName = (Get-Item $componentPath -ErrorAction Stop).Name - -$outputHeadsDir = "$componentPath/$headsFolderName"; - -# Remove existing heads directory to refresh -Remove-Item -Recurse -Force $outputHeadsDir -ErrorAction SilentlyContinue; - -# Intall our heads as a temporary template -dotnet new --install "$PSScriptRoot/SingleComponent" --force - -# We need to copy files and run slngen from the target directory path -Push-Location $componentPath - -# Copy and rename projects -# Set output folder to 'heads' instead of default -dotnet new ct-tooling-heads -n $componentName -o $headsFolderName - -# Remove template, as just for script -dotnet new --uninstall "$PSScriptRoot/SingleComponent" - -# Generate Solution -# ------------------ - -# Projects to include -$projects = [System.Collections.ArrayList]::new() - -# Include all projects in component folder -[void]$projects.Add(".\*\*.*proj") - -# Install slgnen -dotnet tool restore - -$generatedSolutionFilePath = "$componentPath/$componentName.sln" -$platforms = '"Any CPU;x64;x86;ARM64"' -$slngenConfig = "--folders true --collapsefolders true --ignoreMainProject" - -# Remove previous file if it exists -if (Test-Path -Path $generatedSolutionFilePath) -{ - Remove-Item $generatedSolutionFilePath - Write-Host "Removed previous solution file" -} - -# Deployable sample gallery heads -# All heads are included by default since they reside in the same folder as the component. -# Remove any heads that are not required for the solution. -# TODO: this handles separate project heads, but won't directly handle the unified Skia head from Uno. -# Once we have that, just do a transform on the csproj filename inside this loop to decide the same csproj for those separate MultiTargets. -foreach ($multitarget in $MultiTargets) { - # capitalize first letter, avoid case sensitivity issues on linux - $csprojFileNamePartForMultiTarget = $multitarget.substring(0,1).ToUpper() + $multitarget.Substring(1).ToLower() - - $path = "$outputHeadsDir\**\*$csprojFileNamePartForMultiTarget.csproj"; - - if (Test-Path $path) { - # iterate the wildcards caught by $path - foreach ($foundItem in Get-ChildItem $path) - { - $projects = $projects + $foundItem.FullName - } - } - else { - Write-Warning "No project head could be found at $path for MultiTarget $multitarget. Skipping." - } -} - -# Include common dependencies required for solution to build -$projects = $projects + "..\..\tooling\CommunityToolkit.App.Shared\**\*.*proj" -$projects = $projects + "..\..\tooling\CommunityToolkit.Tests.Shared\**\*.*proj" -$projects = $projects + "..\..\tooling\CommunityToolkit.Tooling.SampleGen\*.csproj" -$projects = $projects + "..\..\tooling\CommunityToolkit.Tooling.TestGen\*.csproj" -$projects = $projects + "..\..\tooling\CommunityToolkit.Tooling.XamlNamedPropertyRelay\*.csproj" - -if ($UseDiagnostics.IsPresent) -{ - $sdkoptions = " -d" - $diagnostics = '-bl:slngen.binlog --consolelogger:"ShowEventId;Summary;Verbosity=Detailed" --filelogger:"LogFile=slngen.log;Append;Verbosity=Diagnostic;Encoding=UTF-8" ' -} -else -{ - $sdkoptions = "" - $diagnostics = "" -} - -$cmd = "dotnet$sdkoptions tool run slngen -o $generatedSolutionFilePath $slngenConfig $diagnostics--platform $platforms $($projects -Join ' ')" - -Write-Output "Running Command: $cmd" - -Invoke-Expression $cmd - -# go back to main working directory -Pop-Location +# Use & and a separate script path variable to avoid issues with parameter passing +$scriptPath = "$PSScriptRoot/../GenerateSingleSolution.ps1" +& $scriptPath -MultiTargets $MultiTargets -ExcludeMultiTargets $ExcludeMultiTargets -WinUIMajorVersion $WinUIMajorVersion -UseDiagnostics:$UseDiagnostics -componentPath $componentPath \ No newline at end of file