Replace Step_CopyExtraResultFilesForCI with a YAML template#11568
Conversation
Part of slowly removing xaprepare. The CopyExtraResultFilesForCI scenario existed only to copy build/test artifacts into $(Build.StagingDirectory) on Azure DevOps -- something the built-in CopyFiles@2 task can do natively. Adds build-tools/automation/yaml-templates/copy-extra-result-files.yaml, which reproduces the file globs and destination layout (Build$(Configuration), Test$(Configuration), test-extras, compatibility) using CopyFiles@2 plus a small pwsh step for [System.IO.Path]::GetTempPath()-based llc.exe-* collection. The only caller, upload-results.yaml, now invokes the new template instead of run-xaprepare.yaml --s=CopyExtraResultFilesForCI. Also deletes Step_CopyExtraResultFilesForCI.cs and Scenario_CopyExtraResultFilesForCI.cs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR continues the effort to remove xaprepare usage by replacing the CopyExtraResultFilesForCI scenario/step with a dedicated Azure Pipelines YAML template that stages build/test artifacts directly via CopyFiles@2 (plus a small pwsh helper for temp llc.exe-* files).
Changes:
- Added a new
copy-extra-result-files.yamltemplate that reproduces the previous globbing + destination layout in$(Build.StagingDirectory). - Updated
upload-results.yamlto call the new template instead ofrun-xaprepare.yaml --s=CopyExtraResultFilesForCI. - Deleted the obsolete
xapreparestep + scenario C# implementations.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| build-tools/automation/yaml-templates/copy-extra-result-files.yaml | New YAML template to stage CI artifacts using CopyFiles@2 + pwsh. |
| build-tools/automation/yaml-templates/upload-results.yaml | Switches artifact staging to the new YAML template. |
| build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs | Removes the old xaprepare step implementation. |
| build-tools/xaprepare/xaprepare/Scenarios/Scenario_CopyExtraResultFilesForCI.cs | Removes the old xaprepare scenario wiring. |
- Use repo root as sourceFolder for the bin/Build, bin/Test, and compatibility CopyFiles@2 steps so a missing folder produces 0 matches instead of erroring (matches the original C# Directory.Exists guards). Patterns now include the bin/Build$(Configuration)/ or bin/Test$(Configuration)/ prefix; flattenFolders: true keeps the destination layout flat as before. - Rename $matches to $llcFiles in the llc.exe-* pwsh step to avoid shadowing PowerShell's $Matches automatic regex variable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Step_CopyExtraResultFilesForCI was the sole caller; deleting it left this method orphaned. Also drop the stale CopyFilesSimple reference from the new YAML template's comment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run |
|
/review |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
✅ Android PR Reviewer completed successfully! |
There was a problem hiding this comment.
✅ LGTM
Clean replacement of the Step_CopyExtraResultFilesForCI xaprepare step with a native YAML template. Verified behavior parity across all file groups:
- ✅ Recursive config file collection (
**/config.log, etc.) with path preservation matchesSearchOption.AllDirectories+ relative path copy - ✅ Flat
bin/Build$(Configuration)andbin/Test$(Configuration)copies match the C#CopyFilesSimplebehavior - ✅
compatibility/subfolder,TestResult*.xml/*.csv, andllc.exe-*temp file collection all match - ✅
continueOnError: trueon every step handles missing directories gracefully (equivalent toDirectory.Existsguards) - ✅
CopyFilesSimplehas no remaining callers — safe to remove - ✅ Intentionally dropped no-ops (packages cleanup, empty dir pruning) are well-documented in the PR description
CI: dotnet-android ✅, license/cla ✅. Xamarin.Android-PR not yet triggered (normal).
One minor 💡 suggestion about glob scope posted inline — not blocking.
Generated by Android PR Reviewer for issue #11568 · ● 12M
| **/config.h | ||
| **/android-*.config.cache | ||
| CMakeFiles/*.log | ||
| external/Java.Interop/bin/Build${{ parameters.configuration }}/*.props |
There was a problem hiding this comment.
🤖 💡 Performance — The **/config.h and **/config.log patterns are very broad recursive globs that will walk the entire source tree (including external/, packages/, etc.). This matches the original C# behavior (SearchOption.AllDirectories), so it's correct for parity — but a future follow-up could scope these to known subtrees (e.g. src/**/config.h) to speed up artifact collection on large workspaces.
Rule: Behavioral parity acknowledged
There was a problem hiding this comment.
Not fixing, to keep behavior the same as before.
## Why `bin/configuration.mk` exists only to persist `CONFIGURATION=<value>` between Unix `make` invocations. Removing it lets us delete the only meaningful contents of `Step_GenerateFiles.Unix.cs`, continuing the slow removal of `xaprepare` (see precedent: #11568, #11529). ## What - Drop `-include bin/configuration.mk` from the top of `Makefile`. The `CONFIGURATION ?= Debug` fallback at the top of the file is unchanged. - Delete `build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.Unix.cs` entirely (it contained `GeneratedConfigurationFile` and a one-line `AddUnixPostBuildSteps` partial that registered it). The `partial void AddUnixPostBuildSteps (Context context, List<GeneratedFile> steps);` declaration in `Step_GenerateFiles.cs` is intentionally left in place — partial methods without an implementation are legal in C#, and the call site becomes a zero-cost no-op. `Step_GenerateFiles.Windows.cs` implements a *different* partial (`AddOSSpecificSteps`) and is unaffected. ## Why this is safe | Caller | Pre-change behavior | Post-change behavior | | --- | --- | --- | | All CI YAML (`build-linux-steps.yaml`, `build-macos-steps.yaml`, `commercial-build.yaml`, `azure-pipelines-apidocs.yaml`) | Passes `CONFIGURATION=$(XA.Build.Configuration)` on every `make` call | Same — explicit value still wins | | `build.sh` (`make prepare && make jenkins && make pack-dotnet`) | First `make prepare` runs against an empty `bin/`, so the `-include` no-ops and `?= Debug` takes effect | Identical — `?= Debug` still takes effect | | Fresh local checkout, bare `make all` | `?= Debug` (no `bin/configuration.mk` yet) | Same | | Local dev who runs `make prepare CONFIGURATION=Release` then bare `make all` | Persisted Release via `bin/configuration.mk` | Now defaults back to Debug — must pass `CONFIGURATION=Release` on every invocation | That last case is the only behavior change. It was never documented as a contract anywhere in `Documentation/` or `README.md`, and developers building Release locally should be passing the flag explicitly anyway. ## Verification - `git grep "configuration\.mk"` and `git grep "GeneratedConfigurationFile"`: zero matches after this change. - `dotnet build build-tools/xaprepare/xaprepare/xaprepare.csproj`: 0 warnings, 0 errors. - Rubber-duck review: no remaining `Path.Combine(..., "configuration.mk")` references, no Makefile target depends on `bin/configuration.mk` as a prerequisite, and the leftover partial-method declaration is benign.
…11608) `Mono.Android.Apis.projitems` was previously generated at prepare time by `GeneratedMonoAndroidProjitemsFile` (in xaprepare) from the `BuildAndroidPlatforms.AllPlatforms` list. Both had exactly one consumer (each other), so check in the projitems as a source file and drop the generator plumbing. Changes: * Add `src/Mono.Android/Mono.Android.Apis.projitems` — content matches the generator's output byte-for-byte; only the header comment now points at `Documentation/workflow/HowToAddNewApiLevel.md` instead of declaring "GENERATED FILE". * Repoint the 4 importers (`Mono.Android.targets` x2, `create-installers.targets`, `create-android-api.csproj`, `Xamarin.Android.Build.Tasks.targets`) at the new path and drop the `Condition="Exists(...)"` guards — the file is always present now. * Delete `GeneratedMonoAndroidProjitemsFile.cs` and `AndroidPlatform.cs` (whole files — `AndroidPlatform` class and `AndroidPlatformExtensions` both become unused). * Drop the `new GeneratedMonoAndroidProjitemsFile()` registration in `Step_GenerateFiles.cs`. * Remove `BuildAndroidPlatforms.AllPlatforms` and the now-unused `using System.Collections.Generic;`. Keep the NDK constants (`AndroidNdkVersion`, `AndroidNdkPkgRevision`, `NdkMinimumAPI`, `NdkMinimumAPILegacy32`) — they still have consumers. * Update `Documentation/workflow/HowToAddNewApiLevel.md` with the XML-based instructions for adding a new API level. * Narrow the `build-tools/xaprepare/README.md` blurb for `BuildAndroidPlatforms.cs` to NDK metadata. * Fix stale doc comment in `GenerateSupportedPlatforms.cs` pointing at the old generated path. Continues the xaprepare cleanup started in PRs #11568 and #11580. ### [docs] Fix Stable=True/False contradiction in HowToAddNewApiLevel The added prose said Stable should be False for preview API levels, but the example (CANARY) sets <Stable>True</Stable>, and every entry in Mono.Android.Apis.projitems is True. Rewrite the prose to match the data and briefly explain what setting Stable=False would actually do (excludes entry from default stable framework selection). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Localized file check-in by OneLocBuild Task (#11610) Build definition ID 17928: Build ID 14320800 * [xaprepare] Check in `Mono.Android.Apis.projitems`, remove generator (#11608) `Mono.Android.Apis.projitems` was previously generated at prepare time by `GeneratedMonoAndroidProjitemsFile` (in xaprepare) from the `BuildAndroidPlatforms.AllPlatforms` list. Both had exactly one consumer (each other), so check in the projitems as a source file and drop the generator plumbing. Changes: * Add `src/Mono.Android/Mono.Android.Apis.projitems` — content matches the generator's output byte-for-byte; only the header comment now points at `Documentation/workflow/HowToAddNewApiLevel.md` instead of declaring "GENERATED FILE". * Repoint the 4 importers (`Mono.Android.targets` x2, `create-installers.targets`, `create-android-api.csproj`, `Xamarin.Android.Build.Tasks.targets`) at the new path and drop the `Condition="Exists(...)"` guards — the file is always present now. * Delete `GeneratedMonoAndroidProjitemsFile.cs` and `AndroidPlatform.cs` (whole files — `AndroidPlatform` class and `AndroidPlatformExtensions` both become unused). * Drop the `new GeneratedMonoAndroidProjitemsFile()` registration in `Step_GenerateFiles.cs`. * Remove `BuildAndroidPlatforms.AllPlatforms` and the now-unused `using System.Collections.Generic;`. Keep the NDK constants (`AndroidNdkVersion`, `AndroidNdkPkgRevision`, `NdkMinimumAPI`, `NdkMinimumAPILegacy32`) — they still have consumers. * Update `Documentation/workflow/HowToAddNewApiLevel.md` with the XML-based instructions for adding a new API level. * Narrow the `build-tools/xaprepare/README.md` blurb for `BuildAndroidPlatforms.cs` to NDK metadata. * Fix stale doc comment in `GenerateSupportedPlatforms.cs` pointing at the old generated path. Continues the xaprepare cleanup started in PRs #11568 and #11580. ### [docs] Fix Stable=True/False contradiction in HowToAddNewApiLevel The added prose said Stable should be False for preview API levels, but the example (CANARY) sets <Stable>True</Stable>, and every entry in Mono.Android.Apis.projitems is True. Rewrite the prose to match the data and briefly explain what setting Stable=False would actually do (excludes entry from default stable framework selection). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * [Xamarin.AndroidTools] Remove dead VS Mac / legacy code (#11607) Context: after the `android-platform-support` repo was inlined here (see c22cdcf), `src/Xamarin.AndroidTools/` carries a large amount of code that was only used by old VS Mac / installer / debugger-host workflows that are no longer part of the .NET for Android product. None of these types have callers anywhere in this repo, in `external/xamarin-android-tools/`, or in `external/Java.Interop/`. Removed (13 files): * `PublicationUtilities/PublishAndroidApplication.cs` * `PublicationUtilities/PackageSigningTasks.cs` * `PublicationUtilities/KeyManagement.cs` * `PublicationUtilities/KeystoreEntry.cs` * `Sessions/AndroidDeploySession.cs` * `Sessions/AndroidConnectCommandSession.cs` * `Sessions/AndroidCommandSession.cs` * `Sessions/AndroidDeploymentException.cs` * `Devices/AndroidPackageList.cs` * `Devices/AndroidPackageListExtensions.cs` * `Debugging/MonoDroidProcessMonitor.cs` * `PlatformPackage.cs` * `IProgressNotifier.cs` * `AndroidSigningOptions.cs` Moved (still needed by `ProcessUtils.cs`): * `PublicationUtilities/AndroidSdkToolException.cs` -> `AndroidSdkToolException.cs` (namespace unchanged) Pruned from `Devices/AndroidDeviceExtensions.cs` (the methods only referenced the just-deleted types and had no in-tree callers): * `StartActivityWithCommandSession` (used `AndroidCommandSession`) * `GetDeploySession`, `GetPackagesAsync`, `GetPackages` (used `AndroidDeploySession` / `IProgressNotifier`) * `InstallSharedRuntime*` and `InstallSharedPlatform*` overloads that took `IProgressNotifier` * `GetPackageRemotePath`/`GetPackageRemotePathAsync` (used `AndroidDeploymentException`) * `GetFastDevRemotePath`/`GetFastDevRemotePathAsync` and the inner `FastDevRemotePathInfo` class (only consumer was `GetPackageRemotePathAsync`) Kept methods in `AndroidDeviceExtensions.cs` are the ones still used by `Xamarin.Android.Build.Debugging.Tasks` (`EnsureProperties`, `KillProcessAndWaitForExit`, `PushAndInstallPackageAsync`) and by `DebuggingExtensions` (`SetFastDevPropertyFile`, `GetProcessIDAsync`, `SetDebugPropertiesAsync`). Also cleaned up: * `Properties/Resources.resx` (English source): removed seven `CreateKeyError_*` strings that only `KeyManagement.cs` used. * `Properties/Resources.Designer.cs`: removed the seven matching properties. * `MonoDroidSdk.cs`: two `[Obsolete]` messages referenced the now-deleted `PlatformPackage`; changed to `"Do not use."`. Non-English `Resources.*.resx` and `Localize/loc/**/*.lcl` are left alone per repo policy (auto-regenerated by OneLocBuild). Build verified locally: * `src/Xamarin.AndroidTools/Xamarin.AndroidTools.csproj` * `src/Mono.AndroidTools/Mono.AndroidTools.csproj` * `src/Xamarin.Android.Build.Debugging.Tasks/Xamarin.Android.Build.Debugging.Tasks.csproj` * `src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK.csproj` Net change: -4225 / +2 lines across 19 files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * [NUnitLite] Add OneTimeSetUp/OneTimeTearDown attribute shims NUnit 3.x renamed [TestFixtureSetUp]/[TestFixtureTearDown] to [OneTimeSetUp]/[OneTimeTearDown]. dotnet/java-interop#1437 migrated the Java.Interop test suite to the new names. The bundled Xamarin.Android.NUnitLite (src-ThirdParty/NUnitLite/) only defines the legacy names. Add no-op subclasses for the new names so test source using [OneTimeSetUp]/[OneTimeTearDown] still compiles against bundled NUnitLite once the Java.Interop submodule is bumped past dotnet/java-interop#1437. These shims become unnecessary once dotnet/android moves off bundled NUnitLite to stock NUnit (tracked in PR #11224). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: VS MobileTools Engineering Service 2 <vsmobiletoolsengsvc2@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…#11613) Continues the slow `xaprepare` removal. Recent precedent: #11568 (CopyExtraResultFilesForCI → YAML), #11580 (configuration.mk removal), #11529 (android-platform-support consolidation, which also dropped `Step_PrepareExternalGitDependencies`). ## What `Step_PrepareProps` generated `external/Java.Interop/Configuration.Override.props` (inside the submodule) by substituting two placeholders into `build-tools/scripts/Configuration.Java.Interop.Override.in.props`. The substituted properties (`_XamarinAndroidCecilVersion`, `UtilityOutputFullPathCoreApps`, `XamarinAndroidToolsDirectory`) are now supplied directly via the checked-in static file `external/Java.Interop.override.props`, which Java.Interop's own `Directory.Build.props` already auto-imports via the parent-dir convention added in dotnet/java-interop#872. The shared version values (`MonoCecilVersion`, `AndroidPackVersion`, `AndroidPackVersionSuffix`) move into `eng/Versions.props`. `Directory.Build.props` and `external/Java.Interop.override.props` both `<Import>` it. No duplicate-import sentinel is needed because every code path that imports `Configuration.props` has already loaded `Directory.Build.props` (either via MSBuild auto-load or via the explicit `<Import>` in `external/xamarin-android-tools.override.props`). `MicrosoftAndroidSdkPackName` stays in `Configuration.props` (it is OS-conditioned, not version-shaped, so it doesn't belong in `Versions.props`). The same 3-line OS-conditioned block is mirrored privately in `external/Java.Interop.override.props` as `_MicrosoftAndroidSdkPackName`, used only to compute `UtilityOutputFullPathCoreApps` for the Java.Interop build. Also dropped: - `Configurables.Paths.InstallMSBuildDir` and its backing field — the only consumer was `Step_PrepareProps`. - The dead `UtilityOutputFullPath` line in the old template — Java.Interop's `TargetFrameworkDependentValues.props` unconditionally routes it to `$(UtilityOutputFullPathCoreApps)` anyway, so it was a no-op. Updated `build-tools/scripts/XAVersionInfo.targets` (the `GitBlame` for `<AndroidPackVersion>` now points at `eng/Versions.props`) and `Documentation/guides/HowToBranch.md` to reflect the moves. ## Why not just `<Import>` `Directory.Build.props` from the Java.Interop override? That was the original idea. I prototyped it: importing dotnet/android's full props chain from `external/Java.Interop.override.props` flips `DotNetTargetFrameworkVersion` from `10.0` to `11.0` inside Java.Interop, and `dotnet restore Java.Interop.csproj` then fails with: ``` NETSDK1045: The current .NET SDK does not support targeting .NET 11.0 ``` `xamarin-android-tools.override.props` gets away with the same trick only because its sole csproj sets `AndroidToolsDisableMultiTargeting=true`, which makes the TFM-clobber harmless. Java.Interop has no equivalent escape hatch. `eng/Versions.props` is collision-free with Java.Interop (verified against the submodule sources — none of the existing entries collide), has no `<Import>` of its own, and is the safe minimal shared file. ## Verification On Windows: - `dotnet build build-tools/xaprepare/xaprepare/xaprepare.csproj` — 0 warnings, 0 errors. - From `src/Xamarin.Android.Build.Tasks/`: `dotnet msbuild --getProperty:MonoCecilVersion,AndroidPackVersion,AndroidPackVersionSuffix,MicrosoftAndroidSdkPackName,MicrosoftAndroidSdkOutDir` — values unchanged from baseline. - From `external/Java.Interop/src/Java.Interop/`: - `dotnet msbuild --getProperty:DotNetTargetFramework,_XamarinAndroidCecilVersion,UtilityOutputFullPathCoreApps` returns `net10.0`, `0.11.5`, the expected packs/tools path. - `dotnet restore Java.Interop.csproj` succeeds (no `NETSDK1045`). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
### Context `Get_Omnisharp_Json` in `Step_GenerateFiles` substituted two placeholders into `build-tools/scripts/omnisharp.json.in` and wrote `omnisharp.json` at the repo root for OmniSharp / VS Code C# extension users. The generated file was always `.gitignore`d and **nothing in the repo, build, or CI consumes it** — it was purely a local-dev convenience. Anyone who actually wants an `omnisharp.json` can keep their own local copy (it remains gitignored). Removing this generation slice is another small step in the slow xaprepare reduction, continuing the pattern from #11568, #11580, #11608, and #11613. ### Audit Before this change `git grep -in "omnisharp"` returned five hits. After it returns only one — the unrelated MSBuild-context guard in `xaprepare.csproj` that prevents xaprepare's targets from importing under OmniSharp's MSBuild process: ``` build-tools/xaprepare/xaprepare/xaprepare.csproj:52: <Import Project="xaprepare.targets" Condition=" $(MSBuildToolsPath.IndexOf('omnisharp')) < 0 " /> ``` That guard is intentional and is **not** touched by this PR. ### Changes - `build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs`: drop the `Get_Omnisharp_Json (context)` entry from the generated-files list and delete the `Get_Omnisharp_Json` method. - Delete `build-tools/scripts/omnisharp.json.in`. The shared properties used by the deleted method (`MicrosoftDotnetSdkInternalPackageVersion`, `DotNetPreviewPath`) are still referenced by `Step_InstallDotNetPreview` and `xaprepare.targets`, so they remain. ### Verification - `dotnet build build-tools/xaprepare/xaprepare/xaprepare.csproj -c Debug` — 0 warnings, 0 errors. - `git grep -in "omnisharp"` — returns only the unrelated `xaprepare.csproj` guard described above. - No `Documentation/` references to omnisharp; no `.vscode/` folder in the repo. - Diff: 3 files, 35 deletions, 0 additions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mirrors #11608 (which checked in `Mono.Android.Apis.projitems` the same way). See also #11568, #11580, #11613, #11631, #11657, #11658. ## What `build-tools/scripts/Ndk.projitems.in` was a template with `@NDK_*@` placeholders that the `Get_Ndk_projitems` generator in xaprepare filled in from constants in `BuildAndroidPlatforms.cs`. Those substitution values only change on rare NDK bumps, so generating the file on every build adds no value. This PR checks in the resolved file as a static `build-tools/scripts/Ndk.projitems` and removes the generator. ## Changes - **Add** `build-tools/scripts/Ndk.projitems` — the static, checked-in file. Rather than hardcoding values, it sources them from the existing properties in `Configuration.props` (which is imported before `Ndk.targets`): - `AndroidNdkVersion` → `$(_XAAndroidNdkRelease)` - `AndroidNdkPkgRevision` → `$(_XAAndroidNdkPkgRevision)` - the per-ABI `AndroidNdkApiLevel_*` → `$(AndroidMinimumDotNetApiLevel)` So there is nothing to keep in sync on an NDK/API bump. - **`build-tools/scripts/Ndk.targets`** — point `ProjitemsFile` at the new in-tree location (`$(MSBuildThisFileDirectory)Ndk.projitems`) instead of `bin/Build$(Configuration)/Ndk.projitems`. - **Delete** `build-tools/scripts/Ndk.projitems.in`. - **`Step_GenerateFiles.cs`** — remove the `Get_Ndk_projitems` method and its dispatch entry. - **`Configurables.cs`** — update a doc comment reference from `Ndk.projitems.in` → `Ndk.projitems`. ### Simplifications (from review) - **Collapsed the dead legacy/NET API-level split.** The legacy 32-bit minimum API level used to be lower than the .NET minimum, but they are identical now. Removed the two per-ABI properties that nothing references (`AndroidNdkApiLevel_Arm`, `AndroidNdkApiLevel_X86_Legacy`). The `arm64-v8a`/`x86_64` properties are kept because shipped targets (`Build.Tasks.targets`, `Common.props.in`, `NativeAOT.targets`) still consume them by name. - **Removed the `ApiLevelNET` item metadata.** `ApiLevelNET` was the .NET (.NET 6+) Android minimum API level vs. the legacy Xamarin.Android/Mono `ApiLevel`; the two are identical now and this repo is .NET-only. Its only consumer was `src/native/common/libunwind/libunwind-xamarin.targets`, which now reads `ApiLevel`. Dropped `ApiLevelNET` from all four `AndroidSupportedTargetJitAbi` items. The NDK constants in `BuildAndroidPlatforms.cs` are intentionally left untouched — they're still consumed by `Get_XABuildConfig_cs` and the cmake presets generator. ## Verification - `dotnet build build-tools/xaprepare/xaprepare/xaprepare.csproj -c Debug` → 0 errors / 0 warnings. - Evaluated the import chain via a standalone MSBuild harness (importing the real `Configuration.props`); it produces all four `AndroidSupportedTargetJitAbi` items with `ApiLevel`=24 and the expected `AndroidRID` metadata, matching prior generator output (NDK `28c` / pkg `28.2.13676358`). - Audits clean: `git grep Ndk.projitems.in`, `git grep Ndk_projitems`, `git grep ApiLevelNET`, and the old `bin/Build$(Configuration)/Ndk.projitems` path all return 0 hits. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Many xaprepare provisioning steps have been removed over the past year (#11332, #11348, #11399, #11440, #11441, #11636 and follow-up cleanups in #11568, #11580, #11608, #11613, #11631, #11657, #11658, #11731, #11732, #11733, #11737). The supporting scaffolding around those steps was left behind. This PR removes the verified-dead pieces in two passes. ## Files removed (first pass — original audit) | File | Justification | | --- | --- | | `Application/TestAssembly.cs` | Orphan test infra; only referenced by `TestAssemblyType.cs`. | | `Application/TestAssemblyType.cs` | Only referenced by `TestAssembly.cs`. | | `Application/StepWithDownloadProgress.cs` | No subclasses remain. | | `Application/NDKTool.cs` | NDK provisioning moved to MSBuild in #11440. Last consumer was the also-dead `Configurables.NDKTools` collection (removed below). | | `ToolRunners/SnRunner.cs` | Strong-naming tool runner; never instantiated. | | `ToolRunners/SnRunner.OutputSink.cs` | Partial sibling of `SnRunner`. | | `ToolRunners/CMakeRunner.cs` | Never instantiated. | | `ToolRunners/CMakeRunner.OutputSink.cs` | Partial sibling of `CMakeRunner`. | ## Files removed (second pass — repo-wide re-audit) | File | Justification | | --- | --- | | `ToolRunners/MakeRunner.Linux.cs` | Partial of `MakeRunner`; type never instantiated. | | `ToolRunners/MakeRunner.MacOS.cs` | Partial of `MakeRunner`. | | `ToolRunners/MakeRunner.OutputSink.Unix.cs` | Partial of `MakeRunner`. | | `ToolRunners/MakeRunner.Unix.cs` | Partial of `MakeRunner`. | | `ToolRunners/MSBuildRunner.cs` | Never instantiated. | | `ToolRunners/MSBuildRunner.OutputSink.cs` | Partial sibling of `MSBuildRunner`. | | `ToolRunners/NinjaRunner.cs` | Never instantiated. | | `ToolRunners/NinjaRunner.OutputSink.cs` | Partial sibling of `NinjaRunner`. | | `Application/ScenarioNoStandardEndSteps.cs` | Abstract class with zero subclasses. | ## Cascading cleanup - `ConfigAndData/Configurables.cs` — removed the dead `NDKTools` `List<NDKTool>` collection (lines 132–145). Rest of the file unchanged. ## Removed from initial deletion list after verification - `Application/Extensions.DictionaryOfProgramVersionParser.cs` — initial name-only audit flagged it as dead, but its `Add` extension method is consumed via dictionary collection-initializer syntax in `Application/VersionFetchers.cs`. The consumer never references the static class by name, which is why the first audit missed it. The file stays. - `Scenarios/Scenario_Required.cs` — looks unreferenced by static grep, but `Scenario` subclasses are reflectively discovered via the `[Scenario]` attribute in `Context.cs` (`Utilities.GetTypesWithCustomAttribute<ScenarioAttribute> ()`). Live. The file stays. ## Verification - `git grep -n -w <TypeName>` for each deleted type now returns 0 real hits (only unrelated `"TestAssembly"` string literals in `tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/` remain — those are assembly-name strings, not the C# type). - `dotnet build build-tools/xaprepare/xaprepare/xaprepare.csproj -c Debug` → 0 warnings, 0 errors. ## Deferred follow-up The csproj conditionally excludes `*MacOS*` files from compilation when `HostOS != Darwin`, so static dead-code analysis from a Windows/Linux host can't see whether the macOS-only consumers are themselves live. These candidates need verification on a Mac host (or a build matrix) before deletion: - `Application/PkgProgram.MacOS.cs` - `Application/HomebrewProgram.MacOS.cs` - `ToolRunners/BrewRunner.MacOS.cs` - `ToolRunners/PkgutilRunner.MacOS.cs` - `ConfigAndData/Dependencies/MacOS.cs`
…ct (#11760) Continues the incremental dismantling of `xaprepare` (see #11568, #11580, #11608, #11613, #11631, #11657, #11658, #11731, #11732, #11733, #11737, #11740). Two more generator methods come out, and the work they did moves into a small dedicated MSBuild project. ## What changes Two xaprepare generators in `build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs` are deleted: * `Get_Cmake_XA_Build_Configuration` — produced `bin/Build$(Configuration)/xa_build_configuration.cmake`, included by `src/native/CMakeLists.txt`. * `Get_Cmake_Presets` (and its `GetCmakePresetsCommon` helper) — produced `src/native/CMakePresets.json`, consumed by the `cmake` preset invocations in `src/native/native.targets`. Both are now generated by a new project: * **`src/native/cmake-config/cmake-config.csproj`** (`Microsoft.Build.NoTargets`) hosts `_GenerateCMakeFiles`, which uses the existing `ReplaceFileContents` MSBuild task to substitute the placeholders in `build-tools/scripts/xa_build_configuration.cmake.in` and `src/native/CMakePresets.json.in`. * `native-mono.csproj`, `native-clr.csproj`, and `native-nativeaot.csproj` each `<ProjectReference>` this project. ### Why a dedicated project (not just a target in `native.targets`) The three native csproj share two output files (`bin/Build$(Configuration)/xa_build_configuration.cmake` and `src/native/CMakePresets.json`). Hosting the generator in `native.targets` would either: * Race on the shared outputs under parallel msbuild (`/m`), or * Require a `'$(MSBuildProjectName)' == 'native-mono'` gate -- which breaks isolated `dotnet build native-clr.csproj` on a clean tree (the gitignored output files would never get generated). A dedicated project with three incoming `<ProjectReference>`s solves both: single producer, and project-reference ordering guarantees the outputs exist before any consumer's `cmake` preset call -- including for isolated single-csproj builds. ### Incremental correctness `_GenerateCMakeFiles` declares fully-anchored `Inputs`: * `build-tools/scripts/xa_build_configuration.cmake.in` * `src/native/CMakePresets.json.in` * `Configuration.props` (`AndroidNdkDirectory`, `NinjaPath`, `MicrosoftAndroidSdkOutDir`, `XAPackagesDir`, `AndroidMinimumDotNetApiLevel`) * `Directory.Build.props` (`TestOutputDirectory`) * `eng/Versions.props` (`MicrosoftNETCoreAppRefPackageVersion`) so editing any of those re-runs the target; a no-change rebuild skips it. (Note: `$(MSBuildAllProjects)` is intentionally **not** used -- it does not include imported `.props` files for SDK-style projects since MSBuild 16.0; verified empirically.) ### Cascading deletions in xaprepare * `Configurables.NativeSourcesDir` (was used only by `Get_Cmake_Presets`). * All eight `Configurables.Paths.NetcoreAppRuntimeAndroid*` / `CoreClrAppRuntimeAndroid*` properties (+ backing fields + the `GetNetcoreAppRuntimePath` / `GetCoreClrAppRuntimePath` helpers) -- the new MSBuild target reads `$(XAPackagesDir)` / `$(MicrosoftNETCoreAppRefPackageVersion)` directly. * The `Get_Cmake_*` entries in `Step_GenerateFiles.GetFilesToGenerate`. `BuildAndroidPlatforms.NdkMinimumAPI` / `NdkMinimumAPILegacy32` are kept -- still used by `Get_XABuildConfig_cs` (a separate generator for a future PR). ### What stays The `.in` template files are unchanged and still tracked in git -- the new MSBuild target reads them. The other generators in `Step_GenerateFiles.cs` (`Get_SourceLink_Json`, `Get_Configuration_OperatingSystem_props`, `Get_XABuildConfig_cs`, `AddOSSpecificSteps`) are out of scope and untouched. ## Verification On Windows: * `build.cmd Prepare -c Debug` * `dotnet-local.cmd build src\native\native-mono.csproj -c Debug` -> 0 errors, generates both files * `dotnet-local.cmd build src\native\native-clr.csproj -c Debug` -> 0 errors (incl. clean-tree isolated build) * `dotnet-local.cmd build src\native\native-nativeaot.csproj -c Debug` -> 0 errors * `dotnet-local.cmd build build-tools\xaprepare\xaprepare\xaprepare.csproj -c Debug` -> 0 errors Incremental behaviour verified by walking through MSBuild diagnostic output: * No-change rebuild: `Skipping target "_GenerateCMakeFiles" because all output files are up-to-date`. * `touch eng/Versions.props` + rebuild: `Building target "_GenerateCMakeFiles" completely`, outputs re-written. The generated `CMakePresets.json` and `xa_build_configuration.cmake` were diffed against the xaprepare baselines captured before the deletion; only the path separator normalisation (forward slashes throughout) differs, which both CMake and JSON accept on every platform. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
### Context After #11636 (dotnet provisioning step removed) and #11731 (test-deps scenarios removed), `Context.AutoProvision` is `false` by default everywhere except hand-run dev provisioning, which is no longer in use. The per-OS package lists are populated at `OS.Init()` time but `EnsureDependencies` is effectively a no-op: - `OS.EnsureDependencies()` returns early when `AutoProvision` is false (the default), - nothing else in the codebase reads from the `Program` derivatives' install/uninstall paths, - the `BuildToolsInventory` writer remains driven only from `EssentialTools.MacOS.cs` (homebrew version detection). The `OS.Init() / InitializeDependencies() / EnsureDependencies()` machinery on `OS.cs` itself is intentionally **left in place** here — that's a larger refactor for a follow-up PR. This PR only strips the now-vestigial package-list data and the program/runner classes that fed it. ### Files deleted (Phase F — macOS, 4 files) - `Application/HomebrewProgram.MacOS.cs` - `Application/PkgProgram.MacOS.cs` - `ToolRunners/BrewRunner.MacOS.cs` - `ToolRunners/PkgutilRunner.MacOS.cs` ### Files deleted (Phase G — Linux, 5 files) - `Application/Program.Linux.cs` (`LinuxProgram` base — orphan after subclasses go) - `Application/Program.ArchLinux.cs` - `Application/Program.DebianLinux.cs` - `Application/Program.FedoraLinux.cs` - `Application/Program.GentooLinux.cs` ### Files deleted (Phase 3 — orphan) - `Application/IBuildInventoryItem.cs` (only implementor was `HomebrewProgram`; `BuildToolsInventory` itself stays, populated directly by `EssentialTools.MacOS.cs`). ### Files reduced to empty stubs `ConfigAndData/Dependencies/`: - `MacOS.cs` — `InitializeDependencies()` no-op (was Homebrew formula list + git fallback). - `Linux.Arch.cs` — class kept (referenced by `distroMap`); package list removed. - `Linux.Fedora.cs` — same. - `Linux.Gentoo.cs` — same. - `Linux.DebianCommon.cs` — common Debian/Ubuntu package list removed; `Flavor = "Debian"` kept. - `Linux.UbuntuCommon.cs` — `libtoolPackages` + `NeedLibtool` virtual + `InitOS` override removed (all dead). - `Linux.Debian.cs` — all per-version package lists (`packages`, `packagesPre10`, `packagesPreTrixie`, `packagesTrixieAndLater`, `packages10AndNewerBuildBots`) removed; release/codename detection (`EnsureVersionInformation`, `DebianUnstableVersionMap`, `IsDebian10OrNewer`, etc.) preserved as conservative scope. - `Linux.Ubuntu.cs` — `preCosmicPackages`, `cosmicPackages`, `preDiscoPackages` lists + `NeedLibtool` override removed; `UbuntuRelease` + `EnsureVersionInformation` preserved. - `Linux.Mint.cs` — `NeedLibtool` override removed (the property is gone from the base). `ConfigAndData/Dependencies/Windows.cs` was already a no-op stub — no edit. ### Verification Orphan audit (each `git grep -nw <Type> -- 'build-tools/xaprepare/*'` reports **0 hits**): - `HomebrewProgram`, `PkgProgram`, `BrewRunner`, `PkgutilRunner` - `ArchLinuxProgram`, `DebianLinuxProgram`, `FedoraLinuxProgram`, `GentooLinuxProgram`, `LinuxProgram` - `IBuildInventoryItem` Build: ``` dotnet build build-tools\xaprepare\xaprepare\xaprepare.csproj -c Debug Build succeeded. 0 Warning(s) 0 Error(s) ``` ### Out of scope (follow-up) - Removing the abstract `OS.InitializeDependencies()` declaration and the surrounding `EnsureDependencies()` machinery from `OperatingSystems/OS.cs`. - `VersionFetchers` / `ProgramVersionParser` / `RegexProgramVersionParser` / `SevenZipVersionParser` / `Extensions.DictionaryOfProgramVersionParser.cs` are kept — `Utilities.GetProgramVersion` still queries them from `Program.cs`, `ToolRunner.cs`, `EssentialTools.MacOS.cs`, and `OperatingSystems/MacOS.cs` (brew detection). ### Precedent #11568, #11580, #11608, #11613, #11631, #11657, #11658, #11731, #11732, #11733, #11737, #11740, #11760
…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>
…11825) 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. ### Simplify generate-cgmanifest.yaml using ConvertTo-Json 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>
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>
Part of slowly removing
xaprepare.The
CopyExtraResultFilesForCIscenario existed only to copy build/test artifacts into$(Build.StagingDirectory)on Azure DevOps beforePublishPipelineArtifact— something the built-inCopyFiles@2task can do natively.Changes
build-tools/automation/yaml-templates/copy-extra-result-files.yamlreproducing the C# step's file globs and destination layout (Build$(Configuration),Test$(Configuration),test-extras/,compatibility/) usingCopyFiles@2. A smallpwshstep uses[System.IO.Path]::GetTempPath()to match the originalPath.GetTempPath()behavior forllc.exe-*collection.upload-results.yaml(the only caller) to invoke the new template instead ofrun-xaprepare.yaml --s=CopyExtraResultFilesForCI.build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.csandbuild-tools/xaprepare/xaprepare/Scenarios/Scenario_CopyExtraResultFilesForCI.cs.Behavior parity
The YAML reproduces the C# step file-for-file:
Configuration.OperatingSystem.props,Configuration.Override.props,config.log,config.status,config.h,android-*.config.cache(preserve relative paths)**/<pattern>withflattenFolders: falseCMakeFiles/*.log(preserve paths)CMakeFiles/*.logwithflattenFolders: falseexternal/Java.Interop/bin/Build$(Config)/*.props(preserve paths)flattenFolders: falsebin/Build$(Config)/<pattern>flat (XABuildConfig.cs, .binlog, preparelog, *.json, *.mk, *.projitems, *.cmake, .targets, CMakeCache.txt, .ninja_log, clang-tidy.log)flattenFolders: truebin/Test$(Config)/<pattern>flat (.apkdesc, .aabdesc, logcat-.txt, log, TestOutput-.txt, Timing_, *.runsettings)flattenFolders: truebin/Test$(Config)/compatibility/*→Test$(Config)/compatibility/CopyFiles@2TestResult*.xml,*.csv→Test$(Config)/test-extras/(top-level only)flattenFolders: truellc.exe-*→Test$(Config)/test-extras/pwshstep using[System.IO.Path]::GetTempPath()Two no-ops from the C# step are intentionally dropped:
packages/cleanup of the destination — the narrow filename patterns will never copy anything from apackagesdirectory.CopyFiles@2does not create empty directories.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com