Skip to content

Commit c70345e

Browse files
Fix up a ton of build tech debt
- Use a source generator for resgen - And for polyfills - Make the build script suck a bit less - Use directory build props
1 parent 0c691d0 commit c70345e

9 files changed

Lines changed: 196 additions & 346 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
## Ignore Visual Studio temporary files, build results, and
22
## files generated by popular Visual Studio add-ons.
33

4+
src/ClassExplorer/Generated/
5+
46
# Project specific files
57
tools/dotnet
68
tools/opencover

ClassExplorer.build.ps1

Lines changed: 154 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -18,42 +18,118 @@ $testModuleManifestSplat = @{
1818
}
1919

2020
$manifest = Test-ModuleManifest @testModuleManifestSplat
21-
22-
$script:Settings = @{
23-
Name = $moduleName
24-
Manifest = $manifest
25-
Version = $manifest.Version
26-
ShouldTest = $true
27-
}
28-
29-
$script:Folders = @{
30-
PowerShell = "$PSScriptRoot\module"
31-
CSharp = "$PSScriptRoot\src"
32-
Build = '{0}\src\{1}\bin\{2}' -f $PSScriptRoot, $moduleName, $Configuration
33-
Release = '{0}\Release\{1}\{2}' -f $PSScriptRoot, $moduleName, $manifest.Version
34-
Docs = "$PSScriptRoot\docs"
35-
Test = "$PSScriptRoot\test"
36-
Results = "$PSScriptRoot\testresults"
37-
}
38-
39-
$script:Discovery = @{
40-
HasDocs = Test-Path ('{0}\{1}\*.md' -f $Folders.Docs, $PSCulture)
41-
HasTests = Test-Path ('{0}\*.Tests.ps1' -f $Folders.Test)
42-
IsUnix = $PSVersionTable.PSEdition -eq "Core" -and -not $IsWindows
43-
}
21+
$moduleVersion = $manifest.Version
22+
23+
24+
# $script:Settings = @{
25+
# Name = $moduleName
26+
# Manifest = $manifest
27+
# Version = $manifest.Version
28+
# ShouldTest = $true
29+
# }
30+
31+
# $script:Folders = @{
32+
# PowerShell = "$PSScriptRoot\module"
33+
# CSharp = "$PSScriptRoot\src"
34+
# Build = '{0}\src\{1}\bin\{2}' -f $PSScriptRoot, $moduleName, $Configuration
35+
# Release = '{0}\Release\{1}\{2}' -f $PSScriptRoot, $moduleName, $manifest.Version
36+
# Docs = "$PSScriptRoot\docs"
37+
# Test = "$PSScriptRoot\test"
38+
# Results = "$PSScriptRoot\testresults"
39+
# }
40+
41+
# HasDocs = Test-Path ('{0}\{1}\*.md' -f $Folders.Docs, $PSCulture)
42+
# HasTests = Test-Path ('{0}\*.Tests.ps1' -f $Folders.Test)
43+
# $_IsUnix = $PSVersionTable.PSEdition -eq "Core" -and -not $IsWindows
4444

4545
$tools = "$PSScriptRoot\tools"
4646
$script:GetDotNet = Get-Command $tools\GetDotNet.ps1
4747
$script:AssertModule = Get-Command $tools\AssertRequiredModule.ps1
4848
$script:GetOpenCover = Get-Command $tools\GetOpenCover.ps1
4949
$script:GenerateSignatureMarkdown = Get-Command $tools\GenerateSignatureMarkdown.ps1
5050

