-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDirectory.Build.targets
More file actions
326 lines (306 loc) · 27.4 KB
/
Copy pathDirectory.Build.targets
File metadata and controls
326 lines (306 loc) · 27.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
<Project>
<!-- Imported after the project body and the SDK targets, so conditions here see final property values. -->
<Target Name="CheatEngineClientRequireProjectReadme"
BeforeTargets="Pack"
Condition="'$(IsPackable)' == 'true'">
<Error Condition="!Exists('$(MSBuildProjectDirectory)/README.md')"
Code="CHEATENGINECLIENT9001"
Text="$(MSBuildProjectName) has no README.md next to its project file."/>
</Target>
<Target Name="CheatEngineClientValidateShippingPackageSettings"
BeforeTargets="Pack"
Condition="$(_CheatEngineClientFolder.StartsWith('src/', System.StringComparison.OrdinalIgnoreCase)) or $(_CheatEngineClientFolder.StartsWith('libs/', System.StringComparison.OrdinalIgnoreCase))">
<Error Condition="'$(TargetFramework)' != 'net10.0'"
Code="CHEATENGINECLIENT9002"
Text="Shipping projects must target net10.0."/>
<Error Condition="'$(LangVersion)' != '14.0'"
Code="CHEATENGINECLIENT9003"
Text="Shipping projects must use C# 14."/>
<Error Condition="'$(IsAotCompatible)' != 'true'"
Code="CHEATENGINECLIENT9004"
Text="Shipping projects must enable Native AOT compatibility analysis."/>
<Error Condition="'$(VerifyReferenceAotCompatibility)' != 'true'"
Code="CHEATENGINECLIENT9005"
Text="Shipping projects must verify AOT compatibility of their references."/>
<Error Condition="'$(GenerateDocumentationFile)' != 'true'"
Code="CHEATENGINECLIENT9006"
Text="Shipping projects must generate XML documentation."/>
<Error Condition="'$(EnablePackageValidation)' != 'true'"
Code="CHEATENGINECLIENT9007"
Text="Shipping projects must enable package validation."/>
<Error Condition="'$(VerifyReferenceTrimCompatibility)' != 'true'"
Code="CHEATENGINECLIENT9008"
Text="Shipping projects must verify trim compatibility of their references."/>
</Target>
<Target Name="CheatEngineClientValidatePublishedDependencyGraph"
BeforeTargets="Pack">
<ItemGroup>
<!-- Pack augments ProjectReference with transitive projects. Keep only references declared by this project. -->
<!-- Compiler-only project references are analyzer assets, not runtime Client-layer dependencies. -->
<_CheatEngineClientDirectProjectReference Include="@(ProjectReference)"
Condition="'%(ProjectReference.DefiningProjectName)' == '$(MSBuildProjectName)' and '%(ProjectReference.ReferenceOutputAssembly)' != 'false'"/>
<_CheatEngineClientSdkReference Include="@(PackageReference)"
Condition="'%(PackageReference.Identity)' == 'CheatEngine.SDK' and '%(PackageReference.DefiningProjectName)' == '$(MSBuildProjectName)'"/>
<_CheatEngineClientSdkRangeReference Include="@(_CheatEngineClientSdkReference)"
Condition="'%(_CheatEngineClientSdkReference.VersionOverride)' == '$(CheatEngineSdkVersionRange)'"/>
</ItemGroup>
<PropertyGroup>
<_CheatEngineClientProjectReferences>@(_CheatEngineClientDirectProjectReference->'%(Filename)')</_CheatEngineClientProjectReferences>
</PropertyGroup>
<Error Condition="'$(MSBuildProjectName)' == 'CheatEngine.Client.Abstractions' and '$(_CheatEngineClientProjectReferences)' != ''"
Code="CHEATENGINECLIENT9010"
Text="CheatEngine.Client.Abstractions cannot project-reference another Client layer."/>
<Error Condition="'$(MSBuildProjectName)' == 'CheatEngine.Client.Fluent' and '$(_CheatEngineClientProjectReferences)' != 'CheatEngine.Client.Abstractions'"
Code="CHEATENGINECLIENT9011"
Text="CheatEngine.Client.Fluent must reference only CheatEngine.Client.Abstractions."/>
<Error Condition="'$(MSBuildProjectName)' == 'CheatEngine.Client.Core' and '$(_CheatEngineClientProjectReferences)' != 'CheatEngine.Client.Abstractions'"
Code="CHEATENGINECLIENT9012"
Text="CheatEngine.Client.Core must reference only CheatEngine.Client.Abstractions."/>
<Error Condition="'$(MSBuildProjectName)' == 'CheatEngine.Client.Extensions.DependencyInjection' and '$(_CheatEngineClientProjectReferences)' != 'CheatEngine.Client.Abstractions;CheatEngine.Client.Core'"
Code="CHEATENGINECLIENT9013"
Text="CheatEngine.Client.Extensions.DependencyInjection must reference Abstractions then Core."/>
<Error Condition="'$(MSBuildProjectName)' == 'CheatEngine.Client.Hosting' and '$(_CheatEngineClientProjectReferences)' != 'CheatEngine.Client.Extensions.DependencyInjection'"
Code="CHEATENGINECLIENT9014"
Text="CheatEngine.Client.Hosting must reference only CheatEngine.Client.Extensions.DependencyInjection."/>
<Error Condition="'$(MSBuildProjectName)' == 'CheatEngine.Client' and '$(_CheatEngineClientProjectReferences)' != 'CheatEngine.Client.Fluent;CheatEngine.Client.Hosting'"
Code="CHEATENGINECLIENT9015"
Text="CheatEngine.Client must reference only CheatEngine.Client.Fluent and CheatEngine.Client.Hosting."/>
<Error Condition="('$(MSBuildProjectName)' == 'CheatEngine.Client.Abstractions' or '$(MSBuildProjectName)' == 'CheatEngine.Client.Core' or '$(MSBuildProjectName)' == 'CheatEngine.Client.Hosting') and '@(_CheatEngineClientSdkRangeReference)' == ''"
Code="CHEATENGINECLIENT9016"
Text="SDK-facing published packages must declare CheatEngine.SDK as $(CheatEngineSdkVersionRange), the range of eng/CheatEngineSdk.props."/>
</Target>
<!--
CHEATENGINECLIENT9016 and 9017: the consumed CheatEngine.SDK comes from eng/CheatEngineSdk.props only (audit ADR-10,
A21-01). The checks run before NuGet collects package references, so restore and build of every project fail before
NuGet resolves anything (no NU1102, no silently resolved package of an unsupported major).
-->
<Target Name="_CheatEngineClientComputeSdkPinProblem">
<PropertyGroup>
<_CheatEngineClientSdkPinMajor>$([System.Text.RegularExpressions.Regex]::Match('$(CheatEngineSdkVersion)', '^[0-9]+').Value)</_CheatEngineClientSdkPinMajor>
<_CheatEngineClientSdkPinProblem></_CheatEngineClientSdkPinProblem>
<_CheatEngineClientSdkPinProblem Condition="!$([System.Text.RegularExpressions.Regex]::IsMatch('$(CheatEngineSdkVersion)', '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'))">is not a NuGet version</_CheatEngineClientSdkPinProblem>
<_CheatEngineClientSdkPinProblem Condition="'$(_CheatEngineClientSdkPinProblem)' == '' and $(CheatEngineSdkVersion.Contains('-'))">is a prerelease</_CheatEngineClientSdkPinProblem>
<_CheatEngineClientSdkPinProblem Condition="'$(_CheatEngineClientSdkPinProblem)' == '' and '$(_CheatEngineClientSdkPinMajor)' != '$(_CheatEngineClientSupportedSdkMajor)'">has major version $(_CheatEngineClientSdkPinMajor), but this Client supports CheatEngine.SDK $(_CheatEngineClientSupportedSdkMajor).x only</_CheatEngineClientSdkPinProblem>
<_CheatEngineClientSdkPinProblem Condition="'$(_CheatEngineClientSdkPinProblem)' == '' and !$(CheatEngineSdkVersionRange.StartsWith('[$(CheatEngineSdkVersion),'))">is not the lower bound of the declared range '$(CheatEngineSdkVersionRange)'</_CheatEngineClientSdkPinProblem>
<_CheatEngineClientSdkPinMessage>The consumed CheatEngine.SDK version '$(CheatEngineSdkVersion)' $(_CheatEngineClientSdkPinProblem). This Client is built and tested against a stable CheatEngine.SDK $(_CheatEngineClientSupportedSdkMajor).x release and declares '$(CheatEngineSdkVersionRange)'. Change the pin only in eng/CheatEngineSdk.props (see its header comment for the full bump procedure); moving to another major is a deliberate migration, not a dependency bump.</_CheatEngineClientSdkPinMessage>
</PropertyGroup>
</Target>
<Target Name="CheatEngineClientValidateSdkPin"
BeforeTargets="CollectPackageReferences"
DependsOnTargets="_CheatEngineClientComputeSdkPinProblem">
<Error Condition="'$(_CheatEngineClientSdkPinProblem)' != ''"
Code="CHEATENGINECLIENT9016"
Text="$(_CheatEngineClientSdkPinMessage)"/>
<PropertyGroup>
<_CheatEngineClientSdkFacingLibrary>false</_CheatEngineClientSdkFacingLibrary>
<_CheatEngineClientSdkFacingLibrary Condition="'$(MSBuildProjectName)' == 'CheatEngine.Client.Abstractions' or '$(MSBuildProjectName)' == 'CheatEngine.Client.Core' or '$(MSBuildProjectName)' == 'CheatEngine.Client.Hosting'">true</_CheatEngineClientSdkFacingLibrary>
<_CheatEngineClientExpectedSdkVersion>$(CheatEngineSdkVersion)</_CheatEngineClientExpectedSdkVersion>
<_CheatEngineClientExpectedSdkVersion Condition="'$(CoexistenceSdkPackageVersion)' != ''">$(CoexistenceSdkPackageVersion)</_CheatEngineClientExpectedSdkVersion>
<_CheatEngineClientCentralSdkVersion>@(PackageVersion->WithMetadataValue('Identity', 'CheatEngine.SDK')->'%(Version)')</_CheatEngineClientCentralSdkVersion>
</PropertyGroup>
<ItemGroup>
<_CheatEngineClientPinnedSdkReference Remove="@(_CheatEngineClientPinnedSdkReference)"/>
<_CheatEngineClientPinnedSdkReference Include="@(PackageReference)" Condition="'%(Identity)' == 'CheatEngine.SDK'"/>
<_CheatEngineClientMisversionedSdkReference Remove="@(_CheatEngineClientMisversionedSdkReference)"/>
<_CheatEngineClientMisversionedSdkReference Include="@(_CheatEngineClientPinnedSdkReference)"
Condition="('$(ManagePackageVersionsCentrally)' == 'true' and '$(_CheatEngineClientSdkFacingLibrary)' == 'true' and '%(_CheatEngineClientPinnedSdkReference.VersionOverride)' != '$(CheatEngineSdkVersionRange)') or ('$(ManagePackageVersionsCentrally)' == 'true' and '$(_CheatEngineClientSdkFacingLibrary)' != 'true' and '%(_CheatEngineClientPinnedSdkReference.VersionOverride)' != '') or ('$(ManagePackageVersionsCentrally)' == 'true' and '%(_CheatEngineClientPinnedSdkReference.Version)' != '') or ('$(ManagePackageVersionsCentrally)' != 'true' and '%(_CheatEngineClientPinnedSdkReference.Version)' != '$(_CheatEngineClientExpectedSdkVersion)')"/>
</ItemGroup>
<Error Condition="'@(_CheatEngineClientMisversionedSdkReference)' != ''"
Code="CHEATENGINECLIENT9017"
Text="$(MSBuildProjectName) declares CheatEngine.SDK with Version '@(_CheatEngineClientMisversionedSdkReference->'%(Version)')' and VersionOverride '@(_CheatEngineClientMisversionedSdkReference->'%(VersionOverride)')'. The version comes from eng/CheatEngineSdk.props only: the SDK-facing libraries (Abstractions, Core, Hosting) declare VersionOverride="%24(CheatEngineSdkVersionRange)" (now '$(CheatEngineSdkVersionRange)'), other centrally managed projects declare no version, and projects outside Central Package Management declare Version '$(_CheatEngineClientExpectedSdkVersion)'."/>
<Error Condition="'$(ManagePackageVersionsCentrally)' == 'true' and '$(_CheatEngineClientCentralSdkVersion)' != '$(CheatEngineSdkVersion)'"
Code="CHEATENGINECLIENT9017"
Text="$(MSBuildProjectName) sees the central CheatEngine.SDK PackageVersion '$(_CheatEngineClientCentralSdkVersion)', expected '$(CheatEngineSdkVersion)' from eng/CheatEngineSdk.props. Do not add or update a CheatEngine.SDK PackageVersion outside Directory.Packages.props."/>
</Target>
<!--
CHEATENGINECLIENT9020: a Roslyn component compiled against a newer Roslyn than the consumer's compiler does not load
there (CS9057), and no local build notices a bumped pin because the SDK in global.json bundles the same Roslyn. The
target compares the central pins with the declared floor, so a Roslyn bump is always a deliberate, reviewed change.
-->
<Target Name="CheatEngineClientCheckRoslynPin"
BeforeTargets="BeforeBuild"
Condition="'$(IsRoslynComponent)' == 'true'">
<PropertyGroup>
<_CheatEngineClientRoslynCSharpPin>@(PackageVersion->WithMetadataValue('Identity', 'Microsoft.CodeAnalysis.CSharp')->'%(Version)')</_CheatEngineClientRoslynCSharpPin>
<_CheatEngineClientRoslynAnalyzersPin>@(PackageVersion->WithMetadataValue('Identity', 'Microsoft.CodeAnalysis.Analyzers')->'%(Version)')</_CheatEngineClientRoslynAnalyzersPin>
</PropertyGroup>
<Error Condition="'$(_CheatEngineClientRoslynCSharpPin)' != '$(CheatEngineClientRoslynComponentFloor)' or '$(_CheatEngineClientRoslynAnalyzersPin)' != '$(CheatEngineClientRoslynComponentFloor)'"
Code="CHEATENGINECLIENT9020"
Text="$(MSBuildProjectName) is a Roslyn component: Directory.Packages.props pins Microsoft.CodeAnalysis.CSharp '$(_CheatEngineClientRoslynCSharpPin)' and Microsoft.CodeAnalysis.Analyzers '$(_CheatEngineClientRoslynAnalyzersPin)', but CheatEngineClientRoslynComponentFloor is '$(CheatEngineClientRoslynComponentFloor)'. A generator compiled against Roslyn N does not load in an older compiler (CS9057): restore the pin, or raise it together with CheatEngineClientRoslynComponentFloor (Directory.Build.props), the template sdk-version constraint (templates/CheatEngine.Client.Templates/content/CheatEngine.Plugin/.template.config/template.json), global.json and the .NET SDK requirement row of the README."/>
</Target>
<!--
Versioning (MinVer, configured in Directory.Build.props). The evaluation-time values are captured here, after the
project body and the SDK defaults, so CHEATENGINECLIENT9019 can tell a version set by a project or a -p: switch from
the root placeholder.
-->
<!--
A package without build output (the CheatEngine.Client facade, the template package) has no PDB, so its symbol
package would contain only a nuspec; nuget.org's symbol server accepts portable PDBs, and an empty .snupkg would be
pushed next to the .nupkg for nothing. Evaluated here, after the project body and before the NuGet pack targets.
https://learn.microsoft.com/nuget/create-packages/symbol-packages-snupkg#nugetorg-symbol-package-constraints
-->
<PropertyGroup Label="Symbols only for packages with build output" Condition="'$(IncludeBuildOutput)' == 'false'">
<IncludeSymbols>false</IncludeSymbols>
</PropertyGroup>
<PropertyGroup Label="Evaluated version sources">
<_CheatEngineClientEvaluatedVersion>$(Version)</_CheatEngineClientEvaluatedVersion>
<_CheatEngineClientEvaluatedPackageVersion>$(PackageVersion)</_CheatEngineClientEvaluatedPackageVersion>
</PropertyGroup>
<!--
MinVer sets AssemblyVersion to major.0.0.0. In 0.x a minor release is breaking, and the Client assemblies were 0.1.0.0
before MinVer, so keep major.minor while the major is 0. This is the customization MinVer documents: a target that
runs after MinVer.
-->
<Target Name="CheatEngineClientAssemblyVersion"
AfterTargets="MinVer"
Condition="'$(MinVerSkip)' != 'true' and '$(MinVerMajor)' == '0'">
<PropertyGroup>
<AssemblyVersion>$(MinVerMajor).$(MinVerMinor).0.0</AssemblyVersion>
</PropertyGroup>
</Target>
<!--
CHEATENGINECLIENT9019: the seven packages always share the MinVer version. A package whose version comes from
anywhere else (a project property, a -p: switch, the version-suffix option of dotnet pack, or MinVerSkip) is refused
before its nuspec exists.
-->
<Target Name="CheatEngineClientValidateLockstepVersion"
BeforeTargets="GenerateNuspec"
Condition="'$(IsPackable)' == 'true'">
<PropertyGroup>
<_CheatEngineClientMinVerPackageVersion>$(MinVerVersion.Split('+')[0])</_CheatEngineClientMinVerPackageVersion>
</PropertyGroup>
<Error Condition="'$(MinVerSkip)' == 'true'"
Code="CHEATENGINECLIENT9019"
Text="$(MSBuildProjectName) cannot be packed with MinVerSkip=true: every Client package takes its version from MinVer. Rehearse a release version with -p:MinVerVersionOverride=X.Y.Z instead."/>
<Error Condition="'$(MinVerSkip)' != 'true' and ('$(VersionPrefix)' != '$(_CheatEngineClientRootVersionPrefix)' or '$(VersionSuffix)' != '' or '$(_CheatEngineClientEvaluatedVersion)' != '$(_CheatEngineClientRootVersionPrefix)' or ('$(_CheatEngineClientEvaluatedPackageVersion)' != '' and '$(_CheatEngineClientEvaluatedPackageVersion)' != '$(_CheatEngineClientEvaluatedVersion)'))"
Code="CHEATENGINECLIENT9019"
Text="$(MSBuildProjectName) sets its own version (VersionPrefix '$(VersionPrefix)', VersionSuffix '$(VersionSuffix)', Version '$(_CheatEngineClientEvaluatedVersion)', PackageVersion '$(_CheatEngineClientEvaluatedPackageVersion)'). The seven Client packages share one MinVer version: remove the project property or command-line switch; MinVerMinimumMajorMinor in Directory.Build.props and the v* tag are the only version inputs."/>
<Error Condition="'$(MinVerSkip)' != 'true' and '$(PackageVersion)' != '$(_CheatEngineClientMinVerPackageVersion)'"
Code="CHEATENGINECLIENT9019"
Text="$(MSBuildProjectName) would be packed as '$(PackageVersion)', but MinVer computed '$(MinVerVersion)'. The seven Client packages share one MinVer version."/>
</Target>
<!--
Every inter-Client package dependency is exact (audit PKG-10, API-15). NuGet packs a project reference as a
dependency on the referenced project's package version, which a nuspec reads as a minimum ('1.0.0' means '>= 1.0.0').
Extensions.DependencyInjection and Hosting use Core and DependencyInjection internals through InternalsVisibleTo, and
Core has no public API, so a graph that mixed Client versions could fail at run time with MissingMethodException or
TypeLoadException, which neither package validation nor the public API baselines can see. The seven packages share
one version (CHEATENGINECLIENT9019), so each one requires exactly that version of every Client package it depends on.
The .NET SDK 10.0.401 pack targets (NuGet.Build.Tasks.Pack.targets, internal and undocumented; eng/CheatEngineSdk.props
asks for a re-check after a .NET SDK bump): GenerateNuspec depends on _GetProjectReferenceVersions, which reads the
project references of project.assets.json, calls _GetProjectVersion on each and collects the results as
_ProjectReferencesWithVersions items, whose ProjectVersion metadata is the referenced project's $(PackageVersion).
PackTask receives those items as ProjectReferencesWithVersions and parses ProjectVersion as a NuGet version range, so
'[X.Y.Z]' becomes an exact dependency. This target runs between the two. Restore never runs it, so no lock file
changes; the CheatEngine.SDK range is a package reference and is not affected.
-->
<Target Name="CheatEngineClientPinInterClientDependencies"
AfterTargets="_GetProjectReferenceVersions"
BeforeTargets="GenerateNuspec"
Condition="'$(IsPackable)' == 'true'">
<ItemGroup>
<_CheatEngineClientOtherVersionReference Remove="@(_CheatEngineClientOtherVersionReference)"/>
<_CheatEngineClientOtherVersionReference Include="@(_ProjectReferencesWithVersions)"
Condition="'%(_ProjectReferencesWithVersions.ProjectVersion)' != '$(PackageVersion)'"/>
</ItemGroup>
<Error Condition="'@(_CheatEngineClientOtherVersionReference)' != ''"
Code="CHEATENGINECLIENT9019"
Text="$(MSBuildProjectName) would be packed as '$(PackageVersion)' with project references packed as another version (@(_CheatEngineClientOtherVersionReference->'%(Filename) %(ProjectVersion)', ', ')). The seven Client packages share one MinVer version."/>
<ItemGroup>
<_ProjectReferencesWithVersions>
<ProjectVersion>[$(PackageVersion)]</ProjectVersion>
</_ProjectReferencesWithVersions>
</ItemGroup>
</Target>
<!--
Microsoft.Sbom.Targets derives SbomGenerationPackageVersion from $(Version) at evaluation, which is the placeholder,
not the MinVer version the package carries. Its GenerateSbomTarget runs after Pack, so setting the property after
MinVer makes the SBOM describe the package it is embedded in.
-->
<Target Name="CheatEngineClientSbomPackageVersion"
AfterTargets="MinVer"
Condition="'$(GenerateSBOM)' == 'true'">
<PropertyGroup>
<SbomGenerationPackageVersion>$(PackageVersion)</SbomGenerationPackageVersion>
</PropertyGroup>
</Target>
<!--
What the SBOM lists besides the packed files. The default component path is the project folder, where the artifacts
layout keeps no restore output, so no package would be listed. The intermediate folder would also expose stale
nuspec files of earlier packs. The SBOM therefore scans a folder holding only this project's project.assets.json: it
lists the resolved NuGet graph, runtime dependencies and build-only tools alike (MinVer, analyzers, Microsoft.Sbom.Targets,
template tasks), as RELEASING.md states.
-->
<Target Name="CheatEngineClientPrepareSbomComponents"
BeforeTargets="GenerateSbomTarget"
Condition="'$(IsPackable)' == 'true' and '$(GenerateSBOM)' == 'true'">
<PropertyGroup>
<_CheatEngineClientSbomComponentPath>$([MSBuild]::NormalizeDirectory('$(IntermediateOutputPath)', 'sbom-components'))</_CheatEngineClientSbomComponentPath>
<SbomGenerationBuildComponentPath>$(_CheatEngineClientSbomComponentPath)</SbomGenerationBuildComponentPath>
</PropertyGroup>
<Error Condition="!Exists('$(ProjectAssetsFile)')"
Code="CHEATENGINECLIENT9021"
Text="$(MSBuildProjectName) has no restore output ($(ProjectAssetsFile)) to describe in its SBOM. Restore before packing."/>
<RemoveDir Directories="$(_CheatEngineClientSbomComponentPath)"/>
<Copy SourceFiles="$(ProjectAssetsFile)" DestinationFolder="$(_CheatEngineClientSbomComponentPath)"/>
</Target>
<!-- CHEATENGINECLIENT9021: every Client package embeds its SPDX SBOM (audit PR-CQ-14); a pack without it is refused. -->
<Target Name="CheatEngineClientRequireSbom"
BeforeTargets="GenerateNuspec"
Condition="'$(IsPackable)' == 'true'">
<Error Condition="'$(GenerateSBOM)' != 'true'"
Code="CHEATENGINECLIENT9021"
Text="$(MSBuildProjectName) cannot be packed with GenerateSBOM='$(GenerateSBOM)': every Client package embeds an SPDX 2.2 SBOM at _manifest/spdx_2.2/manifest.spdx.json (eng/Shipping.props, eng/Templates.props)."/>
<Error Condition="'$(GenerateSBOM)' == 'true' and '@(PackageReference->WithMetadataValue('Identity', 'Microsoft.Sbom.Targets'))' == ''"
Code="CHEATENGINECLIENT9021"
Text="$(MSBuildProjectName) sets GenerateSBOM=true but does not reference Microsoft.Sbom.Targets, so no SBOM would be generated."/>
</Target>
<!--
Packing checks the SDK pin again, so an unsupported SDK pin never produces a package, even from a pack that did not
build first. The guard runs before GenerateNuspec, which writes the .nupkg and the .snupkg: a BeforeTargets="Pack"
target would run only after Pack's dependencies had already written them.
-->
<Target Name="CheatEngineClientRefuseUnsupportedSdkPack"
BeforeTargets="GenerateNuspec"
DependsOnTargets="_CheatEngineClientComputeSdkPinProblem"
Condition="'$(IsPackable)' == 'true'">
<Error Condition="'$(_CheatEngineClientSdkPinProblem)' != ''"
Code="CHEATENGINECLIENT9016"
Text="$(MSBuildProjectName) cannot be packed: $(_CheatEngineClientSdkPinMessage)"/>
</Target>
<!--
Supply-chain guards (repository only, never shipped). They run in every build so a project-level or command-line
override cannot silently weaken the analysis pin, the NuGet audit policy or the lock-file contract set in
Directory.Build.props. Diagnostic ids CHEATENGINECLIENT9030-9039 are reserved for these guards.
-->
<Target Name="CheatEngineClientValidateSupplyChainSettings"
BeforeTargets="BeforeBuild">
<PropertyGroup>
<!-- NoWarn and WarningsNotAsErrors accept ';' or ',' separators and any whitespace; normalise to ';CODE;' so NU19031 never matches NU1903. -->
<_CheatEngineClientNoWarnCodes>;$([System.Text.RegularExpressions.Regex]::Replace('$(NoWarn)', '[\s,;]+', ';').ToUpperInvariant());</_CheatEngineClientNoWarnCodes>
<_CheatEngineClientWarningsNotAsErrorsCodes>;$([System.Text.RegularExpressions.Regex]::Replace('$(WarningsNotAsErrors)', '[\s,;]+', ';').ToUpperInvariant());</_CheatEngineClientWarningsNotAsErrorsCodes>
<_CheatEngineClientDowngradesBlockingAudit>false</_CheatEngineClientDowngradesBlockingAudit>
<_CheatEngineClientDowngradesBlockingAudit Condition="$(_CheatEngineClientNoWarnCodes.Contains(';NU1903;')) or $(_CheatEngineClientNoWarnCodes.Contains(';NU1904;')) or $(_CheatEngineClientWarningsNotAsErrorsCodes.Contains(';NU1903;')) or $(_CheatEngineClientWarningsNotAsErrorsCodes.Contains(';NU1904;'))">true</_CheatEngineClientDowngradesBlockingAudit>
<!-- The Coexistence fixtures are the only projects outside Central Package Management (v1 lock files). -->
<_CheatEngineClientIsCoexistenceFixture>$(_CheatEngineClientFolder.StartsWith('tests/CheatEngine.Client.LivePlugin.Coexistence/', System.StringComparison.OrdinalIgnoreCase))</_CheatEngineClientIsCoexistenceFixture>
<!-- Documented operator override (CoexistencePlugin.props): an SDK version other than the pin of eng/CheatEngineSdk.props is a qualification input whose restore records its closure in obj/, never in the committed lock file. -->
<_CheatEngineClientLockFileOverride>false</_CheatEngineClientLockFileOverride>
<_CheatEngineClientLockFileOverride Condition="'$(_CheatEngineClientIsCoexistenceFixture)' == 'true' and '$(CoexistenceSdkPackageVersion)' != '' and '$(CoexistenceSdkPackageVersion)' != '$(CheatEngineSdkVersion)'">true</_CheatEngineClientLockFileOverride>
</PropertyGroup>
<Error Condition="'$(AnalysisLevel)' != '$(_CheatEngineClientPinnedAnalysisLevel)'"
Code="CHEATENGINECLIENT9030"
Text="$(MSBuildProjectName) builds with AnalysisLevel '$(AnalysisLevel)', but the repository pins '$(_CheatEngineClientPinnedAnalysisLevel)'. Do not override it per project or on the command line: raise the pin in Directory.Build.props together with global.json."/>
<Error Condition="'$(NuGetAudit)' != 'true' or '$(NuGetAuditMode)' != 'all' or '$(NuGetAuditLevel)' != 'low'"
Code="CHEATENGINECLIENT9031"
Text="$(MSBuildProjectName) weakens the NuGet audit policy (NuGetAudit='$(NuGetAudit)', NuGetAuditMode='$(NuGetAuditMode)', NuGetAuditLevel='$(NuGetAuditLevel)'; required: true, all, low). Suppress a single advisory with NuGetAuditSuppress instead."/>
<Error Condition="'$(_CheatEngineClientDowngradesBlockingAudit)' == 'true'"
Code="CHEATENGINECLIENT9031"
Text="$(MSBuildProjectName) lists NU1903 or NU1904 in NoWarn or WarningsNotAsErrors. High and critical advisories must fail every build; suppress a single advisory with NuGetAuditSuppress (advisory URL, justification, expiry) instead."/>
<Error Condition="'$(RestorePackagesWithLockFile)' != 'true' and '$(_CheatEngineClientLockFileOverride)' != 'true'"
Code="CHEATENGINECLIENT9032"
Text="$(MSBuildProjectName) restores without a lock file (RestorePackagesWithLockFile='$(RestorePackagesWithLockFile)'). Every project keeps a committed packages.lock.json: regenerate with 'dotnet restore $(MSBuildProjectFullPath) --force-evaluate'."/>
<Error Condition="'$(ManagePackageVersionsCentrally)' != 'true' and '$(_CheatEngineClientIsCoexistenceFixture)' != 'true'"
Code="CHEATENGINECLIENT9032"
Text="$(MSBuildProjectName) opts out of Central Package Management (ManagePackageVersionsCentrally='$(ManagePackageVersionsCentrally)'). Only the Coexistence fixtures may; declare versions in Directory.Packages.props and regenerate with 'dotnet restore $(MSBuildProjectFullPath) --force-evaluate'."/>
</Target>
</Project>