|
| 1 | +<# |
| 2 | +.SYNOPSIS |
| 3 | + Uses the dotnet template tool to copy and rename project heads to run sample code for different platforms. |
| 4 | +
|
| 5 | +.DESCRIPTION |
| 6 | + This is used to centralize configuration and reduce duplication of copying these heads for every project. |
| 7 | + This script also generates a solution for the project and will open Visual Studio. |
| 8 | +
|
| 9 | +.PARAMETER componentPath |
| 10 | + Folder for the project to copy the project heads to. |
| 11 | +
|
| 12 | +.PARAMETER MultiTargets |
| 13 | + Specifies the MultiTarget TFM(s) to include for building the components. The default value is 'uwp', 'wasm', 'wasdk'. |
| 14 | +
|
| 15 | +.PARAMETER ExcludeMultiTargets |
| 16 | + 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. |
| 17 | +
|
| 18 | +.PARAMETER Component |
| 19 | + The name of the components to generate project and solution references for. Defaults to an empty string. |
| 20 | +
|
| 21 | +.PARAMETER WinUIMajorVersion |
| 22 | + 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'. |
| 23 | +
|
| 24 | +.PARAMETER UseDiagnostics |
| 25 | + Add extra diagnostic output to running slngen, such as a binlog, etc... |
| 26 | +
|
| 27 | +.EXAMPLE |
| 28 | + C:\PS> .\GenerateSingleSampleHeads -componentPath components\testproj |
| 29 | + Builds project heads for component in testproj directory. |
| 30 | +
|
| 31 | +.NOTES |
| 32 | + Author: Windows Community Toolkit Labs Team |
| 33 | + Date: Feb 9, 2023 |
| 34 | +#> |
| 35 | +Param ( |
| 36 | + [ValidateSet('all', 'wasm', 'uwp', 'wasdk', 'wpf', 'linuxgtk', 'macos', 'ios', 'android')] |
| 37 | + [Alias("mt")] |
| 38 | + [string[]]$MultiTargets = @('uwp', 'wasm', 'wasdk'), |
| 39 | + |
| 40 | + [string[]]$ExcludeMultiTargets = @(), |
| 41 | + |
| 42 | + [Alias("winui")] |
| 43 | + [int]$WinUIMajorVersion = 3, |
| 44 | + |
| 45 | + [Alias("c")] |
| 46 | + [string]$Component, |
| 47 | + |
| 48 | + [Parameter(HelpMessage = "The path to the containing folder for a component where sample heads should be generated.")] |
| 49 | + [string]$componentPath, |
| 50 | + |
| 51 | + [Parameter(HelpMessage = "Add extra diagnostic output to slngen generator.")] |
| 52 | + [switch]$UseDiagnostics = $false |
| 53 | +) |
| 54 | + |
| 55 | +if ($null -ne $Env:Path -and $Env:Path.ToLower().Contains("msbuild") -eq $false) { |
| 56 | + Write-Host |
| 57 | + Write-Host -ForegroundColor Red "Please run from a command window that has MSBuild.exe on the PATH" |
| 58 | + Write-Host |
| 59 | + Write-Host "Press any key to continue" |
| 60 | + [void]$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") |
| 61 | + |
| 62 | + Exit |
| 63 | +} |
| 64 | + |
| 65 | +# If Component (name) is provided, use a known path to find componentPath |
| 66 | +if ($null -ne $Component -and $Component -ne '') |
| 67 | +{ |
| 68 | + $componentPath = Get-Item "$PSScriptRoot/../components/$Component/" |
| 69 | +} |
| 70 | + |
| 71 | +# If componentPath is not provided or is an empty string, use the current directory $pwd |
| 72 | +if ($null -eq $componentPath -or $componentPath -eq '') |
| 73 | +{ |
| 74 | + $componentPath = $pwd |
| 75 | +} |
| 76 | + |
| 77 | +# Remove trailing slash |
| 78 | +$componentPath = $componentPath.TrimEnd('\').TrimEnd('/') |
| 79 | + |
| 80 | +# Component check |
| 81 | +# ----------------- |
| 82 | + |
| 83 | +# Check that the component path exists |
| 84 | +if (-not (Test-Path $componentPath -PathType Container)) |
| 85 | +{ |
| 86 | + Write-Error "Component path '$componentPath' does not exist." |
| 87 | + Exit |
| 88 | +} |
| 89 | + |
| 90 | +# Check that the path contains a src folder |
| 91 | +if (-not (Test-Path "$componentPath/src" -PathType Container)) |
| 92 | +{ |
| 93 | + Write-Error "Provided path '$componentPath' does not contain a 'src' folder and may not be a component." |
| 94 | + Exit |
| 95 | +} |
| 96 | + |
| 97 | +# Multitarget handling |
| 98 | +# ----------------- |
| 99 | + |
| 100 | +if ($MultiTargets.Contains('all')) { |
| 101 | + $MultiTargets = @('wasm', 'uwp', 'wasdk', 'wpf', 'linuxgtk', 'macos', 'ios', 'android') |
| 102 | +} |
| 103 | + |
| 104 | +if ($null -eq $ExcludeMultiTargets) |
| 105 | +{ |
| 106 | + $ExcludeMultiTargets = @() |
| 107 | +} |
| 108 | + |
| 109 | +# Both uwp and wasdk share a targetframework. Both cannot be enabled at once. |
| 110 | +# If both are supplied, remove one based on WinUIMajorVersion. |
| 111 | +if ($MultiTargets.Contains('uwp') -and $MultiTargets.Contains('wasdk')) |
| 112 | +{ |
| 113 | + if ($WinUIMajorVersion -eq 2) |
| 114 | + { |
| 115 | + $ExcludeMultiTargets = $ExcludeMultiTargets + 'wasdk' |
| 116 | + } |
| 117 | + else |
| 118 | + { |
| 119 | + $ExcludeMultiTargets = $ExcludeMultiTargets + 'uwp' |
| 120 | + } |
| 121 | +} |
| 122 | + |
| 123 | +$MultiTargets = $MultiTargets | Where-Object { $_ -notin $ExcludeMultiTargets } |
| 124 | + |
| 125 | +# Generate required props for preferences |
| 126 | +& $PSScriptRoot/MultiTarget/UseTargetFrameworks.ps1 -MultiTargets $MultiTargets |
| 127 | +& $PSScriptRoot/MultiTarget/UseUnoWinUI.ps1 $WinUIMajorVersion |
| 128 | + |
| 129 | +# Head generation |
| 130 | +# ----------------- |
| 131 | + |
| 132 | +$headsFolderName = "heads" |
| 133 | +$componentName = (Get-Item $componentPath -ErrorAction Stop).Name |
| 134 | + |
| 135 | +$outputHeadsDir = "$componentPath\$headsFolderName"; |
| 136 | + |
| 137 | +# Remove existing heads directory to refresh |
| 138 | +Write-Output "Removing existing heads directory: $outputHeadsDir" |
| 139 | +Remove-Item -Recurse -Force $outputHeadsDir -ErrorAction SilentlyContinue; |
| 140 | + |
| 141 | +# Intall our heads as a temporary template |
| 142 | +Write-Output "Installing SingleComponent template" |
| 143 | +dotnet new --install "$PSScriptRoot/ProjectHeads/SingleComponent" --force |
| 144 | + |
| 145 | +# We need to copy files and run slngen from the target directory path |
| 146 | +Push-Location $componentPath |
| 147 | + |
| 148 | +# Copy and rename projects |
| 149 | +# Set output folder to 'heads' instead of default |
| 150 | +Write-Output "Generating heads for $componentName in $outputHeadsDir" |
| 151 | +dotnet new ct-tooling-heads -n $componentName -o $headsFolderName |
| 152 | + |
| 153 | +# Remove template, as just for script |
| 154 | +Write-Output "Uninstalling SingleComponent template" |
| 155 | +dotnet new --uninstall "$PSScriptRoot/ProjectHeads/SingleComponent" |
| 156 | + |
| 157 | +# Generate Solution |
| 158 | +# ------------------ |
| 159 | + |
| 160 | +# Projects to include |
| 161 | +$projects = [System.Collections.ArrayList]::new() |
| 162 | + |
| 163 | +# Include all projects in component folder |
| 164 | +[void]$projects.Add(".\*\*.*proj") |
| 165 | + |
| 166 | +# Install slgnen |
| 167 | +dotnet tool restore |
| 168 | + |
| 169 | +$generatedSolutionFilePath = "$componentPath\$componentName.sln" |
| 170 | +$platforms = '"Any CPU;x64;x86;ARM64"' |
| 171 | +$slngenConfig = "--folders true --collapsefolders true --ignoreMainProject" |
| 172 | + |
| 173 | +# Remove previous file if it exists |
| 174 | +if (Test-Path -Path $generatedSolutionFilePath) |
| 175 | +{ |
| 176 | + Remove-Item $generatedSolutionFilePath |
| 177 | + Write-Host "Removed previous solution file" |
| 178 | +} |
| 179 | + |
| 180 | +# Deployable sample gallery heads |
| 181 | +Write-Output "Generating solution for $componentName in $generatedSolutionFilePath" |
| 182 | + |
| 183 | +# All heads are included by default since they reside in the same folder as the component. |
| 184 | +# Remove any heads that are not required for the solution. |
| 185 | +# TODO: this handles separate project heads, but won't directly handle the unified Skia head from Uno. |
| 186 | +# Once we have that, just do a transform on the csproj filename inside this loop to decide the same csproj for those separate MultiTargets. |
| 187 | +foreach ($multitarget in $MultiTargets) { |
| 188 | + # capitalize first letter, avoid case sensitivity issues on linux |
| 189 | + $csprojFileNamePartForMultiTarget = $multitarget.substring(0,1).ToUpper() + $multitarget.Substring(1).ToLower() |
| 190 | + |
| 191 | + $path = "$outputHeadsDir\**\*$csprojFileNamePartForMultiTarget.csproj"; |
| 192 | + |
| 193 | + if (Test-Path $path) { |
| 194 | + # iterate the wildcards caught by $path |
| 195 | + foreach ($foundItem in Get-ChildItem $path) |
| 196 | + { |
| 197 | + $projects = $projects + $foundItem.FullName |
| 198 | + } |
| 199 | + } |
| 200 | + else { |
| 201 | + Write-Warning "No project head could be found at $path for MultiTarget $multitarget. Skipping." |
| 202 | + } |
| 203 | +} |
| 204 | + |
| 205 | +# Include common dependencies required for solution to build |
| 206 | +$projects = $projects + "$PSScriptRoot\CommunityToolkit.App.Shared\**\*.*proj" |
| 207 | +$projects = $projects + "$PSScriptRoot\CommunityToolkit.Tests.Shared\**\*.*proj" |
| 208 | +$projects = $projects + "$PSScriptRoot\CommunityToolkit.Tooling.SampleGen\*.csproj" |
| 209 | +$projects = $projects + "$PSScriptRoot\CommunityToolkit.Tooling.TestGen\*.csproj" |
| 210 | +$projects = $projects + "$PSScriptRoot\CommunityToolkit.Tooling.XamlNamedPropertyRelay\*.csproj" |
| 211 | + |
| 212 | +if ($UseDiagnostics.IsPresent) |
| 213 | +{ |
| 214 | + $sdkoptions = " -d" |
| 215 | + $diagnostics = '-bl:slngen.binlog --consolelogger:"ShowEventId;Summary;Verbosity=Detailed" --filelogger:"LogFile=slngen.log;Append;Verbosity=Diagnostic;Encoding=UTF-8" ' |
| 216 | +} |
| 217 | +else |
| 218 | +{ |
| 219 | + $sdkoptions = "" |
| 220 | + $diagnostics = "" |
| 221 | +} |
| 222 | + |
| 223 | +$cmd = "dotnet$sdkoptions tool run slngen -o $generatedSolutionFilePath $slngenConfig $diagnostics--platform $platforms $($projects -Join ' ')" |
| 224 | + |
| 225 | +Write-Output "Running Command: $cmd" |
| 226 | + |
| 227 | +Invoke-Expression $cmd |
| 228 | + |
| 229 | +# go back to main working directory |
| 230 | +Pop-Location |
0 commit comments