51+
function RemakeFolder {
52+
[CmdletBinding()]
53+
param(
54+
[ValidateNotNullOrEmpty()]
55+
[string] $LiteralPath
56+
)
57+
end {
58+
$ErrorActionPreference = 'Stop'
59+
if (Test-Path -LiteralPath $LiteralPath) {
60+
Remove-Item -LiteralPath $LiteralPath -Recurse
61+
}
62+
63+
$null = New-Item -ItemType Directory -Path $LiteralPath
64+
}
65+
}
66+
67+
function GetArtifactPath {
68+
[CmdletBinding()]
69+
param(
70+
[ValidateNotNullOrEmpty()]
71+
[string] $FileName,
72+
73+
[switch] $Legacy
74+
)
75+
end {
76+
$moduleName = $script:ModuleName
77+
$config = $script:Configuration
78+
$legacyTarget = $script:LegacyTarget
79+
$modernTarget = $script:ModernTarget
80+
81+
$target = $modernTarget
82+
if ($Legacy) {
83+
$target = $legacyTarget
84+
}
85+
86+
if (-not $FileName) {
87+
return "./artifacts/publish/$moduleName/${config}_${target}"
88+
}
89+
90+
return "./artifacts/publish/$moduleName/${config}_${target}/$FileName"
91+
}
92+
}
93+
94+
task GetProjectInfo {
95+
$script:ModernTarget = $null
96+
$script:LegacyTarget = $null
97+
if (Test-Path -LiteralPath ./Directory.Build.props) {
98+
$content = Get-Content -Raw -LiteralPath ./Directory.Build.props
99+
if ($content -match '<ModernTarget>(?<target>[^<]+)</ModernTarget>') {
100+
$script:ModernTarget = $matches['target']
101+
}
102+
103+
if ($content -match '<LegacyTarget>(?<target>[^<]+)</LegacyTarget>') {
104+
$script:LegacyTarget = $matches['target']
105+
}
106+
}
107+
108+
109+
$script:ModuleName = $ModuleName = 'ClassExplorer'
110+
$testModuleManifestSplat = @{
111+
ErrorAction = 'Ignore'
112+
WarningAction = 'Ignore'
113+
Path = "./module/$ModuleName.psd1"
114+
}
115+
116+
$manifest = Test-ModuleManifest @testModuleManifestSplat
117+
$script:ModuleVersion = $manifest.Version
118+
$script:_IsWindows = $true
119+
$runtimeInfoType = 'System.Runtime.InteropServices.RuntimeInformation' -as [type]
120+
try {
121+
if ($null -ne $runtimeInfoType) {
122+
$script:_IsWindows = $runtimeInfoType::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::Windows)
123+
}
124+
} catch { }
125+
}
126+
51127
task AssertDotNet {
52-
$script:dotnet = & $GetDotNet -Unix:$Discovery.IsUnix
128+
$script:dotnet = & $GetDotNet -Unix:$script:_IsWindows
53129
}
54130

