[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll - #11826

Merged
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild
Jul 1, 2026
Merged

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll#11826
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild

Conversation

@jonathanpeppers

@jonathanpeppersjonathanpeppers commented Jun 30, 2026

Copy link
Copy Markdown
Member

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.
  • ProjectReferences 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.insrc/AndroidBuildConfig/XABuildConfig.cs.in (static classpublic 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 classpublic 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.

Mirrors the cmake-config.csproj precedent (#11760): a new
Microsoft.Build.NoTargets project at
build-tools/scripts/xabuildconfig/xabuildconfig.csproj generates
bin/Build$(Configuration)/XABuildConfig.cs from
build-tools/scripts/XABuildConfig.cs.in using the existing
ReplaceFileContents, GitCommitHash, and GitBranch prep tasks (all
hosted via TaskFactory=TaskHostFactory Runtime=NET, per the
internal-prep-task convention). All substitution values come from
Configuration.props properties already in scope - no new C# task code
required.
The three consumers that <Compile Include> XABuildConfig.cs now
<ProjectReference> the new csproj with ReferenceOutputAssembly=False,
ensuring single-execution and ordering for isolated builds:
* 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
The generated file is byte-identical to the prior xaprepare output
(verified via fc /b against a baseline captured before the change).
xaprepare cleanup (the only consumers of these methods/properties were
the deleted Get_XABuildConfig_cs and its helpers):
* Step_GenerateFiles.cs: deleted Get_XABuildConfig_cs and its
GetMajor/GetMinor helpers; the at-build-start list now contains
only Get_Configuration_OperatingSystem_props.
* BuildInfo.cs: deleted NDKRevision, NDKVersionMajor/Minor/Micro,
NDKVersion, cachedNdkVersion, XACommitHash, XABranch,
GatherGitInfo, and DetermineXACommitInfo.
* Context.cs: removed the
`if (SelectedScenario.NeedsGitBuildInfo)` GatherGitInfo block.
* Scenario.cs / Scenario_Required.cs / Scenario_Standard.cs:
removed the now-unused NeedsGitBuildInfo property and setters.
* ConfigAndData/BuildAndroidPlatforms.cs: entire file deleted -
AndroidNdkVersion, AndroidNdkPkgRevision, NdkMinimumAPI, and
NdkMinimumAPILegacy32 were all sourced from Configuration.props
by way of Get_XABuildConfig_cs.
* Utilities.cs: deleted ParseAndroidPkgRevision (sole caller was
BuildInfo.NDKVersion).
* GitRunner.cs: deleted GetTopCommitHash and GetBranchName (sole
caller was BuildInfo.DetermineXACommitInfo). The GitRunner class
is retained - other consumers (Blame, SubmoduleUpdate, etc.) remain.
* README.md: dropped the BuildAndroidPlatforms.cs bullet.
Net diff: +6 / -195 (one new ~120-line csproj, ~175 lines of C# removed).
Verification:
* xaprepare.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: builds; consumes the
MSBuild-generated XABuildConfig.cs unchanged.
* Incremental rebuild of xabuildconfig.csproj reports
_GenerateXABuildConfig as up-to-date.
* fc /b vs baseline: no differences encountered.
Precedent PRs in this incremental xaprepare removal stream: #11568,
#11580, #11608, #11613, #11631, #11731, #11732, #11733, #11737, #11740,
#11760, #11803, #11821, #11825.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 21:10
…ass library
Follow-up to commit f6958e4 on this branch.
The previous commit moved XABuildConfig.cs generation out of xaprepare
into a NoTargets MSBuild project that produced
bin/Build$(Configuration)/XABuildConfig.cs and was <Compile Include>'d
into three csprojs (Xamarin.Android.Build.Tasks, Xamarin.ProjectTools,
Xamarin.Android.Build.Tests). That preserved byte-equivalence with
xaprepare's output but kept the long-standing problem that the same
type (Xamarin.Android.Tools.XABuildConfig) ended up compiled into
three different assemblies. Because Build.Tests references Build.Tasks
(which exposes its internals via InternalsVisibleTo), every use of
XABuildConfig in test sources produced CS0436 "type conflicts with
imported type" warnings — about 22 of them.
This commit collapses XABuildConfig to a single definition by making
it a real class library:
* New project src/AndroidBuildConfig/AndroidBuildConfig.csproj is a
regular Microsoft.NET.Sdk netstandard2.0 strong-named assembly. It
generates obj/$(Configuration)/$(TargetFramework)/XABuildConfig.cs
from XABuildConfig.cs.in (now living alongside the csproj) using
the same GitCommitHash / GitBranch / ReplaceFileContents tasks as
before, with the BeforeCompile + Compile-inside-target pattern so
the generated file lands under obj/ instead of the source tree.
* The XABuildConfig class is now public, so consumers reference the
assembly normally (the user explicitly OK'd making it public).
* The three consumer csprojs lose their <Compile Include> for
XABuildConfig.cs and reference AndroidBuildConfig with a normal
ProjectReference (no ReferenceOutputAssembly=False).
* build-tools/installers/create-installers.targets ships
AndroidBuildConfig.dll and .pdb alongside Xamarin.Android.Build.Tasks
so the SDK installer carries the new dll.
Verification:
* AndroidBuildConfig.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: 0 errors, 85 pre-existing
unrelated warnings (none referencing XABuildConfig).
* Xamarin.Android.Build.Tests.csproj: 0 errors, 7 warnings — down
from ~22, the ~15 XABuildConfig CS0436 warnings are eliminated.
* xaprepare.csproj: 0 warnings, 0 errors.
* Generated XABuildConfig.cs matches the previous output exactly
apart from "static class" -> "public static class" (the
intentional change) and the expected commit-hash / branch drift.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers changed the title [xaprepare] Move XABuildConfig.cs generation from xaprepare to MSBuild[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dllJun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

jonathanpeppersand others added 2 commits July 1, 2026 08:04
Without this the CI build fails on Windows/Linux because the project
reference from Xamarin.Android.Build.Tasks (built via the sln in Release)
somehow triggers AndroidBuildConfig with Configuration=Debug, so it looks
for bin\BuildDebug\net10.0\xa-prep-tasks.dll -- which doesn't exist yet.
Adding the project to the sln with proper Debug/Release configuration
mappings (mirroring cmake-config which has the same pattern) ensures the
solution build passes Configuration correctly.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Jul 1, 2026
@jonathanpeppers
jonathanpeppers merged commit 788d363 into mainJul 1, 2026
40 checks passed
@jonathanpeppers
jonathanpeppers deleted the jonathanpeppers-xabuildconfig-to-msbuild branch July 1, 2026 16:57
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
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>
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
…#11945)
Follow-up to #11826. After that PR moved XABuildConfig generation to AndroidBuildConfig.dll and removed instance members from BuildInfo, the entire cascade downstream of `BuildInfo.DetermineLastVersionChangeCommit` became unreachable.
Removed:
* `Application/BuildInfo.cs` (whole file — all members orphan)
* `ToolRunners/GitRunner.BlamePorcelainEntry.cs` (whole file)
* `GitRunner` `Blame(...)` overloads (3), `ParseBlameLine`, and now-unused `SetCommandArguments` helper
* `Context.BuildInfo` property + assignment in `Init()`
* `Utilities.ShortenGitHash` and its only consumer `Configurables.Defaults.AbbreviatedHashLength`
`BuildInfo.cs.in` was changed from `partial class` to `static class` since only `XAVersion` remains; `Main.cs` still uses `BuildInfo.XAVersion`.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival pushed a commit that referenced this pull request Jul 3, 2026
…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>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

ready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jonathanpeppers@simonrozsival
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll - #11826

Merged
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild
Jul 1, 2026
Merged

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll#11826
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild

Conversation

@jonathanpeppers

@jonathanpeppersjonathanpeppers commented Jun 30, 2026

Copy link
Copy Markdown
Member

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.
  • ProjectReferences 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.insrc/AndroidBuildConfig/XABuildConfig.cs.in (static classpublic 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 classpublic 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.

Mirrors the cmake-config.csproj precedent (#11760): a new
Microsoft.Build.NoTargets project at
build-tools/scripts/xabuildconfig/xabuildconfig.csproj generates
bin/Build$(Configuration)/XABuildConfig.cs from
build-tools/scripts/XABuildConfig.cs.in using the existing
ReplaceFileContents, GitCommitHash, and GitBranch prep tasks (all
hosted via TaskFactory=TaskHostFactory Runtime=NET, per the
internal-prep-task convention). All substitution values come from
Configuration.props properties already in scope - no new C# task code
required.
The three consumers that <Compile Include> XABuildConfig.cs now
<ProjectReference> the new csproj with ReferenceOutputAssembly=False,
ensuring single-execution and ordering for isolated builds:
* 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
The generated file is byte-identical to the prior xaprepare output
(verified via fc /b against a baseline captured before the change).
xaprepare cleanup (the only consumers of these methods/properties were
the deleted Get_XABuildConfig_cs and its helpers):
* Step_GenerateFiles.cs: deleted Get_XABuildConfig_cs and its
GetMajor/GetMinor helpers; the at-build-start list now contains
only Get_Configuration_OperatingSystem_props.
* BuildInfo.cs: deleted NDKRevision, NDKVersionMajor/Minor/Micro,
NDKVersion, cachedNdkVersion, XACommitHash, XABranch,
GatherGitInfo, and DetermineXACommitInfo.
* Context.cs: removed the
`if (SelectedScenario.NeedsGitBuildInfo)` GatherGitInfo block.
* Scenario.cs / Scenario_Required.cs / Scenario_Standard.cs:
removed the now-unused NeedsGitBuildInfo property and setters.
* ConfigAndData/BuildAndroidPlatforms.cs: entire file deleted -
AndroidNdkVersion, AndroidNdkPkgRevision, NdkMinimumAPI, and
NdkMinimumAPILegacy32 were all sourced from Configuration.props
by way of Get_XABuildConfig_cs.
* Utilities.cs: deleted ParseAndroidPkgRevision (sole caller was
BuildInfo.NDKVersion).
* GitRunner.cs: deleted GetTopCommitHash and GetBranchName (sole
caller was BuildInfo.DetermineXACommitInfo). The GitRunner class
is retained - other consumers (Blame, SubmoduleUpdate, etc.) remain.
* README.md: dropped the BuildAndroidPlatforms.cs bullet.
Net diff: +6 / -195 (one new ~120-line csproj, ~175 lines of C# removed).
Verification:
* xaprepare.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: builds; consumes the
MSBuild-generated XABuildConfig.cs unchanged.
* Incremental rebuild of xabuildconfig.csproj reports
_GenerateXABuildConfig as up-to-date.
* fc /b vs baseline: no differences encountered.
Precedent PRs in this incremental xaprepare removal stream: #11568,
#11580, #11608, #11613, #11631, #11731, #11732, #11733, #11737, #11740,
#11760, #11803, #11821, #11825.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 21:10
…ass library
Follow-up to commit f6958e4 on this branch.
The previous commit moved XABuildConfig.cs generation out of xaprepare
into a NoTargets MSBuild project that produced
bin/Build$(Configuration)/XABuildConfig.cs and was <Compile Include>'d
into three csprojs (Xamarin.Android.Build.Tasks, Xamarin.ProjectTools,
Xamarin.Android.Build.Tests). That preserved byte-equivalence with
xaprepare's output but kept the long-standing problem that the same
type (Xamarin.Android.Tools.XABuildConfig) ended up compiled into
three different assemblies. Because Build.Tests references Build.Tasks
(which exposes its internals via InternalsVisibleTo), every use of
XABuildConfig in test sources produced CS0436 "type conflicts with
imported type" warnings — about 22 of them.
This commit collapses XABuildConfig to a single definition by making
it a real class library:
* New project src/AndroidBuildConfig/AndroidBuildConfig.csproj is a
regular Microsoft.NET.Sdk netstandard2.0 strong-named assembly. It
generates obj/$(Configuration)/$(TargetFramework)/XABuildConfig.cs
from XABuildConfig.cs.in (now living alongside the csproj) using
the same GitCommitHash / GitBranch / ReplaceFileContents tasks as
before, with the BeforeCompile + Compile-inside-target pattern so
the generated file lands under obj/ instead of the source tree.
* The XABuildConfig class is now public, so consumers reference the
assembly normally (the user explicitly OK'd making it public).
* The three consumer csprojs lose their <Compile Include> for
XABuildConfig.cs and reference AndroidBuildConfig with a normal
ProjectReference (no ReferenceOutputAssembly=False).
* build-tools/installers/create-installers.targets ships
AndroidBuildConfig.dll and .pdb alongside Xamarin.Android.Build.Tasks
so the SDK installer carries the new dll.
Verification:
* AndroidBuildConfig.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: 0 errors, 85 pre-existing
unrelated warnings (none referencing XABuildConfig).
* Xamarin.Android.Build.Tests.csproj: 0 errors, 7 warnings — down
from ~22, the ~15 XABuildConfig CS0436 warnings are eliminated.
* xaprepare.csproj: 0 warnings, 0 errors.
* Generated XABuildConfig.cs matches the previous output exactly
apart from "static class" -> "public static class" (the
intentional change) and the expected commit-hash / branch drift.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers changed the title [xaprepare] Move XABuildConfig.cs generation from xaprepare to MSBuild[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dllJun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

jonathanpeppersand others added 2 commits July 1, 2026 08:04
Without this the CI build fails on Windows/Linux because the project
reference from Xamarin.Android.Build.Tasks (built via the sln in Release)
somehow triggers AndroidBuildConfig with Configuration=Debug, so it looks
for bin\BuildDebug\net10.0\xa-prep-tasks.dll -- which doesn't exist yet.
Adding the project to the sln with proper Debug/Release configuration
mappings (mirroring cmake-config which has the same pattern) ensures the
solution build passes Configuration correctly.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Jul 1, 2026
@jonathanpeppers
jonathanpeppers merged commit 788d363 into mainJul 1, 2026
40 checks passed
@jonathanpeppers
jonathanpeppers deleted the jonathanpeppers-xabuildconfig-to-msbuild branch July 1, 2026 16:57
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
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>
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
…#11945)
Follow-up to #11826. After that PR moved XABuildConfig generation to AndroidBuildConfig.dll and removed instance members from BuildInfo, the entire cascade downstream of `BuildInfo.DetermineLastVersionChangeCommit` became unreachable.
Removed:
* `Application/BuildInfo.cs` (whole file — all members orphan)
* `ToolRunners/GitRunner.BlamePorcelainEntry.cs` (whole file)
* `GitRunner` `Blame(...)` overloads (3), `ParseBlameLine`, and now-unused `SetCommandArguments` helper
* `Context.BuildInfo` property + assignment in `Init()`
* `Utilities.ShortenGitHash` and its only consumer `Configurables.Defaults.AbbreviatedHashLength`
`BuildInfo.cs.in` was changed from `partial class` to `static class` since only `XAVersion` remains; `Main.cs` still uses `BuildInfo.XAVersion`.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival pushed a commit that referenced this pull request Jul 3, 2026
…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>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

ready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jonathanpeppers@simonrozsival
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll - #11826

Merged
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild
Jul 1, 2026
Merged

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll#11826
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild

Conversation

@jonathanpeppers

@jonathanpeppersjonathanpeppers commented Jun 30, 2026

Copy link
Copy Markdown
Member

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.
  • ProjectReferences 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.insrc/AndroidBuildConfig/XABuildConfig.cs.in (static classpublic 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 classpublic 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.

Mirrors the cmake-config.csproj precedent (#11760): a new
Microsoft.Build.NoTargets project at
build-tools/scripts/xabuildconfig/xabuildconfig.csproj generates
bin/Build$(Configuration)/XABuildConfig.cs from
build-tools/scripts/XABuildConfig.cs.in using the existing
ReplaceFileContents, GitCommitHash, and GitBranch prep tasks (all
hosted via TaskFactory=TaskHostFactory Runtime=NET, per the
internal-prep-task convention). All substitution values come from
Configuration.props properties already in scope - no new C# task code
required.
The three consumers that <Compile Include> XABuildConfig.cs now
<ProjectReference> the new csproj with ReferenceOutputAssembly=False,
ensuring single-execution and ordering for isolated builds:
* 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
The generated file is byte-identical to the prior xaprepare output
(verified via fc /b against a baseline captured before the change).
xaprepare cleanup (the only consumers of these methods/properties were
the deleted Get_XABuildConfig_cs and its helpers):
* Step_GenerateFiles.cs: deleted Get_XABuildConfig_cs and its
GetMajor/GetMinor helpers; the at-build-start list now contains
only Get_Configuration_OperatingSystem_props.
* BuildInfo.cs: deleted NDKRevision, NDKVersionMajor/Minor/Micro,
NDKVersion, cachedNdkVersion, XACommitHash, XABranch,
GatherGitInfo, and DetermineXACommitInfo.
* Context.cs: removed the
`if (SelectedScenario.NeedsGitBuildInfo)` GatherGitInfo block.
* Scenario.cs / Scenario_Required.cs / Scenario_Standard.cs:
removed the now-unused NeedsGitBuildInfo property and setters.
* ConfigAndData/BuildAndroidPlatforms.cs: entire file deleted -
AndroidNdkVersion, AndroidNdkPkgRevision, NdkMinimumAPI, and
NdkMinimumAPILegacy32 were all sourced from Configuration.props
by way of Get_XABuildConfig_cs.
* Utilities.cs: deleted ParseAndroidPkgRevision (sole caller was
BuildInfo.NDKVersion).
* GitRunner.cs: deleted GetTopCommitHash and GetBranchName (sole
caller was BuildInfo.DetermineXACommitInfo). The GitRunner class
is retained - other consumers (Blame, SubmoduleUpdate, etc.) remain.
* README.md: dropped the BuildAndroidPlatforms.cs bullet.
Net diff: +6 / -195 (one new ~120-line csproj, ~175 lines of C# removed).
Verification:
* xaprepare.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: builds; consumes the
MSBuild-generated XABuildConfig.cs unchanged.
* Incremental rebuild of xabuildconfig.csproj reports
_GenerateXABuildConfig as up-to-date.
* fc /b vs baseline: no differences encountered.
Precedent PRs in this incremental xaprepare removal stream: #11568,
#11580, #11608, #11613, #11631, #11731, #11732, #11733, #11737, #11740,
#11760, #11803, #11821, #11825.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 21:10
…ass library
Follow-up to commit f6958e4 on this branch.
The previous commit moved XABuildConfig.cs generation out of xaprepare
into a NoTargets MSBuild project that produced
bin/Build$(Configuration)/XABuildConfig.cs and was <Compile Include>'d
into three csprojs (Xamarin.Android.Build.Tasks, Xamarin.ProjectTools,
Xamarin.Android.Build.Tests). That preserved byte-equivalence with
xaprepare's output but kept the long-standing problem that the same
type (Xamarin.Android.Tools.XABuildConfig) ended up compiled into
three different assemblies. Because Build.Tests references Build.Tasks
(which exposes its internals via InternalsVisibleTo), every use of
XABuildConfig in test sources produced CS0436 "type conflicts with
imported type" warnings — about 22 of them.
This commit collapses XABuildConfig to a single definition by making
it a real class library:
* New project src/AndroidBuildConfig/AndroidBuildConfig.csproj is a
regular Microsoft.NET.Sdk netstandard2.0 strong-named assembly. It
generates obj/$(Configuration)/$(TargetFramework)/XABuildConfig.cs
from XABuildConfig.cs.in (now living alongside the csproj) using
the same GitCommitHash / GitBranch / ReplaceFileContents tasks as
before, with the BeforeCompile + Compile-inside-target pattern so
the generated file lands under obj/ instead of the source tree.
* The XABuildConfig class is now public, so consumers reference the
assembly normally (the user explicitly OK'd making it public).
* The three consumer csprojs lose their <Compile Include> for
XABuildConfig.cs and reference AndroidBuildConfig with a normal
ProjectReference (no ReferenceOutputAssembly=False).
* build-tools/installers/create-installers.targets ships
AndroidBuildConfig.dll and .pdb alongside Xamarin.Android.Build.Tasks
so the SDK installer carries the new dll.
Verification:
* AndroidBuildConfig.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: 0 errors, 85 pre-existing
unrelated warnings (none referencing XABuildConfig).
* Xamarin.Android.Build.Tests.csproj: 0 errors, 7 warnings — down
from ~22, the ~15 XABuildConfig CS0436 warnings are eliminated.
* xaprepare.csproj: 0 warnings, 0 errors.
* Generated XABuildConfig.cs matches the previous output exactly
apart from "static class" -> "public static class" (the
intentional change) and the expected commit-hash / branch drift.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers changed the title [xaprepare] Move XABuildConfig.cs generation from xaprepare to MSBuild[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dllJun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

jonathanpeppersand others added 2 commits July 1, 2026 08:04
Without this the CI build fails on Windows/Linux because the project
reference from Xamarin.Android.Build.Tasks (built via the sln in Release)
somehow triggers AndroidBuildConfig with Configuration=Debug, so it looks
for bin\BuildDebug\net10.0\xa-prep-tasks.dll -- which doesn't exist yet.
Adding the project to the sln with proper Debug/Release configuration
mappings (mirroring cmake-config which has the same pattern) ensures the
solution build passes Configuration correctly.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Jul 1, 2026
@jonathanpeppers
jonathanpeppers merged commit 788d363 into mainJul 1, 2026
40 checks passed
@jonathanpeppers
jonathanpeppers deleted the jonathanpeppers-xabuildconfig-to-msbuild branch July 1, 2026 16:57
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
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>
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
…#11945)
Follow-up to #11826. After that PR moved XABuildConfig generation to AndroidBuildConfig.dll and removed instance members from BuildInfo, the entire cascade downstream of `BuildInfo.DetermineLastVersionChangeCommit` became unreachable.
Removed:
* `Application/BuildInfo.cs` (whole file — all members orphan)
* `ToolRunners/GitRunner.BlamePorcelainEntry.cs` (whole file)
* `GitRunner` `Blame(...)` overloads (3), `ParseBlameLine`, and now-unused `SetCommandArguments` helper
* `Context.BuildInfo` property + assignment in `Init()`
* `Utilities.ShortenGitHash` and its only consumer `Configurables.Defaults.AbbreviatedHashLength`
`BuildInfo.cs.in` was changed from `partial class` to `static class` since only `XAVersion` remains; `Main.cs` still uses `BuildInfo.XAVersion`.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival pushed a commit that referenced this pull request Jul 3, 2026
…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>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

ready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jonathanpeppers@simonrozsival
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll - #11826

Merged
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild
Jul 1, 2026
Merged

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll#11826
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild

Conversation

@jonathanpeppers

@jonathanpeppersjonathanpeppers commented Jun 30, 2026

Copy link
Copy Markdown
Member

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.
  • ProjectReferences 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.insrc/AndroidBuildConfig/XABuildConfig.cs.in (static classpublic 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 classpublic 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.

Mirrors the cmake-config.csproj precedent (#11760): a new
Microsoft.Build.NoTargets project at
build-tools/scripts/xabuildconfig/xabuildconfig.csproj generates
bin/Build$(Configuration)/XABuildConfig.cs from
build-tools/scripts/XABuildConfig.cs.in using the existing
ReplaceFileContents, GitCommitHash, and GitBranch prep tasks (all
hosted via TaskFactory=TaskHostFactory Runtime=NET, per the
internal-prep-task convention). All substitution values come from
Configuration.props properties already in scope - no new C# task code
required.
The three consumers that <Compile Include> XABuildConfig.cs now
<ProjectReference> the new csproj with ReferenceOutputAssembly=False,
ensuring single-execution and ordering for isolated builds:
* 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
The generated file is byte-identical to the prior xaprepare output
(verified via fc /b against a baseline captured before the change).
xaprepare cleanup (the only consumers of these methods/properties were
the deleted Get_XABuildConfig_cs and its helpers):
* Step_GenerateFiles.cs: deleted Get_XABuildConfig_cs and its
GetMajor/GetMinor helpers; the at-build-start list now contains
only Get_Configuration_OperatingSystem_props.
* BuildInfo.cs: deleted NDKRevision, NDKVersionMajor/Minor/Micro,
NDKVersion, cachedNdkVersion, XACommitHash, XABranch,
GatherGitInfo, and DetermineXACommitInfo.
* Context.cs: removed the
`if (SelectedScenario.NeedsGitBuildInfo)` GatherGitInfo block.
* Scenario.cs / Scenario_Required.cs / Scenario_Standard.cs:
removed the now-unused NeedsGitBuildInfo property and setters.
* ConfigAndData/BuildAndroidPlatforms.cs: entire file deleted -
AndroidNdkVersion, AndroidNdkPkgRevision, NdkMinimumAPI, and
NdkMinimumAPILegacy32 were all sourced from Configuration.props
by way of Get_XABuildConfig_cs.
* Utilities.cs: deleted ParseAndroidPkgRevision (sole caller was
BuildInfo.NDKVersion).
* GitRunner.cs: deleted GetTopCommitHash and GetBranchName (sole
caller was BuildInfo.DetermineXACommitInfo). The GitRunner class
is retained - other consumers (Blame, SubmoduleUpdate, etc.) remain.
* README.md: dropped the BuildAndroidPlatforms.cs bullet.
Net diff: +6 / -195 (one new ~120-line csproj, ~175 lines of C# removed).
Verification:
* xaprepare.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: builds; consumes the
MSBuild-generated XABuildConfig.cs unchanged.
* Incremental rebuild of xabuildconfig.csproj reports
_GenerateXABuildConfig as up-to-date.
* fc /b vs baseline: no differences encountered.
Precedent PRs in this incremental xaprepare removal stream: #11568,
#11580, #11608, #11613, #11631, #11731, #11732, #11733, #11737, #11740,
#11760, #11803, #11821, #11825.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 21:10
…ass library
Follow-up to commit f6958e4 on this branch.
The previous commit moved XABuildConfig.cs generation out of xaprepare
into a NoTargets MSBuild project that produced
bin/Build$(Configuration)/XABuildConfig.cs and was <Compile Include>'d
into three csprojs (Xamarin.Android.Build.Tasks, Xamarin.ProjectTools,
Xamarin.Android.Build.Tests). That preserved byte-equivalence with
xaprepare's output but kept the long-standing problem that the same
type (Xamarin.Android.Tools.XABuildConfig) ended up compiled into
three different assemblies. Because Build.Tests references Build.Tasks
(which exposes its internals via InternalsVisibleTo), every use of
XABuildConfig in test sources produced CS0436 "type conflicts with
imported type" warnings — about 22 of them.
This commit collapses XABuildConfig to a single definition by making
it a real class library:
* New project src/AndroidBuildConfig/AndroidBuildConfig.csproj is a
regular Microsoft.NET.Sdk netstandard2.0 strong-named assembly. It
generates obj/$(Configuration)/$(TargetFramework)/XABuildConfig.cs
from XABuildConfig.cs.in (now living alongside the csproj) using
the same GitCommitHash / GitBranch / ReplaceFileContents tasks as
before, with the BeforeCompile + Compile-inside-target pattern so
the generated file lands under obj/ instead of the source tree.
* The XABuildConfig class is now public, so consumers reference the
assembly normally (the user explicitly OK'd making it public).
* The three consumer csprojs lose their <Compile Include> for
XABuildConfig.cs and reference AndroidBuildConfig with a normal
ProjectReference (no ReferenceOutputAssembly=False).
* build-tools/installers/create-installers.targets ships
AndroidBuildConfig.dll and .pdb alongside Xamarin.Android.Build.Tasks
so the SDK installer carries the new dll.
Verification:
* AndroidBuildConfig.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: 0 errors, 85 pre-existing
unrelated warnings (none referencing XABuildConfig).
* Xamarin.Android.Build.Tests.csproj: 0 errors, 7 warnings — down
from ~22, the ~15 XABuildConfig CS0436 warnings are eliminated.
* xaprepare.csproj: 0 warnings, 0 errors.
* Generated XABuildConfig.cs matches the previous output exactly
apart from "static class" -> "public static class" (the
intentional change) and the expected commit-hash / branch drift.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers changed the title [xaprepare] Move XABuildConfig.cs generation from xaprepare to MSBuild[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dllJun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

jonathanpeppersand others added 2 commits July 1, 2026 08:04
Without this the CI build fails on Windows/Linux because the project
reference from Xamarin.Android.Build.Tasks (built via the sln in Release)
somehow triggers AndroidBuildConfig with Configuration=Debug, so it looks
for bin\BuildDebug\net10.0\xa-prep-tasks.dll -- which doesn't exist yet.
Adding the project to the sln with proper Debug/Release configuration
mappings (mirroring cmake-config which has the same pattern) ensures the
solution build passes Configuration correctly.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Jul 1, 2026
@jonathanpeppers
jonathanpeppers merged commit 788d363 into mainJul 1, 2026
40 checks passed
@jonathanpeppers
jonathanpeppers deleted the jonathanpeppers-xabuildconfig-to-msbuild branch July 1, 2026 16:57
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
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>
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
…#11945)
Follow-up to #11826. After that PR moved XABuildConfig generation to AndroidBuildConfig.dll and removed instance members from BuildInfo, the entire cascade downstream of `BuildInfo.DetermineLastVersionChangeCommit` became unreachable.
Removed:
* `Application/BuildInfo.cs` (whole file — all members orphan)
* `ToolRunners/GitRunner.BlamePorcelainEntry.cs` (whole file)
* `GitRunner` `Blame(...)` overloads (3), `ParseBlameLine`, and now-unused `SetCommandArguments` helper
* `Context.BuildInfo` property + assignment in `Init()`
* `Utilities.ShortenGitHash` and its only consumer `Configurables.Defaults.AbbreviatedHashLength`
`BuildInfo.cs.in` was changed from `partial class` to `static class` since only `XAVersion` remains; `Main.cs` still uses `BuildInfo.XAVersion`.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival pushed a commit that referenced this pull request Jul 3, 2026
…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>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

ready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jonathanpeppers@simonrozsival
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll - #11826

Merged
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild
Jul 1, 2026
Merged

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll#11826
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild

Conversation

@jonathanpeppers

@jonathanpeppersjonathanpeppers commented Jun 30, 2026

Copy link
Copy Markdown
Member

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.
  • ProjectReferences 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.insrc/AndroidBuildConfig/XABuildConfig.cs.in (static classpublic 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 classpublic 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.

Mirrors the cmake-config.csproj precedent (#11760): a new
Microsoft.Build.NoTargets project at
build-tools/scripts/xabuildconfig/xabuildconfig.csproj generates
bin/Build$(Configuration)/XABuildConfig.cs from
build-tools/scripts/XABuildConfig.cs.in using the existing
ReplaceFileContents, GitCommitHash, and GitBranch prep tasks (all
hosted via TaskFactory=TaskHostFactory Runtime=NET, per the
internal-prep-task convention). All substitution values come from
Configuration.props properties already in scope - no new C# task code
required.
The three consumers that <Compile Include> XABuildConfig.cs now
<ProjectReference> the new csproj with ReferenceOutputAssembly=False,
ensuring single-execution and ordering for isolated builds:
* 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
The generated file is byte-identical to the prior xaprepare output
(verified via fc /b against a baseline captured before the change).
xaprepare cleanup (the only consumers of these methods/properties were
the deleted Get_XABuildConfig_cs and its helpers):
* Step_GenerateFiles.cs: deleted Get_XABuildConfig_cs and its
GetMajor/GetMinor helpers; the at-build-start list now contains
only Get_Configuration_OperatingSystem_props.
* BuildInfo.cs: deleted NDKRevision, NDKVersionMajor/Minor/Micro,
NDKVersion, cachedNdkVersion, XACommitHash, XABranch,
GatherGitInfo, and DetermineXACommitInfo.
* Context.cs: removed the
`if (SelectedScenario.NeedsGitBuildInfo)` GatherGitInfo block.
* Scenario.cs / Scenario_Required.cs / Scenario_Standard.cs:
removed the now-unused NeedsGitBuildInfo property and setters.
* ConfigAndData/BuildAndroidPlatforms.cs: entire file deleted -
AndroidNdkVersion, AndroidNdkPkgRevision, NdkMinimumAPI, and
NdkMinimumAPILegacy32 were all sourced from Configuration.props
by way of Get_XABuildConfig_cs.
* Utilities.cs: deleted ParseAndroidPkgRevision (sole caller was
BuildInfo.NDKVersion).
* GitRunner.cs: deleted GetTopCommitHash and GetBranchName (sole
caller was BuildInfo.DetermineXACommitInfo). The GitRunner class
is retained - other consumers (Blame, SubmoduleUpdate, etc.) remain.
* README.md: dropped the BuildAndroidPlatforms.cs bullet.
Net diff: +6 / -195 (one new ~120-line csproj, ~175 lines of C# removed).
Verification:
* xaprepare.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: builds; consumes the
MSBuild-generated XABuildConfig.cs unchanged.
* Incremental rebuild of xabuildconfig.csproj reports
_GenerateXABuildConfig as up-to-date.
* fc /b vs baseline: no differences encountered.
Precedent PRs in this incremental xaprepare removal stream: #11568,
#11580, #11608, #11613, #11631, #11731, #11732, #11733, #11737, #11740,
#11760, #11803, #11821, #11825.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 21:10
…ass library
Follow-up to commit f6958e4 on this branch.
The previous commit moved XABuildConfig.cs generation out of xaprepare
into a NoTargets MSBuild project that produced
bin/Build$(Configuration)/XABuildConfig.cs and was <Compile Include>'d
into three csprojs (Xamarin.Android.Build.Tasks, Xamarin.ProjectTools,
Xamarin.Android.Build.Tests). That preserved byte-equivalence with
xaprepare's output but kept the long-standing problem that the same
type (Xamarin.Android.Tools.XABuildConfig) ended up compiled into
three different assemblies. Because Build.Tests references Build.Tasks
(which exposes its internals via InternalsVisibleTo), every use of
XABuildConfig in test sources produced CS0436 "type conflicts with
imported type" warnings — about 22 of them.
This commit collapses XABuildConfig to a single definition by making
it a real class library:
* New project src/AndroidBuildConfig/AndroidBuildConfig.csproj is a
regular Microsoft.NET.Sdk netstandard2.0 strong-named assembly. It
generates obj/$(Configuration)/$(TargetFramework)/XABuildConfig.cs
from XABuildConfig.cs.in (now living alongside the csproj) using
the same GitCommitHash / GitBranch / ReplaceFileContents tasks as
before, with the BeforeCompile + Compile-inside-target pattern so
the generated file lands under obj/ instead of the source tree.
* The XABuildConfig class is now public, so consumers reference the
assembly normally (the user explicitly OK'd making it public).
* The three consumer csprojs lose their <Compile Include> for
XABuildConfig.cs and reference AndroidBuildConfig with a normal
ProjectReference (no ReferenceOutputAssembly=False).
* build-tools/installers/create-installers.targets ships
AndroidBuildConfig.dll and .pdb alongside Xamarin.Android.Build.Tasks
so the SDK installer carries the new dll.
Verification:
* AndroidBuildConfig.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: 0 errors, 85 pre-existing
unrelated warnings (none referencing XABuildConfig).
* Xamarin.Android.Build.Tests.csproj: 0 errors, 7 warnings — down
from ~22, the ~15 XABuildConfig CS0436 warnings are eliminated.
* xaprepare.csproj: 0 warnings, 0 errors.
* Generated XABuildConfig.cs matches the previous output exactly
apart from "static class" -> "public static class" (the
intentional change) and the expected commit-hash / branch drift.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers changed the title [xaprepare] Move XABuildConfig.cs generation from xaprepare to MSBuild[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dllJun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

jonathanpeppersand others added 2 commits July 1, 2026 08:04
Without this the CI build fails on Windows/Linux because the project
reference from Xamarin.Android.Build.Tasks (built via the sln in Release)
somehow triggers AndroidBuildConfig with Configuration=Debug, so it looks
for bin\BuildDebug\net10.0\xa-prep-tasks.dll -- which doesn't exist yet.
Adding the project to the sln with proper Debug/Release configuration
mappings (mirroring cmake-config which has the same pattern) ensures the
solution build passes Configuration correctly.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Jul 1, 2026
@jonathanpeppers
jonathanpeppers merged commit 788d363 into mainJul 1, 2026
40 checks passed
@jonathanpeppers
jonathanpeppers deleted the jonathanpeppers-xabuildconfig-to-msbuild branch July 1, 2026 16:57
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
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>
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
…#11945)
Follow-up to #11826. After that PR moved XABuildConfig generation to AndroidBuildConfig.dll and removed instance members from BuildInfo, the entire cascade downstream of `BuildInfo.DetermineLastVersionChangeCommit` became unreachable.
Removed:
* `Application/BuildInfo.cs` (whole file — all members orphan)
* `ToolRunners/GitRunner.BlamePorcelainEntry.cs` (whole file)
* `GitRunner` `Blame(...)` overloads (3), `ParseBlameLine`, and now-unused `SetCommandArguments` helper
* `Context.BuildInfo` property + assignment in `Init()`
* `Utilities.ShortenGitHash` and its only consumer `Configurables.Defaults.AbbreviatedHashLength`
`BuildInfo.cs.in` was changed from `partial class` to `static class` since only `XAVersion` remains; `Main.cs` still uses `BuildInfo.XAVersion`.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival pushed a commit that referenced this pull request Jul 3, 2026
…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>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

ready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jonathanpeppers@simonrozsival
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll - #11826

Merged
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild
Jul 1, 2026
Merged

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll#11826
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild

Conversation

@jonathanpeppers

@jonathanpeppersjonathanpeppers commented Jun 30, 2026

Copy link
Copy Markdown
Member

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.
  • ProjectReferences 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.insrc/AndroidBuildConfig/XABuildConfig.cs.in (static classpublic 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 classpublic 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.

Mirrors the cmake-config.csproj precedent (#11760): a new
Microsoft.Build.NoTargets project at
build-tools/scripts/xabuildconfig/xabuildconfig.csproj generates
bin/Build$(Configuration)/XABuildConfig.cs from
build-tools/scripts/XABuildConfig.cs.in using the existing
ReplaceFileContents, GitCommitHash, and GitBranch prep tasks (all
hosted via TaskFactory=TaskHostFactory Runtime=NET, per the
internal-prep-task convention). All substitution values come from
Configuration.props properties already in scope - no new C# task code
required.
The three consumers that <Compile Include> XABuildConfig.cs now
<ProjectReference> the new csproj with ReferenceOutputAssembly=False,
ensuring single-execution and ordering for isolated builds:
* 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
The generated file is byte-identical to the prior xaprepare output
(verified via fc /b against a baseline captured before the change).
xaprepare cleanup (the only consumers of these methods/properties were
the deleted Get_XABuildConfig_cs and its helpers):
* Step_GenerateFiles.cs: deleted Get_XABuildConfig_cs and its
GetMajor/GetMinor helpers; the at-build-start list now contains
only Get_Configuration_OperatingSystem_props.
* BuildInfo.cs: deleted NDKRevision, NDKVersionMajor/Minor/Micro,
NDKVersion, cachedNdkVersion, XACommitHash, XABranch,
GatherGitInfo, and DetermineXACommitInfo.
* Context.cs: removed the
`if (SelectedScenario.NeedsGitBuildInfo)` GatherGitInfo block.
* Scenario.cs / Scenario_Required.cs / Scenario_Standard.cs:
removed the now-unused NeedsGitBuildInfo property and setters.
* ConfigAndData/BuildAndroidPlatforms.cs: entire file deleted -
AndroidNdkVersion, AndroidNdkPkgRevision, NdkMinimumAPI, and
NdkMinimumAPILegacy32 were all sourced from Configuration.props
by way of Get_XABuildConfig_cs.
* Utilities.cs: deleted ParseAndroidPkgRevision (sole caller was
BuildInfo.NDKVersion).
* GitRunner.cs: deleted GetTopCommitHash and GetBranchName (sole
caller was BuildInfo.DetermineXACommitInfo). The GitRunner class
is retained - other consumers (Blame, SubmoduleUpdate, etc.) remain.
* README.md: dropped the BuildAndroidPlatforms.cs bullet.
Net diff: +6 / -195 (one new ~120-line csproj, ~175 lines of C# removed).
Verification:
* xaprepare.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: builds; consumes the
MSBuild-generated XABuildConfig.cs unchanged.
* Incremental rebuild of xabuildconfig.csproj reports
_GenerateXABuildConfig as up-to-date.
* fc /b vs baseline: no differences encountered.
Precedent PRs in this incremental xaprepare removal stream: #11568,
#11580, #11608, #11613, #11631, #11731, #11732, #11733, #11737, #11740,
#11760, #11803, #11821, #11825.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 21:10
…ass library
Follow-up to commit f6958e4 on this branch.
The previous commit moved XABuildConfig.cs generation out of xaprepare
into a NoTargets MSBuild project that produced
bin/Build$(Configuration)/XABuildConfig.cs and was <Compile Include>'d
into three csprojs (Xamarin.Android.Build.Tasks, Xamarin.ProjectTools,
Xamarin.Android.Build.Tests). That preserved byte-equivalence with
xaprepare's output but kept the long-standing problem that the same
type (Xamarin.Android.Tools.XABuildConfig) ended up compiled into
three different assemblies. Because Build.Tests references Build.Tasks
(which exposes its internals via InternalsVisibleTo), every use of
XABuildConfig in test sources produced CS0436 "type conflicts with
imported type" warnings — about 22 of them.
This commit collapses XABuildConfig to a single definition by making
it a real class library:
* New project src/AndroidBuildConfig/AndroidBuildConfig.csproj is a
regular Microsoft.NET.Sdk netstandard2.0 strong-named assembly. It
generates obj/$(Configuration)/$(TargetFramework)/XABuildConfig.cs
from XABuildConfig.cs.in (now living alongside the csproj) using
the same GitCommitHash / GitBranch / ReplaceFileContents tasks as
before, with the BeforeCompile + Compile-inside-target pattern so
the generated file lands under obj/ instead of the source tree.
* The XABuildConfig class is now public, so consumers reference the
assembly normally (the user explicitly OK'd making it public).
* The three consumer csprojs lose their <Compile Include> for
XABuildConfig.cs and reference AndroidBuildConfig with a normal
ProjectReference (no ReferenceOutputAssembly=False).
* build-tools/installers/create-installers.targets ships
AndroidBuildConfig.dll and .pdb alongside Xamarin.Android.Build.Tasks
so the SDK installer carries the new dll.
Verification:
* AndroidBuildConfig.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: 0 errors, 85 pre-existing
unrelated warnings (none referencing XABuildConfig).
* Xamarin.Android.Build.Tests.csproj: 0 errors, 7 warnings — down
from ~22, the ~15 XABuildConfig CS0436 warnings are eliminated.
* xaprepare.csproj: 0 warnings, 0 errors.
* Generated XABuildConfig.cs matches the previous output exactly
apart from "static class" -> "public static class" (the
intentional change) and the expected commit-hash / branch drift.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers changed the title [xaprepare] Move XABuildConfig.cs generation from xaprepare to MSBuild[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dllJun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

jonathanpeppersand others added 2 commits July 1, 2026 08:04
Without this the CI build fails on Windows/Linux because the project
reference from Xamarin.Android.Build.Tasks (built via the sln in Release)
somehow triggers AndroidBuildConfig with Configuration=Debug, so it looks
for bin\BuildDebug\net10.0\xa-prep-tasks.dll -- which doesn't exist yet.
Adding the project to the sln with proper Debug/Release configuration
mappings (mirroring cmake-config which has the same pattern) ensures the
solution build passes Configuration correctly.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Jul 1, 2026
@jonathanpeppers
jonathanpeppers merged commit 788d363 into mainJul 1, 2026
40 checks passed
@jonathanpeppers
jonathanpeppers deleted the jonathanpeppers-xabuildconfig-to-msbuild branch July 1, 2026 16:57
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
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>
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
…#11945)
Follow-up to #11826. After that PR moved XABuildConfig generation to AndroidBuildConfig.dll and removed instance members from BuildInfo, the entire cascade downstream of `BuildInfo.DetermineLastVersionChangeCommit` became unreachable.
Removed:
* `Application/BuildInfo.cs` (whole file — all members orphan)
* `ToolRunners/GitRunner.BlamePorcelainEntry.cs` (whole file)
* `GitRunner` `Blame(...)` overloads (3), `ParseBlameLine`, and now-unused `SetCommandArguments` helper
* `Context.BuildInfo` property + assignment in `Init()`
* `Utilities.ShortenGitHash` and its only consumer `Configurables.Defaults.AbbreviatedHashLength`
`BuildInfo.cs.in` was changed from `partial class` to `static class` since only `XAVersion` remains; `Main.cs` still uses `BuildInfo.XAVersion`.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival pushed a commit that referenced this pull request Jul 3, 2026
…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>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

ready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jonathanpeppers@simonrozsival
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll - #11826

Merged
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild
Jul 1, 2026
Merged

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll#11826
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild

Conversation

@jonathanpeppers

@jonathanpeppersjonathanpeppers commented Jun 30, 2026

Copy link
Copy Markdown
Member

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.
  • ProjectReferences 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.insrc/AndroidBuildConfig/XABuildConfig.cs.in (static classpublic 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 classpublic 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.

Mirrors the cmake-config.csproj precedent (#11760): a new
Microsoft.Build.NoTargets project at
build-tools/scripts/xabuildconfig/xabuildconfig.csproj generates
bin/Build$(Configuration)/XABuildConfig.cs from
build-tools/scripts/XABuildConfig.cs.in using the existing
ReplaceFileContents, GitCommitHash, and GitBranch prep tasks (all
hosted via TaskFactory=TaskHostFactory Runtime=NET, per the
internal-prep-task convention). All substitution values come from
Configuration.props properties already in scope - no new C# task code
required.
The three consumers that <Compile Include> XABuildConfig.cs now
<ProjectReference> the new csproj with ReferenceOutputAssembly=False,
ensuring single-execution and ordering for isolated builds:
* 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
The generated file is byte-identical to the prior xaprepare output
(verified via fc /b against a baseline captured before the change).
xaprepare cleanup (the only consumers of these methods/properties were
the deleted Get_XABuildConfig_cs and its helpers):
* Step_GenerateFiles.cs: deleted Get_XABuildConfig_cs and its
GetMajor/GetMinor helpers; the at-build-start list now contains
only Get_Configuration_OperatingSystem_props.
* BuildInfo.cs: deleted NDKRevision, NDKVersionMajor/Minor/Micro,
NDKVersion, cachedNdkVersion, XACommitHash, XABranch,
GatherGitInfo, and DetermineXACommitInfo.
* Context.cs: removed the
`if (SelectedScenario.NeedsGitBuildInfo)` GatherGitInfo block.
* Scenario.cs / Scenario_Required.cs / Scenario_Standard.cs:
removed the now-unused NeedsGitBuildInfo property and setters.
* ConfigAndData/BuildAndroidPlatforms.cs: entire file deleted -
AndroidNdkVersion, AndroidNdkPkgRevision, NdkMinimumAPI, and
NdkMinimumAPILegacy32 were all sourced from Configuration.props
by way of Get_XABuildConfig_cs.
* Utilities.cs: deleted ParseAndroidPkgRevision (sole caller was
BuildInfo.NDKVersion).
* GitRunner.cs: deleted GetTopCommitHash and GetBranchName (sole
caller was BuildInfo.DetermineXACommitInfo). The GitRunner class
is retained - other consumers (Blame, SubmoduleUpdate, etc.) remain.
* README.md: dropped the BuildAndroidPlatforms.cs bullet.
Net diff: +6 / -195 (one new ~120-line csproj, ~175 lines of C# removed).
Verification:
* xaprepare.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: builds; consumes the
MSBuild-generated XABuildConfig.cs unchanged.
* Incremental rebuild of xabuildconfig.csproj reports
_GenerateXABuildConfig as up-to-date.
* fc /b vs baseline: no differences encountered.
Precedent PRs in this incremental xaprepare removal stream: #11568,
#11580, #11608, #11613, #11631, #11731, #11732, #11733, #11737, #11740,
#11760, #11803, #11821, #11825.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 21:10
…ass library
Follow-up to commit f6958e4 on this branch.
The previous commit moved XABuildConfig.cs generation out of xaprepare
into a NoTargets MSBuild project that produced
bin/Build$(Configuration)/XABuildConfig.cs and was <Compile Include>'d
into three csprojs (Xamarin.Android.Build.Tasks, Xamarin.ProjectTools,
Xamarin.Android.Build.Tests). That preserved byte-equivalence with
xaprepare's output but kept the long-standing problem that the same
type (Xamarin.Android.Tools.XABuildConfig) ended up compiled into
three different assemblies. Because Build.Tests references Build.Tasks
(which exposes its internals via InternalsVisibleTo), every use of
XABuildConfig in test sources produced CS0436 "type conflicts with
imported type" warnings — about 22 of them.
This commit collapses XABuildConfig to a single definition by making
it a real class library:
* New project src/AndroidBuildConfig/AndroidBuildConfig.csproj is a
regular Microsoft.NET.Sdk netstandard2.0 strong-named assembly. It
generates obj/$(Configuration)/$(TargetFramework)/XABuildConfig.cs
from XABuildConfig.cs.in (now living alongside the csproj) using
the same GitCommitHash / GitBranch / ReplaceFileContents tasks as
before, with the BeforeCompile + Compile-inside-target pattern so
the generated file lands under obj/ instead of the source tree.
* The XABuildConfig class is now public, so consumers reference the
assembly normally (the user explicitly OK'd making it public).
* The three consumer csprojs lose their <Compile Include> for
XABuildConfig.cs and reference AndroidBuildConfig with a normal
ProjectReference (no ReferenceOutputAssembly=False).
* build-tools/installers/create-installers.targets ships
AndroidBuildConfig.dll and .pdb alongside Xamarin.Android.Build.Tasks
so the SDK installer carries the new dll.
Verification:
* AndroidBuildConfig.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: 0 errors, 85 pre-existing
unrelated warnings (none referencing XABuildConfig).
* Xamarin.Android.Build.Tests.csproj: 0 errors, 7 warnings — down
from ~22, the ~15 XABuildConfig CS0436 warnings are eliminated.
* xaprepare.csproj: 0 warnings, 0 errors.
* Generated XABuildConfig.cs matches the previous output exactly
apart from "static class" -> "public static class" (the
intentional change) and the expected commit-hash / branch drift.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers changed the title [xaprepare] Move XABuildConfig.cs generation from xaprepare to MSBuild[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dllJun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

jonathanpeppersand others added 2 commits July 1, 2026 08:04
Without this the CI build fails on Windows/Linux because the project
reference from Xamarin.Android.Build.Tasks (built via the sln in Release)
somehow triggers AndroidBuildConfig with Configuration=Debug, so it looks
for bin\BuildDebug\net10.0\xa-prep-tasks.dll -- which doesn't exist yet.
Adding the project to the sln with proper Debug/Release configuration
mappings (mirroring cmake-config which has the same pattern) ensures the
solution build passes Configuration correctly.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Jul 1, 2026
@jonathanpeppers
jonathanpeppers merged commit 788d363 into mainJul 1, 2026
40 checks passed
@jonathanpeppers
jonathanpeppers deleted the jonathanpeppers-xabuildconfig-to-msbuild branch July 1, 2026 16:57
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
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>
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
…#11945)
Follow-up to #11826. After that PR moved XABuildConfig generation to AndroidBuildConfig.dll and removed instance members from BuildInfo, the entire cascade downstream of `BuildInfo.DetermineLastVersionChangeCommit` became unreachable.
Removed:
* `Application/BuildInfo.cs` (whole file — all members orphan)
* `ToolRunners/GitRunner.BlamePorcelainEntry.cs` (whole file)
* `GitRunner` `Blame(...)` overloads (3), `ParseBlameLine`, and now-unused `SetCommandArguments` helper
* `Context.BuildInfo` property + assignment in `Init()`
* `Utilities.ShortenGitHash` and its only consumer `Configurables.Defaults.AbbreviatedHashLength`
`BuildInfo.cs.in` was changed from `partial class` to `static class` since only `XAVersion` remains; `Main.cs` still uses `BuildInfo.XAVersion`.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival pushed a commit that referenced this pull request Jul 3, 2026
…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>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

ready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jonathanpeppers@simonrozsival
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll - #11826

Merged
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild
Jul 1, 2026
Merged

[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dll#11826
jonathanpeppers merged 4 commits into
mainfrom
jonathanpeppers-xabuildconfig-to-msbuild

Conversation

@jonathanpeppers

@jonathanpeppersjonathanpeppers commented Jun 30, 2026

Copy link
Copy Markdown
Member

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.
  • ProjectReferences 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.insrc/AndroidBuildConfig/XABuildConfig.cs.in (static classpublic 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 classpublic 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.

Mirrors the cmake-config.csproj precedent (#11760): a new
Microsoft.Build.NoTargets project at
build-tools/scripts/xabuildconfig/xabuildconfig.csproj generates
bin/Build$(Configuration)/XABuildConfig.cs from
build-tools/scripts/XABuildConfig.cs.in using the existing
ReplaceFileContents, GitCommitHash, and GitBranch prep tasks (all
hosted via TaskFactory=TaskHostFactory Runtime=NET, per the
internal-prep-task convention). All substitution values come from
Configuration.props properties already in scope - no new C# task code
required.
The three consumers that <Compile Include> XABuildConfig.cs now
<ProjectReference> the new csproj with ReferenceOutputAssembly=False,
ensuring single-execution and ordering for isolated builds:
* 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
The generated file is byte-identical to the prior xaprepare output
(verified via fc /b against a baseline captured before the change).
xaprepare cleanup (the only consumers of these methods/properties were
the deleted Get_XABuildConfig_cs and its helpers):
* Step_GenerateFiles.cs: deleted Get_XABuildConfig_cs and its
GetMajor/GetMinor helpers; the at-build-start list now contains
only Get_Configuration_OperatingSystem_props.
* BuildInfo.cs: deleted NDKRevision, NDKVersionMajor/Minor/Micro,
NDKVersion, cachedNdkVersion, XACommitHash, XABranch,
GatherGitInfo, and DetermineXACommitInfo.
* Context.cs: removed the
`if (SelectedScenario.NeedsGitBuildInfo)` GatherGitInfo block.
* Scenario.cs / Scenario_Required.cs / Scenario_Standard.cs:
removed the now-unused NeedsGitBuildInfo property and setters.
* ConfigAndData/BuildAndroidPlatforms.cs: entire file deleted -
AndroidNdkVersion, AndroidNdkPkgRevision, NdkMinimumAPI, and
NdkMinimumAPILegacy32 were all sourced from Configuration.props
by way of Get_XABuildConfig_cs.
* Utilities.cs: deleted ParseAndroidPkgRevision (sole caller was
BuildInfo.NDKVersion).
* GitRunner.cs: deleted GetTopCommitHash and GetBranchName (sole
caller was BuildInfo.DetermineXACommitInfo). The GitRunner class
is retained - other consumers (Blame, SubmoduleUpdate, etc.) remain.
* README.md: dropped the BuildAndroidPlatforms.cs bullet.
Net diff: +6 / -195 (one new ~120-line csproj, ~175 lines of C# removed).
Verification:
* xaprepare.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: builds; consumes the
MSBuild-generated XABuildConfig.cs unchanged.
* Incremental rebuild of xabuildconfig.csproj reports
_GenerateXABuildConfig as up-to-date.
* fc /b vs baseline: no differences encountered.
Precedent PRs in this incremental xaprepare removal stream: #11568,
#11580, #11608, #11613, #11631, #11731, #11732, #11733, #11737, #11740,
#11760, #11803, #11821, #11825.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 21:10
…ass library
Follow-up to commit f6958e4 on this branch.
The previous commit moved XABuildConfig.cs generation out of xaprepare
into a NoTargets MSBuild project that produced
bin/Build$(Configuration)/XABuildConfig.cs and was <Compile Include>'d
into three csprojs (Xamarin.Android.Build.Tasks, Xamarin.ProjectTools,
Xamarin.Android.Build.Tests). That preserved byte-equivalence with
xaprepare's output but kept the long-standing problem that the same
type (Xamarin.Android.Tools.XABuildConfig) ended up compiled into
three different assemblies. Because Build.Tests references Build.Tasks
(which exposes its internals via InternalsVisibleTo), every use of
XABuildConfig in test sources produced CS0436 "type conflicts with
imported type" warnings — about 22 of them.
This commit collapses XABuildConfig to a single definition by making
it a real class library:
* New project src/AndroidBuildConfig/AndroidBuildConfig.csproj is a
regular Microsoft.NET.Sdk netstandard2.0 strong-named assembly. It
generates obj/$(Configuration)/$(TargetFramework)/XABuildConfig.cs
from XABuildConfig.cs.in (now living alongside the csproj) using
the same GitCommitHash / GitBranch / ReplaceFileContents tasks as
before, with the BeforeCompile + Compile-inside-target pattern so
the generated file lands under obj/ instead of the source tree.
* The XABuildConfig class is now public, so consumers reference the
assembly normally (the user explicitly OK'd making it public).
* The three consumer csprojs lose their <Compile Include> for
XABuildConfig.cs and reference AndroidBuildConfig with a normal
ProjectReference (no ReferenceOutputAssembly=False).
* build-tools/installers/create-installers.targets ships
AndroidBuildConfig.dll and .pdb alongside Xamarin.Android.Build.Tasks
so the SDK installer carries the new dll.
Verification:
* AndroidBuildConfig.csproj: 0 warnings, 0 errors.
* Xamarin.Android.Build.Tasks.csproj: 0 errors, 85 pre-existing
unrelated warnings (none referencing XABuildConfig).
* Xamarin.Android.Build.Tests.csproj: 0 errors, 7 warnings — down
from ~22, the ~15 XABuildConfig CS0436 warnings are eliminated.
* xaprepare.csproj: 0 warnings, 0 errors.
* Generated XABuildConfig.cs matches the previous output exactly
apart from "static class" -> "public static class" (the
intentional change) and the expected commit-hash / branch drift.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers changed the title [xaprepare] Move XABuildConfig.cs generation from xaprepare to MSBuild[xaprepare] Move XABuildConfig generation to AndroidBuildConfig.dllJun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

jonathanpeppersand others added 2 commits July 1, 2026 08:04
Without this the CI build fails on Windows/Linux because the project
reference from Xamarin.Android.Build.Tasks (built via the sln in Release)
somehow triggers AndroidBuildConfig with Configuration=Debug, so it looks
for bin\BuildDebug\net10.0\xa-prep-tasks.dll -- which doesn't exist yet.
Adding the project to the sln with proper Debug/Release configuration
mappings (mirroring cmake-config which has the same pattern) ensures the
solution build passes Configuration correctly.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jonathanpeppersjonathanpeppers added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Jul 1, 2026
@jonathanpeppers
jonathanpeppers merged commit 788d363 into mainJul 1, 2026
40 checks passed
@jonathanpeppers
jonathanpeppers deleted the jonathanpeppers-xabuildconfig-to-msbuild branch July 1, 2026 16:57
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
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>
jonathanpeppers added a commit that referenced this pull request Jul 1, 2026
…#11945)
Follow-up to #11826. After that PR moved XABuildConfig generation to AndroidBuildConfig.dll and removed instance members from BuildInfo, the entire cascade downstream of `BuildInfo.DetermineLastVersionChangeCommit` became unreachable.
Removed:
* `Application/BuildInfo.cs` (whole file — all members orphan)
* `ToolRunners/GitRunner.BlamePorcelainEntry.cs` (whole file)
* `GitRunner` `Blame(...)` overloads (3), `ParseBlameLine`, and now-unused `SetCommandArguments` helper
* `Context.BuildInfo` property + assignment in `Init()`
* `Utilities.ShortenGitHash` and its only consumer `Configurables.Defaults.AbbreviatedHashLength`
`BuildInfo.cs.in` was changed from `partial class` to `static class` since only `XAVersion` remains; `Main.cs` still uses `BuildInfo.XAVersion`.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival pushed a commit that referenced this pull request Jul 3, 2026
…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>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

ready-to-reviewThis PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jonathanpeppers@simonrozsival