Uh oh!
There was an error while loading. Please reload this page.
[build] android-platform-support repo consolidation - #11529
Conversation
jonathanpeppers
commented
May 28, 2026
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
c7fe2d6 to
48ce158Comparejonathanpeppers
commented
May 28, 2026
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
653f3e9 to
2d58ed9Comparejonathanpeppers
commented
May 28, 2026
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
b03e93b to
3e04b58Comparejonathanpeppers
commented
May 28, 2026
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Inlines the contents of the `DevDiv/android-platform-support` repo into
dotnet/android, removes the `BuildExternal` MSBuild target that used to
clone it, and prunes dead code carried over with the migration. The
shipped SDK pack DLLs are unchanged.
What moved in from `external/android-platform-support`:
* `src/Xamarin.AndroidTools/` - SDK probing helpers (`AndroidSdk`,
`MonoDroidSdk`, `ProcessUtils`, etc.) used by the debugging tasks
and the installer.
* `src/Mono.AndroidTools/` - `AndroidDevice` / `adb` client used by
fast deployment and the debugging task assembly.
* `src/Xamarin.Android.Build.Debugging.Tasks/` - the
`Xamarin.Android.Common.Debugging.targets` MSBuild tasks (FastDeploy,
RunActivity, RunTests, GetGdbSymbols, ...).
* `src/Xamarin.Installer.AndroidSDK/`,
`src/Xamarin.Installer.Build.Tasks/`,
`src/Xamarin.Installer.Common/` - Android SDK installer used by the
standalone Xamarin Installer / VS Mac Android workload acquisition.
* `tools/fastdev/` - native `xamarin.{sync,cp,find,stat}` helper
binaries plus the `fastdevtools` packaging project consumed during
fast deployment.
* `external/termux-elf-cleaner` - submodule consumed only as a
build-time tool by the fastdev native binaries.
* `build-tools/android-platform-support/` - version/commit metadata
for the above projects, kept under this path to preserve legacy
file names.
Build wiring:
* `Xamarin.Android.sln` now references the inlined projects directly.
* `Directory.Build.props`, `build-tools/scripts/DotNet.targets`, and
`build-tools/installers/create-installers.targets` lose their
`BuildExternal` clone/build of `external/android-platform-support`
and pick the assemblies up from the in-tree build instead.
* `installer-files.projitems` is inlined into the installer targets
rather than imported across the submodule boundary.
* `tools/workload-dependencies/WorkloadDependencies.proj` reads its
feed XML from a copy under `src/Xamarin.Installer.Build.Tasks/`.
Cleanup carried out as part of the migration: removed code, resources,
and tooling files that only existed to serve the standalone
`android-platform-support` build system and have no consumers in
dotnet/android.
THIRD-PARTY-NOTICES.TXT: added the Apache 2.0 notice for
`Kajabity/Kajabity.Tools.Java`, which is vendored under
`src/Xamarin.Installer.AndroidSDK/` and consumed by the
`JavaDependencyInstaller`.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>3e04b58 to
51f61b1Comparejonathanpeppers
commented
May 28, 2026
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
The only entry in `.external` was `DevDiv/android-platform-support`, which is now inlined into the tree, so the whole "prepare external git dependencies" pipeline is dead. Removes: * The `.external` file consumer (`ExternalGitDependency`, `Step_PrepareExternalGitDependencies`, `Scenario_PrepareExternalGitDependencies`, `CommercialExternalDependencies`, `ExternalGitDepsFilePath` / `ExternalGitDepsDestDir`). * `make prepare-external-git-dependencies` and its callers in `build.sh`, `build.cmd`, and the Linux/macOS CI yaml templates. * The `PrepareExternal` MSBuild target in `PrepareWindows.targets` and its `vscode-support.md` documentation entries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers
commented
May 28, 2026
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
627d28c to
3d5286fComparejonathanpeppers
commented
May 28, 2026
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
PoliCheck uses signature-based suppressions in .gdnsuppress files (not PoliCheck.Exclusions.xml). Add the three signatures surfaced by the PoliCheck build stage: * source.gdnsuppress: 'country' parameter in KeyManagement.cs (X.509 distinguished-name field, required by the spec). * CHT.gdnsuppress: false-positive 'PK' from the Cantonese term table inside a machine-translated zh-Hant resource string. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
58bd369 to
f667453Comparejonathanpeppers
commented
Jun 2, 2026
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
…abity Add signature suppressions for the 17 PoliCheck Notes in the inlined installer content: * 16 hits in src/Xamarin.Installer.AndroidSDK/Feeds/AndroidManifestFeed_d18.0.xml for 'country' / 'countries' (rules 79569/79570). These are verbatim text from Google's Android SDK, Google TV Add-on, and GDK license agreements and must not be modified. * 1 hit in src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/ Kajabity.Tools.Java/JavaPropertyReader.cs (rule 92197 'Hong Kong') in a third-party doc comment showing sample data with embedded spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers
commented
Jun 2, 2026
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
jonathanpeppers
commented
Jun 3, 2026
/review |
✅ Android PR Reviewer completed successfully! |
There was a problem hiding this comment.
✅ LGTM — Minor issues only
PR: android-platform-support repo consolidation
Well-structured consolidation that inlines DevDiv/android-platform-support into dotnet/android, removes the BuildExternal clone/build flow, and replaces it with a new Step_Android_SDK_NDK xaprepare step. The build artifact comparison in the PR description is thorough and reassuring — the shipped SDK pack DLLs are functionally unchanged and the only delta is the intentional removal of unused AOSP installer ELF binaries.
Summary
| Severity | Count |
|---|---|
| ❌ Error | 1 |
| 💡 Suggestion | 3 |
Positive callouts:
- Excellent artifact comparison analysis documenting exactly what changed and what was removed
- Clean removal of
PrepareExternalGitDependenciesflow — all references in Makefile, build scripts, YAML pipelines, xaprepare scenarios, and docs are consistently removed - The new
AndroidToolchain/Step_Android_SDK_NDKcode is well-organized with clear separation of per-platform OS tags - Good addition of the Kajabity Apache 2.0 notice to THIRD-PARTY-NOTICES.TXT
CI Status
- ✅
dotnet-android— passed - 🟡
Xamarin.Android-PR— [in progress]((devdiv.visualstudio.com/redacted)
Generated by Android PR Reviewer for issue #11529 · ● 70.6M
…e-android-platform-support
jonathanpeppers
commented
Jun 3, 2026
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Without a ProjectReference to androidsdk.csproj, fastdevtools.csproj can race against the SDK extraction and find a partially-extracted cmake (binary present at /sdk/cmake/3.30.3/bin/cmake but share/ not yet populated), resulting in: CMake error: File .../share/cmake-3.30/Modules/CMakeCXXCompiler.cmake.in does not exist. Other native-build projects (proguard-android, bundletool, r8, java-runtime, manifestmerger) already use this pattern. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers
commented
Jun 3, 2026
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Uh oh!
There was an error while loading. Please reload this page.
## Why `bin/configuration.mk` exists only to persist `CONFIGURATION=<value>` between Unix `make` invocations. Removing it lets us delete the only meaningful contents of `Step_GenerateFiles.Unix.cs`, continuing the slow removal of `xaprepare` (see precedent: #11568, #11529). ## What - Drop `-include bin/configuration.mk` from the top of `Makefile`. The `CONFIGURATION ?= Debug` fallback at the top of the file is unchanged. - Delete `build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.Unix.cs` entirely (it contained `GeneratedConfigurationFile` and a one-line `AddUnixPostBuildSteps` partial that registered it). The `partial void AddUnixPostBuildSteps (Context context, List<GeneratedFile> steps);` declaration in `Step_GenerateFiles.cs` is intentionally left in place — partial methods without an implementation are legal in C#, and the call site becomes a zero-cost no-op. `Step_GenerateFiles.Windows.cs` implements a *different* partial (`AddOSSpecificSteps`) and is unaffected. ## Why this is safe | Caller | Pre-change behavior | Post-change behavior | | --- | --- | --- | | All CI YAML (`build-linux-steps.yaml`, `build-macos-steps.yaml`, `commercial-build.yaml`, `azure-pipelines-apidocs.yaml`) | Passes `CONFIGURATION=$(XA.Build.Configuration)` on every `make` call | Same — explicit value still wins | | `build.sh` (`make prepare && make jenkins && make pack-dotnet`) | First `make prepare` runs against an empty `bin/`, so the `-include` no-ops and `?= Debug` takes effect | Identical — `?= Debug` still takes effect | | Fresh local checkout, bare `make all` | `?= Debug` (no `bin/configuration.mk` yet) | Same | | Local dev who runs `make prepare CONFIGURATION=Release` then bare `make all` | Persisted Release via `bin/configuration.mk` | Now defaults back to Debug — must pass `CONFIGURATION=Release` on every invocation | That last case is the only behavior change. It was never documented as a contract anywhere in `Documentation/` or `README.md`, and developers building Release locally should be passing the flag explicitly anyway. ## Verification - `git grep "configuration\.mk"` and `git grep "GeneratedConfigurationFile"`: zero matches after this change. - `dotnet build build-tools/xaprepare/xaprepare/xaprepare.csproj`: 0 warnings, 0 errors. - Rubber-duck review: no remaining `Path.Combine(..., "configuration.mk")` references, no Makefile target depends on `bin/configuration.mk` as a prerequisite, and the leftover partial-method declaration is benign.
…vailable (#11577) ### Context PR #11529 inlined `external/android-platform-support` into dotnet/android. `Xamarin.Android.Common.Debugging.targets` is now always built and shipped, so `TestEnvironment.CommercialBuildAvailable` is always `true` and `AssertCommercialBuild()` is a no-op. ### Changes - Removed `TestEnvironment.CommercialBuildAvailable` property. - Removed `BaseTest.AssertCommercialBuild()` helper. - Dropped every `AssertCommercialBuild ();` callsite (~40 lines across 19 files). - Simplified all `CommercialBuildAvailable` predicate usages, since the value is always `true`: - `if (TestEnvironment.CommercialBuildAvailable) { X }` → unwrapped to `X` - `if (!TestEnvironment.CommercialBuildAvailable) { X }` → block deleted - `if (isRelease || !TestEnvironment.CommercialBuildAvailable)` → `if (isRelease)` - `TestEnvironment.CommercialBuildAvailable ? "debug" : "release"` → `"debug"` - `!(TestEnvironment.CommercialBuildAvailable && !isRelease)` → `isRelease` - `!TestEnvironment.CommercialBuildAvailable && !isRelease` → `false` - In `InstallAndRunTests.cs`, the `if (TestEnvironment.CommercialBuildAvailable) { ... } else { ... }` block keeps only the (now always-taken) true branch. ### Out of scope The MSBuild gates (`_HasCommercialFiles`, `_AndroidFastDeploymentSupported`, etc.) are intentionally left alone — those will follow in a separate PR. ### Verification - `git grep -n AssertCommercialBuild` → 0 hits - `git grep -n CommercialBuildAvailable` → 0 hits - Brace-balance check on every modified `.cs` file matches the baseline (HEAD) delta exactly.
…Supported gates (#11576) Follow-up to #11529, which inlined the `external/android-platform-support` repo into dotnet/android. The Debugging.targets/props files and supporting assemblies (`Mono.AndroidTools`, `Xamarin.AndroidTools`, `Xamarin.Installer.*`, `Xamarin.Android.Build.Debugging.Tasks`, `fastdevtools`) are now always built in-tree by `Xamarin.Android.sln`, so several `Exists(...)` MSBuild gates are always true. This PR removes those dead gates and their dead branches: - **`build-tools/installers/create-installers.targets`** – drop `_HasCommercialFiles` and make the commercial `_MSBuildFiles` `ItemGroup` unconditional. - **`Microsoft.Android.Sdk.DefaultProperties.targets`** – drop `_AndroidFastDeploymentSupported`. - **`Microsoft.Android.Sdk.BuildOrder.targets`** – drop the `'$(_AndroidFastDeploymentSupported)' == 'true'` condition on `DeployToDeviceDependsOnTargets`; delete the dead `!= 'true'` branch. - **`Microsoft.Android.Sdk.Application.targets`** – same treatment for `_RunDependsOn`; remove the now-stale comment. - **`Xamarin.Android.Common.targets`** – drop `Exists(...)` from the `Xamarin.Android.Common.Debugging.targets` and `Xamarin.Installer.Common.targets` imports (keep the `'$(DesignTimeBuild)' != 'true'` guards); simplify the two dead `_AndroidFastDeploymentSupported` conditions on `EmbedAssembliesIntoApk`. - **`Microsoft.Android.Sdk.targets`** – drop `Exists(...)` from the `Xamarin.Android.Common.Debugging.props` import (keep DTB guard). - **Tests** – drop the now-defensive `proj.SetProperty ("_AndroidFastDeploymentSupported", "true")` calls (and the stale `//NOTE` comment) from `BuildTest.cs` and `InvalidConfigTests.cs`. `TestEnvironment.CommercialBuildAvailable` / `BaseTest.AssertCommercialBuild()` are intentionally left for a follow-up PR. After this change `git grep _HasCommercialFiles` and `git grep _AndroidFastDeploymentSupported` both return zero hits.
…11592) PR #11529 inlined `Mono.AndroidTools` from android-platform-support, which carried PackageReferences to `protobuf-net` 3.2.26 and `protobuf-net.Core` 3.2.26. The original consumer of these packages was the native `tools/base/deploy/installer` binary, which was removed in the same PR. None of the inlined managed code (`Mono.AndroidTools`, `Xamarin.AndroidTools`, `Xamarin.Installer.*`, `Xamarin.Android.Build.Debugging.Tasks`) actually uses the `ProtoBuf` namespace, `[ProtoContract]` / `[ProtoMember]` attributes, or `Serializer.*` calls — so the references are dead weight. More importantly, they were actively breaking `class-parse`'s Kotlin metadata parsing. `Mono.AndroidTools.csproj` outputs to `MicrosoftAndroidSdkOutDir`, where it dropped a v3 `protobuf-net.dll` (a thin facade) that overwrote the v2 self-contained DLL shipped by Java.Interop's `Xamarin.Android.Tools.Bytecode`. Because `protobuf-net.Core.dll` is not packed into the SDK pack, `class-parse` failed at runtime with `FileNotFoundException: Could not load file or assembly 'protobuf-net.Core, Version=3.0.0.0...'`, and `KotlinFixups.Fixup` silently skipped Kotlin metadata. Bindings then regenerated unsigned types as their signed counterparts, breaking `KotlinUnsignedTypesTests.cs` with CS1503/CS0266 errors. Drop the v3 references from `Mono.AndroidTools.csproj` and the now-unused `ProtobufNetVersion` / `ProtobufNetCoreVersion` properties from `Directory.Build.props`. The v2 `protobuf-net.dll` from Java.Interop's class-parse becomes the only one in `MicrosoftAndroidSdkOutDir`, restoring Kotlin metadata parsing. The existing `_MSBuildFiles Include=...protobuf-net.dll` and `SignList.xml` `ThirdParty` entry (added in #5529) continue to ship the v2 DLL into the SDK pack. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…#11613) Continues the slow `xaprepare` removal. Recent precedent: #11568 (CopyExtraResultFilesForCI → YAML), #11580 (configuration.mk removal), #11529 (android-platform-support consolidation, which also dropped `Step_PrepareExternalGitDependencies`). ## What `Step_PrepareProps` generated `external/Java.Interop/Configuration.Override.props` (inside the submodule) by substituting two placeholders into `build-tools/scripts/Configuration.Java.Interop.Override.in.props`. The substituted properties (`_XamarinAndroidCecilVersion`, `UtilityOutputFullPathCoreApps`, `XamarinAndroidToolsDirectory`) are now supplied directly via the checked-in static file `external/Java.Interop.override.props`, which Java.Interop's own `Directory.Build.props` already auto-imports via the parent-dir convention added in dotnet/java-interop#872. The shared version values (`MonoCecilVersion`, `AndroidPackVersion`, `AndroidPackVersionSuffix`) move into `eng/Versions.props`. `Directory.Build.props` and `external/Java.Interop.override.props` both `<Import>` it. No duplicate-import sentinel is needed because every code path that imports `Configuration.props` has already loaded `Directory.Build.props` (either via MSBuild auto-load or via the explicit `<Import>` in `external/xamarin-android-tools.override.props`). `MicrosoftAndroidSdkPackName` stays in `Configuration.props` (it is OS-conditioned, not version-shaped, so it doesn't belong in `Versions.props`). The same 3-line OS-conditioned block is mirrored privately in `external/Java.Interop.override.props` as `_MicrosoftAndroidSdkPackName`, used only to compute `UtilityOutputFullPathCoreApps` for the Java.Interop build. Also dropped: - `Configurables.Paths.InstallMSBuildDir` and its backing field — the only consumer was `Step_PrepareProps`. - The dead `UtilityOutputFullPath` line in the old template — Java.Interop's `TargetFrameworkDependentValues.props` unconditionally routes it to `$(UtilityOutputFullPathCoreApps)` anyway, so it was a no-op. Updated `build-tools/scripts/XAVersionInfo.targets` (the `GitBlame` for `<AndroidPackVersion>` now points at `eng/Versions.props`) and `Documentation/guides/HowToBranch.md` to reflect the moves. ## Why not just `<Import>` `Directory.Build.props` from the Java.Interop override? That was the original idea. I prototyped it: importing dotnet/android's full props chain from `external/Java.Interop.override.props` flips `DotNetTargetFrameworkVersion` from `10.0` to `11.0` inside Java.Interop, and `dotnet restore Java.Interop.csproj` then fails with: ``` NETSDK1045: The current .NET SDK does not support targeting .NET 11.0 ``` `xamarin-android-tools.override.props` gets away with the same trick only because its sole csproj sets `AndroidToolsDisableMultiTargeting=true`, which makes the TFM-clobber harmless. Java.Interop has no equivalent escape hatch. `eng/Versions.props` is collision-free with Java.Interop (verified against the submodule sources — none of the existing entries collide), has no `<Import>` of its own, and is the safe minimal shared file. ## Verification On Windows: - `dotnet build build-tools/xaprepare/xaprepare/xaprepare.csproj` — 0 warnings, 0 errors. - From `src/Xamarin.Android.Build.Tasks/`: `dotnet msbuild --getProperty:MonoCecilVersion,AndroidPackVersion,AndroidPackVersionSuffix,MicrosoftAndroidSdkPackName,MicrosoftAndroidSdkOutDir` — values unchanged from baseline. - From `external/Java.Interop/src/Java.Interop/`: - `dotnet msbuild --getProperty:DotNetTargetFramework,_XamarinAndroidCecilVersion,UtilityOutputFullPathCoreApps` returns `net10.0`, `0.11.5`, the expected packs/tools path. - `dotnet restore Java.Interop.csproj` succeeds (no `NETSDK1045`). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Inlines the contents of the
DevDiv/android-platform-supportrepo intodotnet/android, removes the
BuildExternalMSBuild target that used toclone it, and prunes dead code carried over with the migration. The
shipped SDK pack DLLs are unchanged.
What moved in from
external/android-platform-support:src/Xamarin.AndroidTools/- SDK probing helpers (AndroidSdk,MonoDroidSdk,ProcessUtils, etc.) used by the debugging tasksand the installer.
src/Mono.AndroidTools/-AndroidDevice/adbclient used byfast deployment and the debugging task assembly.
src/Xamarin.Android.Build.Debugging.Tasks/- theXamarin.Android.Common.Debugging.targetsMSBuild tasks (FastDeploy,RunActivity, RunTests, GetGdbSymbols, ...).
src/Xamarin.Installer.AndroidSDK/,src/Xamarin.Installer.Build.Tasks/,src/Xamarin.Installer.Common/- Android SDK installer used by thestandalone Xamarin Installer / VS Mac Android workload acquisition.
tools/fastdev/- nativexamarin.{sync,cp,find,stat}helperbinaries plus the
fastdevtoolspackaging project consumed duringfast deployment.
external/termux-elf-cleaner- submodule consumed only as abuild-time tool by the fastdev native binaries.
build-tools/android-platform-support/- version/commit metadatafor the above projects, kept under this path to preserve legacy
file names.
Build wiring:
Xamarin.Android.slnnow references the inlined projects directly.Directory.Build.props,build-tools/scripts/DotNet.targets, andbuild-tools/installers/create-installers.targetslose theirBuildExternalclone/build ofexternal/android-platform-supportand pick the assemblies up from the in-tree build instead.
installer-files.projitemsis inlined into the installer targetsrather than imported across the submodule boundary.
tools/workload-dependencies/WorkloadDependencies.projreads itsfeed XML from a copy under
src/Xamarin.Installer.Build.Tasks/.Cleanup carried out as part of the migration: removed code, resources,
and tooling files that only existed to serve the standalone
android-platform-supportbuild system and have no consumers indotnet/android.
THIRD-PARTY-NOTICES.TXT: added the Apache 2.0 notice for
Kajabity/Kajabity.Tools.Java, which is vendored undersrc/Xamarin.Installer.AndroidSDK/and consumed by theJavaDependencyInstaller.Build artifact comparison vs main
Compared
nuget-unsignedartifacts from this PR against a recent successfulPR build of
main(build 14260748).Same:
Templates, Manifest, etc.)
Microsoft.Android.Sdk.Darwin)files)
Missing (intentional, safe):
tools/lib/{arm64-v8a,armeabi-v7a,x86,x86_64}/installer— 4 ELFbinaries totaling ~15.6 MB uncompressed (~6 MB compressed, exactly
accounting for the SDK pack size delta below). These are AOSP
tools/base/deploy/installerbinaries (Android Studio's "Apply Changes"fast-deploy helper). Strings analysis confirmed the
tools/base/deploy/proto/deploy.pb.ccand protobuf symbols.tree for the path and for "ApplyChanges"/"deploy.installer". APS shipped
them but had no source either; they were pre-built blobs inherited from
upstream.
Pack size delta:
Microsoft.Android.Sdk.Darwin: 145.5 MB vs 151.6 MB (-6.16 MB)Microsoft.Android.Sdk.Windows: 129.1 MB vs 135.3 MB (-6.16 MB)Ref pack, runtime packs, manifest, and templates are bit-for-bit equivalent
in size. No concerning regressions in the shipped product.