55131
task AssertOpenCover -If { $GenerateCodeCoverage.IsPresent } {
56-
if ($Discovery.IsUnix) {
132+
if (-not $script:_IsWindows) {
57133
Write-Warning 'Generating code coverage from .NET core is currently unsupported, disabling code coverage generation.'
58134
$script:GenerateCodeCoverage = $false
59135
return
@@ -63,66 +139,77 @@ task AssertOpenCover -If { $GenerateCodeCoverage.IsPresent } {
63139
}
64140

65141
task AssertRequiredModules {
66-
& $AssertModule Pester 5.3.0 -Force:$Force.IsPresent
67-
& $AssertModule InvokeBuild 5.8.4 -Force:$Force.IsPresent
142+
& $AssertModule Pester 5.7.1 -Force:$Force.IsPresent
143+
& $AssertModule InvokeBuild 5.14.22 -Force:$Force.IsPresent
68144
& $AssertModule platyPS 0.14.2 -Force:$Force.IsPresent
69-
& $AssertModule Yayaml 0.1.1 -Force:$Force.IsPresent
145+
& $AssertModule Yayaml 0.7.0 -Force:$Force.IsPresent
70146
}
71147

72148
task AssertDevDependencies -Jobs AssertDotNet, AssertOpenCover, AssertRequiredModules
73149

74150
task Clean {
75-
if ($PSScriptRoot -and (Test-Path $PSScriptRoot\Release)) {
76-
Remove-Item $PSScriptRoot\Release -Recurse
77-
}
78-
79-
$null = New-Item $Folders.Release -ItemType Directory
80-
if (Test-Path $Folders.Results) {
81-
Remove-Item $Folders.Results -Recurse
82-
}
83-
84-
$null = New-Item $Folders.Results -ItemType Directory
151+
RemakeFolder ./Release
152+
RemakeFolder ./testresults
85153
& $dotnet clean --verbosity quiet -nologo
86154
}
87155

88-
task BuildDocs -If { $Discovery.HasDocs } {
89-
$sourceDocs = "$PSScriptRoot\docs\$PSCulture"
90-
$releaseDocs = '{0}\{1}' -f $Folders.Release, $PSCulture
156+
task BuildDocs -If { Test-Path ./docs/$PSCulture/*.md } {
157+
$releaseDocs = "./Release/ClassExplorer/$moduleVersion"
158+
$null = New-Item $releaseDocs/$PSCulture -ItemType Directory -Force -ErrorAction Ignore
159+
$null = New-ExternalHelp -Path ./docs/$PSCulture -OutputPath $releaseDocs/$PSCulture
91160

92-
$null = New-Item $releaseDocs -ItemType Directory -Force -ErrorAction SilentlyContinue
93-
$null = New-ExternalHelp -Path $sourceDocs -OutputPath $releaseDocs
94-
95-
& $GenerateSignatureMarkdown.Source -AboutHelp $releaseDocs\about_Type_Signatures.help.txt
96-
& $GenerateSignatureMarkdown.Source $PSScriptRoot\docs\en-US\about_Type_Signatures.help.md
161+
& $GenerateSignatureMarkdown.Source -AboutHelp $releaseDocs/about_Type_Signatures.help.txt
162+
& $GenerateSignatureMarkdown.Source ./docs/en-US/about_Type_Signatures.help.md
97163
}
98164

99165
task BuildDll {
100-
if (-not $Discovery.IsUnix) {
101-
& $dotnet publish --configuration $Configuration --framework net471 --verbosity quiet -nologo
166+
if ($script:_IsWindows) {
167+
& $dotnet publish --configuration $Configuration --framework $script:LegacyTarget --verbosity quiet -nologo
102168
}
103-
& $dotnet publish --configuration $Configuration --framework netcoreapp3.1 --verbosity quiet -nologo
169+
170+
& $dotnet publish --configuration $Configuration --framework $script:ModernTarget --verbosity quiet -nologo
104171
}
105172

106173
task CopyToRelease {
107-
$powershellSource = '{0}\*' -f $Folders.PowerShell
108-
$release = $Folders.Release
109-
$releaseDesktopBin = "$release\bin\Desktop"
110-
$releaseCoreBin = "$release\bin\Core"
111-
$sourceDesktopBin = '{0}\net471\publish\*' -f $Folders.Build
112-
$sourceCoreBin = '{0}\netcoreapp3.1\publish\*' -f $Folders.Build
113-
Copy-Item -Path $powershellSource -Destination $release -Recurse -Force
174+
$version = $script:ModuleVersion
175+
$modern = $script:ModernTarget
176+
$legacy = $script:LegacyTarget
114177

115-
if (-not $Discovery.IsUnix) {
116-
$null = New-Item $releaseDesktopBin -Force -ItemType Directory
117-
Copy-Item -Path $sourceDesktopBin -Destination $releaseDesktopBin -Force
178+
$releasePath = "./Release/ClassExplorer/$version"
179+
if (-not (Test-Path -LiteralPath $releasePath)) {
180+
$null = New-Item $releasePath -ItemType Directory
118181
}
119182

120-
$null = New-Item $releaseCoreBin -Force -ItemType Directory
121-
Copy-Item -Path $sourceCoreBin -Destination $releaseCoreBin -Force
183+
Copy-Item -Path ./module/* -Destination $releasePath -Recurse -Force
184+
185+
if ($script:_IsWindows) {
186+
$null = New-Item $releasePath/bin/Legacy -Force -ItemType Directory
187+
$legacyFiles = (
188+
'ClassExplorer.dll',
189+
'ClassExplorer.pdb',
190+
'System.Buffers.dll',
191+
'System.Collections.Immutable.dll',
192+
'System.Memory.dll',
193+
'System.Numerics.Vectors.dll',
194+
'System.Runtime.CompilerServices.Unsafe.dll')
195+
196+
foreach ($file in $legacyFiles) {
197+
Copy-Item -Force -LiteralPath ./artifacts/publish/ClassExplorer/${Configuration}_$legacy/$file -Destination $releasePath/bin/Legacy
198+
}
199+
}
200+
201+
$null = New-Item $releasePath/bin/Modern -Force -ItemType Directory
202+
$modernFiles = (
203+
'ClassExplorer.dll',
204+
'ClassExplorer.pdb',
205+
'ClassExplorer.deps.json')
206+
foreach ($file in $modernFiles) {
207+
Copy-Item -Force -LiteralPath ./artifacts/publish/ClassExplorer/${Configuration}_$modern/$file -Destination $releasePath/bin/Modern
208+
}
122209
}
123210

124-
task DoTest -If { $Discovery.HasTests -and $Settings.ShouldTest } {
125-
if ($Discovery.IsUnix) {
211+
task DoTest -If { Test-Path ./test/*.ps1 } {
212+
if (-not $script:_IsWindows) {
126213
$scriptString = '
127214
$projectPath = "{0}"
128215
Invoke-Pester "$projectPath" -OutputFormat NUnitXml -OutputFile "$projectPath\testresults\pester.xml"
@@ -141,16 +228,16 @@ task DoTest -If { $Discovery.HasTests -and $Settings.ShouldTest } {
141228
$scriptString))
142229

143230
$powershellCommand = 'powershell'
144-
if ($Discovery.IsUnix) {
231+
if ($PSVersionTable.PSVersion.Major -gt 5) {
145232
$powershellCommand = 'pwsh'
146233
}
147234

148-
$powershell = (Get-Command $powershellCommand).Source
235+
$powershell = (Get-Command -CommandType Application $powershellCommand).Source
149236

150237
if ($GenerateCodeCoverage.IsPresent) {
151238
# OpenCover needs full pdb's. I'm very open to suggestions for streamlining this...
152239
# & $dotnet clean
153-
& $dotnet publish --configuration $Configuration --framework net471 --verbosity quiet -nologo /p:DebugType=Full
240+
& $dotnet publish --configuration $Configuration --framework $script:LegacyTarget --verbosity quiet --nologo /p:DebugType=Full
154241

155242
$moduleName = $Settings.Name
156243
$release = '{0}\bin\Desktop\{1}' -f $Folders.Release, $moduleName
@@ -212,7 +299,7 @@ task DoPublish {
212299
Publish-Module -Name $Folders.Release -NuGetApiKey $apiKey -Force:$Force.IsPresent
213300
}
214301

215-
task Build -Jobs AssertDevDependencies, Clean, BuildDll, CopyToRelease, BuildDocs
302+
task Build -Jobs GetProjectInfo, AssertDevDependencies, Clean, BuildDll, CopyToRelease, BuildDocs
216303

217304
task Test -Jobs Build, DoTest
218305

Directory.Build.props

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project>
2+
<!-- See https://aka.ms/dotnet/msbuild/customize for more details on customizing your build -->
3+
<PropertyGroup>
4+
5+
<ModernTarget>net8.0</ModernTarget>
6+
<LegacyTarget>net471</LegacyTarget>
7+
<ArtifactsPath>$(MSBuildThisFileDirectory)artifacts</ArtifactsPath>
8+
9+
</PropertyGroup>
10+
</Project>

module/ClassExplorer.psm1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
if (-not $PSVersionTable.PSEdition -or $PSVersionTable.PSEdition -eq 'Desktop') {
2-
Import-Module "$PSScriptRoot/bin/Desktop/ClassExplorer.dll"
2+
Import-Module "$PSScriptRoot/bin/Legacy/ClassExplorer.dll"
33
} else {
4-
Import-Module "$PSScriptRoot/bin/Core/ClassExplorer.dll"
4+
Import-Module "$PSScriptRoot/bin/Modern/ClassExplorer.dll"
55
}
66

77
if (-not $env:CLASS_EXPLORER_TRUE_CHARACTER) {
Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,52 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netcoreapp3.1;net471</TargetFrameworks>
5-
<!-- <TargetFrameworks>net471;netcoreapp3.1</TargetFrameworks> -->
4+
<TargetFrameworks>$(ModernTarget);$(LegacyTarget)</TargetFrameworks>
5+
<!-- <TargetFrameworks>$(LegacyTarget);$(ModernTarget)</TargetFrameworks> -->
66
<LangVersion>preview</LangVersion>
77
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
88
<Nullable>enable</Nullable>
9-
<!-- <AssemblyName>ClassExplorer2</AssemblyName> -->
9+
<ResXGenerator_NullForgivingOperators>true</ResXGenerator_NullForgivingOperators>
1010
</PropertyGroup>
1111

1212
<ItemGroup>
13+
<PackageReference Include="Aigamo.ResXGenerator" Version="4.2.0">
14+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
15+
<PrivateAssets>all</PrivateAssets>
16+
</PackageReference>
17+
<PackageReference Include="PolySharp" Version="1.15.0">
18+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19+
<PrivateAssets>all</PrivateAssets>
20+
</PackageReference>
21+
1322
<PackageReference Include="PowerShellStandard.Library" Version="5.1.1" PrivateAssets="all" />
14-
<PackageReference Include="System.Memory" Version="4.5.4" />
1523
</ItemGroup>
1624

17-
<ItemGroup Condition=" '$(TargetFramework)' == 'net471' ">
25+
<ItemGroup Condition=" '$(TargetFramework)' == '$(LegacyTarget)' ">
1826
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
27+
<PackageReference Include="System.Memory" Version="4.5.4" />
1928
</ItemGroup>
2029

2130
<ItemGroup>
22-
<!--
23-
omnisharp-vscode doesn't seem to pick this up without this.
24-
For now we'll ignore the compiler warning
25-
-->
26-
<Compile Include="$(IntermediateOutputPath)\SR.Designer.cs" />
2731
<EmbeddedResource Update="SR.resx">
28-
<Generator>ResXFileCodeGenerator</Generator>
29-
<StronglyTypedFileName>$(IntermediateOutputPath)\SR.Designer.cs</StronglyTypedFileName>
30-
<LastGenOutput>SR.Designer.cs</LastGenOutput>
32+
<PartialClass>true</PartialClass>
33+
<GenerateCode>true</GenerateCode>
34+
<GenerateResource>false</GenerateResource>
3135
<StronglyTypedLanguage>CSharp</StronglyTypedLanguage>
3236
<StronglyTypedNamespace>ClassExplorer</StronglyTypedNamespace>
3337
<StronglyTypedClassName>SR</StronglyTypedClassName>
3438
</EmbeddedResource>
3539
</ItemGroup>
3640

37-
<Target Name="FixResGen" BeforeTargets="AfterResGen">
38-
<Exec ConsoleToMsBuild="true" Command="pwsh -NoLogo -NoProfile -NonInteractive -Command &quot;Set-Content '$(IntermediateOutputPath)\SR.Designer.cs' ((Get-Content '$(IntermediateOutputPath)\SR.Designer.cs' -Raw) -replace '(?m)^(\s*internal )class', '$1partial class')&quot;" />
39-
</Target>
41+
<PropertyGroup>
42+
<!-- Create files for source generated code -->
43+
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
44+
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
45+
</PropertyGroup>
46+
47+
<ItemGroup>
48+
<!-- Exclude the output of source generators from the compilation -->
49+
<Compile Remove="$(CompilerGeneratedFilesOutputPath)/**/*.cs" />
50+
</ItemGroup>
4051

4152
</Project>

src/ClassExplorer/IsExternalInit.cs

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)