[xaprepare] Move cgmanifest.json generation from xaprepare to YAML - #11825
Conversation
Continues the incremental removal of `xaprepare` by moving the
`cgmanifest.json` generator out of the C# step
`Step_GenerateCGManifest` and into a YAML `pwsh:` step that runs only
on CI.
The file is consumed exclusively by the Azure DevOps Component
Governance Detection task (auto-injected on internal pipelines by
`eng/common/core-templates/job/job.yml`). It is not consumed by any
in-repo build target, so generating it from the C# Prepare step is no
longer necessary.
We cannot drop the file outright: `eng/common` ships CG infrastructure
but it is not yet wired to auto-discover submodules in our pipelines,
so the explicit `cgmanifest.json` is still the source of truth.
Files:
* Added: `build-tools/automation/yaml-templates/generate-cgmanifest.yaml`
* Modified: `build-windows-steps.yaml`, `build-macos-steps.yaml`,
`build-linux-steps.yaml`, `commercial-build.yaml` (call the new
template after the Prepare/`make jenkins` step)
* Modified: `Scenario_Standard.cs` (drop registration)
* Modified: `GitRunner.cs` (remove now-unused `ConfigList` and
`SubmoduleStatus` methods)
* Deleted: `Step_GenerateCGManifest.cs`
Verification: byte-for-byte diff of the YAML-generated
`cgmanifest.json` against the previous C# output on Debug:
Baseline=3144 New=3144
Total byte differences: 0
Precedent PRs in this stream: #11568, #11580, #11608, #11613,
#11631, #11731, #11732, #11733, #11737, #11740, #11760, #11803,
#11821.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Moves cgmanifest.json generation out of the xaprepare C# workflow and into a dedicated Azure Pipelines YAML template, aligning with the ongoing effort to reduce/remove xaprepare responsibilities while keeping Component Governance (CG) functionality available for CI.
Changes:
- Added
generate-cgmanifest.yamlPowerShell-based generator to producebin/Build$(Configuration)/cgmanifest.jsonon CI. - Updated CI pipeline step templates (Windows/macOS/Linux + commercial) to call the new generator template after prepare/
make jenkins. - Removed the
Step_GenerateCGManifeststep registration and deleted the C# implementation; removed now-unused GitRunner helper methods.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| build-tools/xaprepare/xaprepare/ToolRunners/GitRunner.cs | Removes ConfigList/SubmoduleStatus helpers that were only used by the deleted CG manifest step. |
| build-tools/xaprepare/xaprepare/Steps/Step_GenerateCGManifest.cs | Deletes the C# CG manifest generation step and its submodule parsing helper. |
| build-tools/xaprepare/xaprepare/Scenarios/Scenario_Standard.cs | Stops registering Step_GenerateCGManifest in the standard xaprepare scenario. |
| build-tools/automation/yaml-templates/generate-cgmanifest.yaml | Adds CI-only PowerShell generation of cgmanifest.json based on git submodules. |
| build-tools/automation/yaml-templates/commercial-build.yaml | Invokes the new generator template after make jenkins. |
| build-tools/automation/yaml-templates/build-windows-steps.yaml | Invokes the new generator template after -t:Prepare. |
| build-tools/automation/yaml-templates/build-macos-steps.yaml | Invokes the new generator template after make jenkins. |
| build-tools/automation/yaml-templates/build-linux-steps.yaml | Invokes the new generator template after make jenkins. |
Replace the hand-rolled StringBuilder JSON emission with PowerShell's `ConvertTo-Json`. The output is no longer byte-identical to the previous C# output (2-space indent instead of 4, and slightly different whitespace), but it is still valid JSON matching the component-detection-manifest schema. The Azure DevOps Component Governance Detection task parses the file, so formatting does not matter. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…11826) ## Summary Moves `XABuildConfig.cs` generation out of `xaprepare` and into a new strong-named class library at `src/AndroidBuildConfig/AndroidBuildConfig.csproj` that produces `AndroidBuildConfig.dll`. This continues the incremental removal of `xaprepare`, following the precedent set by `cmake-config.csproj` (#11760) and the recent batch #11568, #11580, #11608, #11613, #11631, #11731, #11732, #11733, #11737, #11740, #11803, #11821, #11825. It also fixes a long-standing wart: previously `XABuildConfig.cs` was `<Compile Include>`'d into three different assemblies (`Xamarin.Android.Build.Tasks`, `Xamarin.ProjectTools`, and `Xamarin.Android.Build.Tests`), so every test that mentioned `XABuildConfig` produced a `CS0436` "type conflicts with imported type" warning — about **22** of them. Wrapping the type in its own assembly collapses it to a single definition that every consumer references normally. After this change `Xamarin.Android.Build.Tests` builds with **7** warnings (none for `XABuildConfig`). ## How it works `src/AndroidBuildConfig/AndroidBuildConfig.csproj`: - `Microsoft.NET.Sdk` / `netstandard2.0`, strong-named with `product.snk`. - `ProjectReference`s `Xamarin.Android.Tools.AndroidSdk` (for the `AndroidTargetArch` enum used by the template). - `<UsingTask>`s `ReplaceFileContents`, `GitCommitHash`, and `GitBranch` from `$(PrepTasksAssembly)`, all with `TaskFactory="TaskHostFactory" Runtime="NET"` per repo convention. - The `_GenerateXABuildConfig` target runs `BeforeTargets="BeforeCompile;CoreCompile"`, computes every substitution from MSBuild properties already exposed by `Configuration.props` (NDK major/minor/micro via `$(_XAAndroidNdkPkgRevision.Split('.'))`, API levels via `Split`/`Contains`, full commit hash via `GitCommitHash.CommitHash`, branch via `GitBranch.Branch`), and writes the file to `$(IntermediateOutputPath)XABuildConfig.cs`. The `<Compile Include>` lives inside the target so it resolves at execution time, when `IntermediateOutputPath` is final. - `XABuildConfig` is now `public static class` instead of `internal static class`. The three consumer csprojs lose their `<Compile Include="…XABuildConfig.cs" />` and now have a normal `<ProjectReference Include="…AndroidBuildConfig.csproj" />` (no `ReferenceOutputAssembly="False"`). `build-tools/installers/create-installers.targets` ships `AndroidBuildConfig.dll` + `.pdb` alongside `Xamarin.Android.Build.Tasks.dll`. ## xaprepare cleanup Removed dead code that only existed to feed the old `Get_XABuildConfig_cs` step: - `Step_GenerateFiles.Get_XABuildConfig_cs` and its `GetMajor` / `GetMinor` locals - `BuildInfo`: `NDKRevision`, `NDKVersionMajor`, `NDKVersionMinor`, `NDKVersionMicro`, `NDKVersion`, `XACommitHash`, `XABranch`, `GatherGitInfo`, `DetermineXACommitInfo`, `cachedNdkVersion` - `Context`: the `if (SelectedScenario.NeedsGitBuildInfo) { await BuildInfo.GatherGitInfo … }` block - `Scenario.NeedsGitBuildInfo` (and the `NeedsGitBuildInfo = true;` setters in `Scenario_Standard` and `Scenario_Required`) - `BuildAndroidPlatforms.cs` — entire file (only contained constants used by the deleted code) - `Utilities.ParseAndroidPkgRevision` - `GitRunner.GetTopCommitHash` and `GitRunner.GetBranchName` (class retained — still used by `BuildInfo.DetermineLastVersionChangeCommit`) ## Files **Added** - `src/AndroidBuildConfig/AndroidBuildConfig.csproj` **Renamed/moved** - `build-tools/scripts/XABuildConfig.cs.in` → `src/AndroidBuildConfig/XABuildConfig.cs.in` (`static class` → `public static class`) **Modified** - `src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj` - `src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj` - `src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj` - `build-tools/installers/create-installers.targets` - `build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs` - `build-tools/xaprepare/xaprepare/Application/BuildInfo.cs` - `build-tools/xaprepare/xaprepare/Application/Context.cs` - `build-tools/xaprepare/xaprepare/Application/Scenario.cs` - `build-tools/xaprepare/xaprepare/Application/Utilities.cs` - `build-tools/xaprepare/xaprepare/Scenarios/Scenario_Standard.cs` - `build-tools/xaprepare/xaprepare/Scenarios/Scenario_Required.cs` - `build-tools/xaprepare/xaprepare/ToolRunners/GitRunner.cs` - `build-tools/xaprepare/README.md` **Deleted** - `build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs` ## Verification - `AndroidBuildConfig.csproj`: 0 warnings, 0 errors. - `Xamarin.Android.Build.Tasks.csproj`: 0 errors, 85 pre-existing unrelated warnings (none for `XABuildConfig`). - `Xamarin.Android.Build.Tests.csproj`: 0 errors, **7** warnings — down from ~22; all `CS0436 XABuildConfig` conflicts eliminated. - `xaprepare.csproj`: 0 warnings, 0 errors. - Generated `XABuildConfig.cs` is semantically identical to the pre-change xaprepare output. The only token difference is the intentional `static class` → `public static class`; everything else (NDK split, API-level major/minor split, supported-ABIs semicolon list, full commit hash, branch name, etc.) matches the previous baseline byte-for-byte. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Verified that
The file is not uploaded as a build artifact — but that matches the pre-PR behavior. That is fine: the Component Governance Detection task auto-injected on internal pipelines scans the agent working directory for |
On Windows, xaprepare's Step_GenerateFiles.Windows.cs writes
external/Java.Interop/bin/Build$(Configuration)/JdkInfo.props from
build-tools/xaprepare/xaprepare/Resources/JdkInfo.Windows.props.in.
But this file is immediately overwritten. The PrepareWindows.targets
Prepare flow runs, in order:
1. `dotnet xaprepare -a` — writes JdkInfo.props (this code).
2. `MSBuild Xamarin.Android.BootstrapTasks.sln` — does not read JdkInfo.props.
3. `MSBuild src/workloads/workloads.csproj` — does not read JdkInfo.props.
4. `CallTarget PrepareJavaInterop` → `dotnet build -t:Prepare Java.Interop.sln`
→ external/Java.Interop/build-tools/scripts/Prepare.targets → runs the
`JdkInfo` MSBuild task → overwrites JdkInfo.props with its own generated
content.
Nothing between step 1 and step 4 reads the file, and Java.Interop's Prepare
always regenerates it. Now that external/Java.Interop is in-tree, we can
safely delete the redundant write.
This is the smallest-diff removal:
* Delete Step_GenerateFiles.Windows.cs (the AddOSSpecificSteps partial).
* Delete Resources/JdkInfo.Windows.props.in.
* In Step_GenerateFiles.cs, drop the `partial void AddOSSpecificSteps`
declaration and collapse GetFilesToGenerate so `atBuildStart == false`
returns null. Ctor surface (atBuildStart, onlyRequired) is unchanged so
Scenario_Required.cs is unaffected.
* In Scenario_Standard.cs, remove the AddEndSteps override — the only
thing it did was schedule the now-empty Step_GenerateFiles(atBuildStart:
false).
Preserved (future slices will address these):
* Get_Configuration_OperatingSystem_props (D1).
* OperatingSystems/*.cs and Context.OS.* surface.
* PrepareWindows.targets, DotNet.targets, Java.Interop's Prepare.targets.
Verification:
* dotnet build build-tools/xaprepare/xaprepare/xaprepare.csproj -c Debug
→ Build succeeded. 0 Warning(s). 0 Error(s).
* build.cmd -t:Prepare -c Debug (Windows, cold tree) → succeeds; the file
external/Java.Interop/bin/BuildDebug/JdkInfo.props exists.
* Compare-Object of the resulting JdkInfo.props before vs after this
change → byte-identical (1493 bytes, SHA256
DE59A8061B7657831788FFED7BC1DEECA442E9181605083A4553DE7AC8C003A1),
confirming Java.Interop's overwrite is what always ends up on disk.
* Grep audit under build-tools/xaprepare/: no remaining references to
Step_GenerateFiles.Windows, JdkInfo.Windows.props.in, or
AddOSSpecificSteps.
Follows previous xaprepare deletion slices #11568, #11580, #11608, #11613,
#11631, #11731, #11732, #11733, #11737, #11740, #11760, #11803, #11821,
#11825, #11826.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…xaprepare project (#11959) Follow-up to #11956, which moved the JDK half of `Configuration.OperatingSystem.props` to Java.Interop's `JdkInfo.props`. The remaining NDK / OS-info half has zero real consumers, so this PR: 1. Deletes the last generator template (`Configuration.OperatingSystem.props.in`). 2. Cascades through `Step_GenerateFiles`, both `Scenario_*` classes (which now had zero steps), and every supporting `OperatingSystems/`, `Context.*OS.cs`, `EssentialTools.*`, `ToolRunners/*`, `Configurables.*`, `Application/*`, and `Main.cs` file that only existed to feed the scenarios. 3. Deletes the whole `build-tools/xaprepare/` project. 4. Patches every integration point (`Makefile`, `PrepareWindows.targets`, `BuildEverything.mk`, CI YAML, docs) so `build.cmd -t:Prepare` and `make prepare` still work end-to-end. ## `Configuration.OperatingSystem.props.in` placeholder audit | Placeholder | Consumers outside the `.in` file | Action | | --- | --- | --- | | `HostOsName` | none | drop | | `HostOsFlavor` | none | drop | | `HostOsRelease` | none | drop | | `HostBits` | none (`ArchiveBase.HostBits` in `src/Xamarin.Installer.AndroidSDK/` is an unrelated C# property) | drop | | `NdkLlvmTag` | none (the NDK toolchain OS tag is resolved elsewhere via `_NdkToolchainOSTag` in `androidsdk.targets`) | drop | | `HostCpuCount` | only `Configuration.props:72` via `$(MakeConcurrency)` | drop | ## `$(MakeConcurrency)` audit The only definition was `Configuration.props:72`. A repo-wide grep of `.targets`, `.props`, `.projitems`, `Makefile`, and `.mk` files found zero consumers of the MSBuild property. The `MakeConcurrency` hits under `build-tools/xaprepare/` were an unrelated C# `Context.MakeConcurrency` property. **Result:** dropped the `MakeConcurrency` MSBuild property entirely (no `$([System.Environment]::ProcessorCount)` replacement needed) and removed the `$(MakeConcurrency)` bullet in `Documentation/building/configuration.md`. ## xaprepare integration audit (grep-confirmed, patched here) | Location | Change | | --- | --- | | `build-tools/xaprepare/` (entire tree) | **deleted** — 86 tracked files | | `Configuration.props` | dropped `<Import>` of the generated OS props, dropped `MakeConcurrency`, tidied the "between xaprepare and package creation tools" comment | | `.gitignore` | dropped `Configuration.OperatingSystem.props` | | `build-tools/scripts/PrepareWindows.targets` | removed `_XAPrepareExe`, `_XAPrepareStandardArgs`, `_BuildXAPrepare` target, and the `Exec dotnet $(_XAPrepareExe)` line. Repointed `Prepare` at `_InstallDotNet`. Kept the space-in-path guard, BootstrapTasks / workloads MSBuilds, and `PrepareJavaInterop` | | `Makefile` | dropped `PREPARE_PROJECT`, `PREPARE_NET_FX`, `PREPARE_ARGS`, `PREPARE_MSBUILD_FLAGS`, `PREPARE_SCENARIO`, `PREPARE_CI_PR`, `PREPARE_CI`, `_PREPARE_CI_MODE_*`, `_PREPARE_ARGS`, and all their conditionals. Dropped the `dotnet run --project xaprepare.csproj` line from `prepare`. Deleted the `prepare-help` target | | `build-tools/scripts/BuildEverything.mk` | `jenkins` no longer branches on `PREPARE_CI_PR`/`PREPARE_CI`; just `$(MAKE) prepare && $(MAKE) leeroy` | | `.github/workflows/copilot-setup-steps.yml` | dropped now-unused `PREPARE_CI=1` | | `build-tools/automation/azure-pipelines-apidocs.yaml` | dropped `PREPARE_CI=1` | | `build-tools/automation/yaml-templates/build-linux-steps.yaml` | dropped `PREPARE_CI=1` | | `build-tools/automation/yaml-templates/build-macos-steps.yaml` | dropped `PREPARE_CI=1` | | `build-tools/automation/yaml-templates/commercial-build.yaml` | dropped `PREPARE_CI=1` | | `build-tools/automation/yaml-templates/copy-extra-result-files.yaml` | dropped `**/Configuration.OperatingSystem.props` glob and the stale `Step_CopyExtraResultFilesForCI` xaprepare-step comment | | `build-tools/automation/yaml-templates/generate-cgmanifest.yaml` | dropped the stale `Step_GenerateCGManifest` xaprepare-step comment | | `build-tools/automation/yaml-templates/setup-jdk-variables.yaml` | renamed `$xaPrepareJdkPath` → `$xaJdkPath` for hygiene | | `Documentation/workflow/HowToAddNewApiLevel.md` | rewrote the "Add New Platform" section to point at `<_PlatformPackage>` entries in `src/androidsdk/androidsdk.targets` instead of `AndroidToolchain.cs`; updated the `--android-sdk-platforms=all` recipe to `dotnet-local build src/androidsdk/androidsdk.csproj -p:AndroidSdkPlatforms=all` | | `Documentation/building/unix/dependencies.md` | JDK-version link now points at `$(MicrosoftOpenJDKVersion)` in `/Configuration.props` instead of the deleted `Configurables.cs` | | `Documentation/building/configuration.md` | removed the `$(MakeConcurrency)` bullet | **Historical breadcrumb comments left as-is** (still accurate and useful for git-archaeology): - `.github/skills/update-tpn/SKILL.md` - `src/AndroidBuildConfig/AndroidBuildConfig.csproj` - `src/androidsdk/androidsdk.targets` - `src/native/cmake-config/cmake-config.csproj` - `src/workloads/workloads.csproj` ## Verification - `build.cmd Prepare` — succeeded end-to-end on Windows (0 warnings, 0 errors). The trimmed `Prepare` target ran through `_InstallDotNet`, the space-in-path guard, `Xamarin.Android.BootstrapTasks.sln`, `src/workloads/workloads.csproj`, and `PrepareJavaInterop`. - `dotnet build src\Xamarin.Android.Build.Tasks\Xamarin.Android.Build.Tasks.csproj -c Debug` — 0 errors (93 pre-existing warnings from `src/Mono.Android/` and generated MCW, unrelated to this change). - Repo-wide grep for `HostOsName`, `HostOsFlavor`, `HostOsRelease`, `HostCpuCount`, `NdkLlvmTag`, and the MSBuild `MakeConcurrency` property — clean. - Repo-wide grep for `xaprepare` — clean apart from the five intentional historical breadcrumb comments listed above. ## Diff stat 102 files changed, 25 insertions(+), 7891 deletions(-). ## Precedent chain Continues the multi-slice teardown started by #11568, #11580, #11608, #11613, #11631, #11731, #11732, #11733, #11737, #11740, #11760, #11803, #11821, #11825, #11826, #11945, #11946, #11956. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Continues the incremental removal of
xaprepareby moving thecgmanifest.jsongenerator out of the C# stepStep_GenerateCGManifestand into a YAMLpwsh:step that runs only on CI.The file is consumed exclusively by the Azure DevOps Component Governance Detection task (auto-injected on internal pipelines by
eng/common/core-templates/job/job.yml). It is not consumed by any in-repo build target, so generating it from the C# Prepare step is no longer necessary.We cannot drop the file outright:
eng/commonships CG infrastructure but it is not yet wired to auto-discover submodules in our pipelines, so the explicitcgmanifest.jsonis still the source of truth.Files
build-tools/automation/yaml-templates/generate-cgmanifest.yamlbuild-windows-steps.yaml,build-macos-steps.yaml,build-linux-steps.yaml,commercial-build.yaml— call the new template right after the Prepare /make jenkinsstep.Scenario_Standard.cs— drop theStep_GenerateCGManifestregistration.GitRunner.cs— remove now-unusedConfigListandSubmoduleStatusmethods (no other consumers).Step_GenerateCGManifest.cs.Verification
Captured the baseline
bin/BuildDebug/cgmanifest.jsonfrommainbefore any changes (build.cmd -t:Prepare -c Debug), then extracted the new pwsh script and ran it standalone against the same worktree. Byte-for-byte comparison:After applying the C# deletion,
build.cmd -t:Prepare -c Debugstill succeeds with 0 warnings / 0 errors. Thecgmanifest.jsonfile is no longer produced locally — which is the intended change; CG runs only on CI.dotnet build build-tools/xaprepare/xaprepare/xaprepare.csproj -c Debug→ 0 warnings, 0 errors.Precedent
Part of the incremental xaprepare deletion: #11568, #11580, #11608, #11613, #11631, #11731, #11732, #11733, #11737, #11740, #11760, #11803, #11821.