From ab56903da184814fbe3fe7a4f5785ae58fecca2f Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 28 Feb 2025 17:58:47 +0100 Subject: [PATCH 01/39] Enable the test --- .../Tests/Xamarin.Android.Build.Tests/BuildTest2.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index c9e0ac98f36..b9701f8c3ba 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -109,9 +109,6 @@ public void BuildBasicApplication ([Values (true, false)] bool isRelease, [Value [Test] public void BasicApplicationOtherRuntime ([Values (true, false)] bool isRelease) { - // This test would fail, as it requires **our** updated runtime pack, which isn't currently created - // It is created in `src/native/native-clr.csproj` which isn't built atm. - Assert.Ignore ("CoreCLR support isn't fully enabled yet. This test will be enabled in a follow-up PR."); var proj = new XamarinAndroidApplicationProject { IsRelease = isRelease, // Add locally downloaded CoreCLR packs From f1cb05744eac1ffa98976c59b16947bceef0501c Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 28 Feb 2025 19:05:48 +0100 Subject: [PATCH 02/39] Let's see if I got it right :D --- build-tools/automation/azure-pipelines.yaml | 18 ++++++++++++++++ .../yaml-templates/select-test-runtime.yaml | 14 +++++++++++++ .../yaml-templates/stage-linux-tests.yaml | 14 +++++++++++-- .../stage-msbuild-emulator-tests.yaml | 13 ++++++++++-- .../yaml-templates/stage-msbuild-tests.yaml | 7 ++++++- .../Utilities/BaseTest.cs | 3 +++ .../Common/XamarinProject.cs | 8 +++++++ .../Utilities/TargetRuntimeHelper.cs | 21 +++++++++++++++++++ .../Tests/AotProfileTests.cs | 4 ++++ 9 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 build-tools/automation/yaml-templates/select-test-runtime.yaml create mode 100644 src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs diff --git a/build-tools/automation/azure-pipelines.yaml b/build-tools/automation/azure-pipelines.yaml index 446d491e4ed..6ae6834e2e3 100644 --- a/build-tools/automation/azure-pipelines.yaml +++ b/build-tools/automation/azure-pipelines.yaml @@ -103,12 +103,30 @@ extends: macTestAgentsUseCleanImages: ${{ parameters.macTestAgentsUseCleanImages }} - template: /build-tools/automation/yaml-templates/stage-linux-tests.yaml@self + parameters: + runtimeName: "MonoVM" + + - template: /build-tools/automation/yaml-templates/stage-msbuild-tests.yaml@self + parameters: + runtimeName: "MonoVM" + + - template: /build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml@self + parameters: + usesCleanImages: ${{ parameters.macTestAgentsUseCleanImages }} + runtimeName: "MonoVM" + + - template: /build-tools/automation/yaml-templates/stage-linux-tests.yaml@self + parameters: + runtimeName: "CoreCLR" - template: /build-tools/automation/yaml-templates/stage-msbuild-tests.yaml@self + parameters: + runtimeName: "CoreCLR" - template: /build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml@self parameters: usesCleanImages: ${{ parameters.macTestAgentsUseCleanImages }} + runtimeName: "CoreCLR" - stage: maui_tests displayName: MAUI Tests diff --git a/build-tools/automation/yaml-templates/select-test-runtime.yaml b/build-tools/automation/yaml-templates/select-test-runtime.yaml new file mode 100644 index 00000000000..c9ea2d78880 --- /dev/null +++ b/build-tools/automation/yaml-templates/select-test-runtime.yaml @@ -0,0 +1,14 @@ +parameters: + runtimeName: '' + +steps: +- pwsh: | + Write-Host "Selecting target runtime: "${{ parameters.runtimeName }}"" + if ("${{ parameters.runtimeName }}" -eq "CoreCLR") { + $useMonoRuntime="false" + } else { + $useMonoRuntime="true" + } + + Write-Host "##vso[task.setvariable variable=USE_MONO_RUNTIME]$useMonoRuntime" + displayName: select target runtime (MonoVM or CoreCLR) diff --git a/build-tools/automation/yaml-templates/stage-linux-tests.yaml b/build-tools/automation/yaml-templates/stage-linux-tests.yaml index 92173aa7f37..f89569afdbf 100644 --- a/build-tools/automation/yaml-templates/stage-linux-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-linux-tests.yaml @@ -1,8 +1,10 @@ # Runs smoke tests on Linux packages. +parameters: + runtimeName: '' stages: - stage: linux_tests - displayName: Linux Tests + displayName: Linux Tests (${{ parameters.runtimeName }}) dependsOn: - mac_build - linux_build @@ -20,6 +22,10 @@ stages: steps: - template: /build-tools/automation/yaml-templates/setup-test-environment.yaml + - template: /build-tools/automation/yaml-templates/select-test-runtim.yaml + parameters: + runtimeName: ${{ parameters.runtimeName }} + - task: DownloadPipelineArtifact@2 inputs: artifactName: $(TestAssembliesArtifactName) @@ -39,7 +45,7 @@ stages: - template: /build-tools/automation/yaml-templates/fail-on-issue.yaml - job: linux_tests_smoke_2 - displayName: Linux > Tests > MSBuild 2 + displayName: Linux > Tests > MSBuild 2 (${{ parameters.runtimeName }}) pool: name: MAUI-1ESPT image: $(LinuxPoolImage1ESPT) @@ -50,6 +56,10 @@ stages: steps: - template: /build-tools/automation/yaml-templates/setup-test-environment.yaml + - template: /build-tools/automation/yaml-templates/select-test-runtim.yaml + parameters: + runtimeName: ${{ parameters.runtimeName }} + - task: DownloadPipelineArtifact@2 inputs: artifactName: $(TestAssembliesArtifactName) diff --git a/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml b/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml index 957e3f239fb..a7628035f5f 100644 --- a/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml @@ -1,6 +1,7 @@ # Runs MSBuild tests against a device running on macOS parameters: + runtimeName: '' stageName: msbuilddevice_tests job_name: 'mac_dotnetdevice_tests' dependsOn: mac_build @@ -17,7 +18,7 @@ parameters: stages: - stage: ${{ parameters.stageName }} - displayName: ${{ parameters.stagePrefix }}MSBuild Emulator Tests + displayName: ${{ parameters.stagePrefix }}MSBuild Emulator Tests (${{ parameters.runtimeName }}) dependsOn: ${{ parameters.dependsOn }} condition: ${{ parameters.stageCondition }} jobs: @@ -44,6 +45,10 @@ stages: commit: ${{ parameters.commit }} xaprepareScenario: EmulatorTestDependencies + - template: /build-tools/automation/yaml-templates/select-test-runtim.yaml + parameters: + runtimeName: ${{ parameters.runtimeName }} + - task: DownloadPipelineArtifact@2 inputs: artifactName: $(TestAssembliesArtifactName) @@ -85,7 +90,7 @@ stages: condition: ${{ parameters.shouldFailOnIssue }} - job: wear_tests - displayName: macOS > Tests > WearOS + displayName: macOS > Tests > WearOS (${{ parameters.runtimeName }}) timeoutInMinutes: 180 cancelTimeoutInMinutes: 2 strategy: @@ -111,6 +116,10 @@ stages: commit: ${{ parameters.commit }} xaprepareScenario: EmulatorTestDependencies + - template: /build-tools/automation/yaml-templates/select-test-runtim.yaml + parameters: + runtimeName: ${{ parameters.runtimeName }} + - task: DownloadPipelineArtifact@2 inputs: artifactName: $(TestAssembliesArtifactName) diff --git a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml index 54fb9005e16..4151150ff67 100644 --- a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml @@ -1,6 +1,7 @@ # Runs MSBuild tests that do not require devices on Mac/Windows parameters: + runtimeName: '' stageName: msbuild_dotnet stageCondition: succeeded() dependsOn: mac_build @@ -13,10 +14,14 @@ parameters: stages: - stage: ${{ parameters.stageName }} - displayName: ${{ parameters.stagePrefix }}MSBuild Tests + displayName: ${{ parameters.stagePrefix }}MSBuild Tests (${{ parameters.runtimeName }}) dependsOn: ${{ parameters.dependsOn }} condition: ${{ parameters.stageCondition }} jobs: + - template: /build-tools/automation/yaml-templates/select-test-runtim.yaml + parameters: + runtimeName: ${{ parameters.runtimeName }} + - template: /build-tools/automation/yaml-templates/run-msbuild-tests.yaml parameters: testOS: macOS diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs index 1d3d5dca3fe..3534236e5b5 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs @@ -69,6 +69,9 @@ public static string AndroidNdkPath { } } + public static bool TargetsMonoVM => TargetRuntimeHelper.UseMonoRuntime; + public static bool TargetsCoreCLR => !TargetRuntimeHelper.UseMonoRuntime; + /// /// Windows can only create a file of 255 characters: This type of path is composed of components separated by backslashes, each up to the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function (this value is commonly 255 characters). /// See: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/XamarinProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/XamarinProject.cs index 601406c0748..b9248e2f916 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/XamarinProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/XamarinProject.cs @@ -76,6 +76,9 @@ public XamarinProject (string debugConfigurationName = "Debug", string releaseCo PropertyGroups.Add (release); Imports = new List (); + // Selects between MonoVM and CoreCLR (based on presence of the USE_MONO_RUNTIME environment variable) + SetProperty ("UseMonoRuntime", TargetRuntimeHelper.UseMonoRuntime ? "true" : "false"); + //NOTE: for SDK-style projects, we need $(Configuration) set before Microsoft.NET.Sdk.targets Imports.Add (new Import ("Directory.Build.props") { TextContent = () => @@ -109,6 +112,11 @@ public string TargetFrameworks { set { SetProperty ("TargetFrameworks", value); } } + public string UseMonoRuntime { + get { return GetProperty ("UseMonoRuntime"); } + set { SetProperty ("UseMonoRuntime", value); } + } + public string GetProperty (string name) { return GetProperty (CommonProperties, name); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs new file mode 100644 index 00000000000..044f035450a --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs @@ -0,0 +1,21 @@ +using System; + +namespace Xamarin.ProjectTools; + +public class TargetRuntimeHelper +{ + static readonly bool useMonoRuntime; + + static TargetRuntimeHelper () + { + string? envvar = Environment.GetEnvironmentVariable ("USE_MONO_RUNTIME"); + if (envvar == null || envvar.Length == 0 || String.Compare ("true", envvar, StringComparison.OrdinalIgnoreCase) == 0) { + useMonoRuntime = true; + } else { + useMonoRuntime = false; + } + } + + public static bool UseMonoRuntime => useMonoRuntime; + public static bool UseCoreCLR => !useMonoRuntime; +} \ No newline at end of file diff --git a/tests/MSBuildDeviceIntegration/Tests/AotProfileTests.cs b/tests/MSBuildDeviceIntegration/Tests/AotProfileTests.cs index bbc15d40d64..2bb0225206d 100644 --- a/tests/MSBuildDeviceIntegration/Tests/AotProfileTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/AotProfileTests.cs @@ -27,6 +27,10 @@ protected void ClearProp () [NonParallelizable] public void BuildBasicApplicationAndAotProfileIt () { + if (!TargetsMonoVM) { + Assert.Ignore ("This test runs only when targetting MonoVM"); + } + var proj = new XamarinAndroidApplicationProject () { IsRelease = true, AotAssemblies = false, From f496a815c35af330673760a36fb70f378db3ba04 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 28 Feb 2025 19:14:22 +0100 Subject: [PATCH 03/39] Fix typos --- build-tools/automation/yaml-templates/stage-linux-tests.yaml | 4 ++-- .../yaml-templates/stage-msbuild-emulator-tests.yaml | 4 ++-- .../automation/yaml-templates/stage-msbuild-tests.yaml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build-tools/automation/yaml-templates/stage-linux-tests.yaml b/build-tools/automation/yaml-templates/stage-linux-tests.yaml index f89569afdbf..12427c80083 100644 --- a/build-tools/automation/yaml-templates/stage-linux-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-linux-tests.yaml @@ -22,7 +22,7 @@ stages: steps: - template: /build-tools/automation/yaml-templates/setup-test-environment.yaml - - template: /build-tools/automation/yaml-templates/select-test-runtim.yaml + - template: /build-tools/automation/yaml-templates/select-test-runtime.yaml parameters: runtimeName: ${{ parameters.runtimeName }} @@ -56,7 +56,7 @@ stages: steps: - template: /build-tools/automation/yaml-templates/setup-test-environment.yaml - - template: /build-tools/automation/yaml-templates/select-test-runtim.yaml + - template: /build-tools/automation/yaml-templates/select-test-runtime.yaml parameters: runtimeName: ${{ parameters.runtimeName }} diff --git a/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml b/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml index a7628035f5f..4a05e5c7273 100644 --- a/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml @@ -45,7 +45,7 @@ stages: commit: ${{ parameters.commit }} xaprepareScenario: EmulatorTestDependencies - - template: /build-tools/automation/yaml-templates/select-test-runtim.yaml + - template: /build-tools/automation/yaml-templates/select-test-runtime.yaml parameters: runtimeName: ${{ parameters.runtimeName }} @@ -116,7 +116,7 @@ stages: commit: ${{ parameters.commit }} xaprepareScenario: EmulatorTestDependencies - - template: /build-tools/automation/yaml-templates/select-test-runtim.yaml + - template: /build-tools/automation/yaml-templates/select-test-runtime.yaml parameters: runtimeName: ${{ parameters.runtimeName }} diff --git a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml index 4151150ff67..e407eb404ac 100644 --- a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml @@ -18,7 +18,7 @@ stages: dependsOn: ${{ parameters.dependsOn }} condition: ${{ parameters.stageCondition }} jobs: - - template: /build-tools/automation/yaml-templates/select-test-runtim.yaml + - template: /build-tools/automation/yaml-templates/select-test-runtime.yaml parameters: runtimeName: ${{ parameters.runtimeName }} From 6132478bd0fc79621006c4ee0ab166bc767e7754 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 28 Feb 2025 19:32:15 +0100 Subject: [PATCH 04/39] Fix number two --- build-tools/automation/yaml-templates/run-msbuild-tests.yaml | 4 ++++ .../automation/yaml-templates/stage-msbuild-tests.yaml | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build-tools/automation/yaml-templates/run-msbuild-tests.yaml b/build-tools/automation/yaml-templates/run-msbuild-tests.yaml index 7853353e798..c5434936f29 100644 --- a/build-tools/automation/yaml-templates/run-msbuild-tests.yaml +++ b/build-tools/automation/yaml-templates/run-msbuild-tests.yaml @@ -42,6 +42,10 @@ jobs: repositoryAlias: ${{ parameters.repositoryAlias }} commit: ${{ parameters.commit }} + - template: /build-tools/automation/yaml-templates/select-test-runtime.yaml + parameters: + runtimeName: ${{ parameters.runtimeName }} + - task: DownloadPipelineArtifact@2 inputs: artifactName: $(TestAssembliesArtifactName) diff --git a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml index e407eb404ac..35d0aecf7b8 100644 --- a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml @@ -18,10 +18,6 @@ stages: dependsOn: ${{ parameters.dependsOn }} condition: ${{ parameters.stageCondition }} jobs: - - template: /build-tools/automation/yaml-templates/select-test-runtime.yaml - parameters: - runtimeName: ${{ parameters.runtimeName }} - - template: /build-tools/automation/yaml-templates/run-msbuild-tests.yaml parameters: testOS: macOS From 8975a562ed1a96f258b3524e73a3458e67c90148 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 28 Feb 2025 19:49:12 +0100 Subject: [PATCH 05/39] Fix three --- build-tools/automation/yaml-templates/stage-linux-tests.yaml | 2 +- .../automation/yaml-templates/stage-msbuild-emulator-tests.yaml | 2 +- build-tools/automation/yaml-templates/stage-msbuild-tests.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build-tools/automation/yaml-templates/stage-linux-tests.yaml b/build-tools/automation/yaml-templates/stage-linux-tests.yaml index 12427c80083..5068ec80125 100644 --- a/build-tools/automation/yaml-templates/stage-linux-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-linux-tests.yaml @@ -3,7 +3,7 @@ parameters: runtimeName: '' stages: -- stage: linux_tests +- stage: linux_tests_${{ parameters.runtimeName }} displayName: Linux Tests (${{ parameters.runtimeName }}) dependsOn: - mac_build diff --git a/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml b/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml index 4a05e5c7273..9fe0cd93a13 100644 --- a/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml @@ -17,7 +17,7 @@ parameters: use1ESTemplate: true stages: -- stage: ${{ parameters.stageName }} +- stage: ${{ parameters.stageName }}_${{ parameters.runtimeName }} displayName: ${{ parameters.stagePrefix }}MSBuild Emulator Tests (${{ parameters.runtimeName }}) dependsOn: ${{ parameters.dependsOn }} condition: ${{ parameters.stageCondition }} diff --git a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml index 35d0aecf7b8..6038a718682 100644 --- a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml @@ -13,7 +13,7 @@ parameters: use1ESTemplate: true stages: -- stage: ${{ parameters.stageName }} +- stage: ${{ parameters.stageName }}_${{ parameters.runtimeName }} displayName: ${{ parameters.stagePrefix }}MSBuild Tests (${{ parameters.runtimeName }}) dependsOn: ${{ parameters.dependsOn }} condition: ${{ parameters.stageCondition }} From 32ebb88d88ff6a25fbb28d000d6714e6150ceb6f Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 4 Mar 2025 17:37:30 +0100 Subject: [PATCH 06/39] Let's see how this works --- .../yaml-templates/run-msbuild-tests.yaml | 7 ++++--- .../yaml-templates/stage-linux-tests.yaml | 18 +++++++++--------- .../yaml-templates/stage-msbuild-tests.yaml | 2 ++ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/build-tools/automation/yaml-templates/run-msbuild-tests.yaml b/build-tools/automation/yaml-templates/run-msbuild-tests.yaml index c5434936f29..b2ba62fbff9 100644 --- a/build-tools/automation/yaml-templates/run-msbuild-tests.yaml +++ b/build-tools/automation/yaml-templates/run-msbuild-tests.yaml @@ -1,5 +1,6 @@ parameters: testOS: '' # 'macOS' or 'Windows' + runtimeName: '' # MonoVM or CoreCLR jobName: '' # Name of the job jobDisplayName: '' # Display name of the job agentCount: 1 # Number of build agents to run in parallel @@ -48,20 +49,20 @@ jobs: - task: DownloadPipelineArtifact@2 inputs: - artifactName: $(TestAssembliesArtifactName) + artifactName: $(TestAssembliesArtifactName)-${{ parameters.runtimeName }} downloadPath: ${{ parameters.xaSourcePath }}/bin/Test$(XA.Build.Configuration) - template: /build-tools/automation/yaml-templates/run-sliced-nunit-tests.yaml parameters: testAssembly: ${{ parameters.xaSourcePath }}/bin/Test$(XA.Build.Configuration)/$(DotNetStableTargetFramework)/Xamarin.Android.Build.Tests.dll testFilter: ${{ parameters.testFilter }} - testRunTitle: Xamarin.Android.Build.Tests - ${{ parameters.testOS }} + testRunTitle: Xamarin.Android.Build.Tests - ${{ parameters.testOS }} (${{ parameters.runtimeName }}) retryFailedTests: false xaSourcePath: ${{ parameters.xaSourcePath }} - template: /build-tools/automation/yaml-templates/upload-results.yaml parameters: - artifactName: Test Results - MSBuild - ${{ parameters.testOS }}-$(System.JobPositionInPhase) + artifactName: Test Results - MSBuild - ${{ parameters.testOS }}-${{ parameters.runtimeName }}-$(System.JobPositionInPhase) xaSourcePath: ${{ parameters.xaSourcePath }} use1ESTemplate: ${{ parameters.use1ESTemplate }} diff --git a/build-tools/automation/yaml-templates/stage-linux-tests.yaml b/build-tools/automation/yaml-templates/stage-linux-tests.yaml index 5068ec80125..71a55240260 100644 --- a/build-tools/automation/yaml-templates/stage-linux-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-linux-tests.yaml @@ -11,7 +11,7 @@ stages: jobs: # Check - "Xamarin.Android (Linux Tests Linux > Tests > MSBuild)" - job: linux_tests_smoke_1 - displayName: Linux > Tests > MSBuild 1 + displayName: Linux > Tests > MSBuild 1 (${{ parameters.runtimeName }}) pool: name: MAUI-1ESPT image: $(LinuxPoolImage1ESPT) @@ -28,19 +28,19 @@ stages: - task: DownloadPipelineArtifact@2 inputs: - artifactName: $(TestAssembliesArtifactName) + artifactName: $(TestAssembliesArtifactName)-${{ parameters.rutimeName }} downloadPath: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration) - template: /build-tools/automation/yaml-templates/run-nunit-tests.yaml parameters: - testRunTitle: Xamarin.Android.Build.Tests - Linux BuildTest + testRunTitle: Xamarin.Android.Build.Tests - Linux BuildTest (${{ parameters.runtimeName }}) testAssembly: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/$(DotNetStableTargetFramework)/Xamarin.Android.Build.Tests.dll dotNetTestExtraArgs: --filter "Name = BuildTest" - template: /build-tools/automation/yaml-templates/upload-results.yaml parameters: configuration: $(XA.Build.Configuration) - artifactName: Test Results - MSBuild - Linux 1 + artifactName: Test Results - MSBuild - Linux 1 - ${{ parameters.runtimeName }} - template: /build-tools/automation/yaml-templates/fail-on-issue.yaml @@ -62,24 +62,24 @@ stages: - task: DownloadPipelineArtifact@2 inputs: - artifactName: $(TestAssembliesArtifactName) + artifactName: $(TestAssembliesArtifactName)-${{ parameters.runtimeName }} downloadPath: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration) - template: /build-tools/automation/yaml-templates/run-nunit-tests.yaml parameters: - testRunTitle: Xamarin.Android.Build.Tests - Linux PackagingTest + testRunTitle: Xamarin.Android.Build.Tests - Linux PackagingTest (${{ parameters.runtimeName }}) testAssembly: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/$(DotNetStableTargetFramework)/Xamarin.Android.Build.Tests.dll dotNetTestExtraArgs: --filter "Name = PackagingTest" - template: /build-tools/automation/yaml-templates/run-nunit-tests.yaml parameters: - testRunTitle: Xamarin.Android.Build.Tests - Linux XASdkTests + testRunTitle: Xamarin.Android.Build.Tests - Linux XASdkTests (${{ parameters.runtimeName }}) testAssembly: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/$(DotNetStableTargetFramework)/Xamarin.Android.Build.Tests.dll dotNetTestExtraArgs: --filter "Name = XASdkTests & Name != XamarinLegacySdk" - template: /build-tools/automation/yaml-templates/run-nunit-tests.yaml parameters: - testRunTitle: Xamarin.Android.Build.Tests - Linux AndroidDependenciesTests + testRunTitle: Xamarin.Android.Build.Tests - Linux AndroidDependenciesTests (${{ parameters.runtimeName }}) testAssembly: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/$(DotNetStableTargetFramework)/Xamarin.Android.Build.Tests.dll dotNetTestExtraArgs: --filter "Name = AndroidDependenciesTests" @@ -92,6 +92,6 @@ stages: - template: /build-tools/automation/yaml-templates/upload-results.yaml parameters: configuration: $(XA.Build.Configuration) - artifactName: Test Results - MSBuild - Linux 2 + artifactName: Test Results - MSBuild - Linux 2 - ${{ parameters.runtimeName }} - template: /build-tools/automation/yaml-templates/fail-on-issue.yaml diff --git a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml index 6038a718682..71b341ca714 100644 --- a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml @@ -21,6 +21,7 @@ stages: - template: /build-tools/automation/yaml-templates/run-msbuild-tests.yaml parameters: testOS: macOS + runtimeName: ${{ parameters.runtimeName }} jobName: mac_msbuild_tests jobDisplayName: macOS > Tests > MSBuild agentCount: 10 @@ -33,6 +34,7 @@ stages: - template: /build-tools/automation/yaml-templates/run-msbuild-tests.yaml parameters: testOS: Windows + runtimeName: ${{ parameters.runtimeName }} jobName: win_msbuild_tests jobDisplayName: Windows > Tests > MSBuild agentCount: 8 From 82b47f0c760f05196d00407e5144ab527b1c887b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 4 Mar 2025 23:25:23 +0100 Subject: [PATCH 07/39] How about this then --- build-tools/automation/yaml-templates/run-msbuild-tests.yaml | 4 ++-- build-tools/automation/yaml-templates/stage-linux-tests.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build-tools/automation/yaml-templates/run-msbuild-tests.yaml b/build-tools/automation/yaml-templates/run-msbuild-tests.yaml index b2ba62fbff9..4ca12ca5214 100644 --- a/build-tools/automation/yaml-templates/run-msbuild-tests.yaml +++ b/build-tools/automation/yaml-templates/run-msbuild-tests.yaml @@ -49,7 +49,7 @@ jobs: - task: DownloadPipelineArtifact@2 inputs: - artifactName: $(TestAssembliesArtifactName)-${{ parameters.runtimeName }} + artifactName: $(TestAssembliesArtifactName) downloadPath: ${{ parameters.xaSourcePath }}/bin/Test$(XA.Build.Configuration) - template: /build-tools/automation/yaml-templates/run-sliced-nunit-tests.yaml @@ -62,7 +62,7 @@ jobs: - template: /build-tools/automation/yaml-templates/upload-results.yaml parameters: - artifactName: Test Results - MSBuild - ${{ parameters.testOS }}-${{ parameters.runtimeName }}-$(System.JobPositionInPhase) + artifactName: Test Results - MSBuild - ${{ parameters.testOS }}-${{ parameters.runtimeName }} xaSourcePath: ${{ parameters.xaSourcePath }} use1ESTemplate: ${{ parameters.use1ESTemplate }} diff --git a/build-tools/automation/yaml-templates/stage-linux-tests.yaml b/build-tools/automation/yaml-templates/stage-linux-tests.yaml index 71a55240260..643d0888089 100644 --- a/build-tools/automation/yaml-templates/stage-linux-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-linux-tests.yaml @@ -28,7 +28,7 @@ stages: - task: DownloadPipelineArtifact@2 inputs: - artifactName: $(TestAssembliesArtifactName)-${{ parameters.rutimeName }} + artifactName: $(TestAssembliesArtifactName) downloadPath: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration) - template: /build-tools/automation/yaml-templates/run-nunit-tests.yaml @@ -62,7 +62,7 @@ stages: - task: DownloadPipelineArtifact@2 inputs: - artifactName: $(TestAssembliesArtifactName)-${{ parameters.runtimeName }} + artifactName: $(TestAssembliesArtifactName) downloadPath: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration) - template: /build-tools/automation/yaml-templates/run-nunit-tests.yaml From 5620b25662c95abfd2837eb427107bf1411890f2 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 5 Mar 2025 22:43:29 +0100 Subject: [PATCH 08/39] Let's see what, if anything, is fixed by this --- .../Android/XamarinAndroidApplicationProject.cs | 6 ++++++ .../Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs index a2112ab413c..0833d45cd37 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs @@ -69,6 +69,12 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug" AndroidResources.Add (new AndroidItem.AndroidResource ("Resources\\values\\Strings.xml") { TextContent = () => StringsXml.Replace ("${PROJECT_NAME}", ProjectName) }); Sources.Add (new BuildItem.Source (() => "MainActivity" + Language.DefaultExtension) { TextContent = () => ProcessSourceTemplate (MainActivity ?? DefaultMainActivity) }); + + // This is a quick hack to get all the tests executing in the CoreCLR context to work only for the, currently limited, + // subset of ABIs supported by CoreCLR without having to modify each test individually. Eventually it shouldn't be necessary. + if (TargetRuntimeHelper.UseCoreCLR) { + this.SetRuntimeIdentifiers (TargetRuntimeHelper.CoreClrSupportedAbis); + } } // it is exposed as public because we may want to slightly modify this. diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs index 044f035450a..d57943526fd 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs @@ -5,6 +5,7 @@ namespace Xamarin.ProjectTools; public class TargetRuntimeHelper { static readonly bool useMonoRuntime; + static readonly string[] coreClrSupportedAbis = new []{ "arm64-v8a" }; static TargetRuntimeHelper () { @@ -18,4 +19,5 @@ static TargetRuntimeHelper () public static bool UseMonoRuntime => useMonoRuntime; public static bool UseCoreCLR => !useMonoRuntime; -} \ No newline at end of file + public static string[] CoreClrSupportedAbis => coreClrSupportedAbis; +} From f2f996097a1300956022430b1e29bb276ad5579e Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 6 Mar 2025 09:01:20 +0100 Subject: [PATCH 09/39] Try to prevent the SetupOSSpecificPropertyes from running when not needed The target sets up environment for the NativeAOT ILC compiler and it requires to find llvm-objcopy and objcopy (among others) utilities in the PATH. We have code that sets PATH up to point to the NDK bin directory, but it runs too late to prevent errors when the setup target doesn't find all the required binaries. It appears the target runs whether or not NativeAOT is used, and is dependent on the NativeCompilationDuringPublish property being `true`, which is the default value, assigned to it whenever ilccompiler targets are included in the build (which seems to be our case no matter which android runtime we target in the given build). Let's see if this commit helps. --- .../Microsoft.Android.Sdk.DefaultProperties.targets | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets index a24f56ccf53..1876ebe9c9c 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets @@ -33,6 +33,13 @@ <_IsPublishing Condition=" '$(_IsPublishing)' == '' and '$(_AndroidRuntime)' == 'NativeAOT' ">true + + false + $(AndroidMinimumSupportedApiLevel) From 09a2d4a65f162de4bee32c3c3ff9db1188dce754 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 6 Mar 2025 16:31:41 +0100 Subject: [PATCH 10/39] Does this change anything? --- .../Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs index d57943526fd..74d7bde7e07 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs @@ -1,11 +1,13 @@ using System; +using System.Collections.Generic; namespace Xamarin.ProjectTools; public class TargetRuntimeHelper { static readonly bool useMonoRuntime; - static readonly string[] coreClrSupportedAbis = new []{ "arm64-v8a" }; + static readonly string[] coreClrSupportedAbis = new []{ "arm64-v8a", "x86_64" }; + static readonly HashSet coreClrAbis = new (coreClrSupportedAbis, StringComparer.OrdinalIgnoreCase); static TargetRuntimeHelper () { @@ -20,4 +22,6 @@ static TargetRuntimeHelper () public static bool UseMonoRuntime => useMonoRuntime; public static bool UseCoreCLR => !useMonoRuntime; public static string[] CoreClrSupportedAbis => coreClrSupportedAbis; + + public static bool CoreClrSupportsAbi (string abiName) => coreClrAbis.Contains (abiName); } From 1146a8929070b8acb5de056683341aee503517da Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 6 Mar 2025 20:21:25 +0100 Subject: [PATCH 11/39] Tweaks --- .../Android/XamarinAndroidApplicationProject.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs index 0833d45cd37..744c9ddaa58 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs @@ -187,6 +187,11 @@ public void SetPublishAot (bool value, string androidNdkPath) PublishAot = value; SetProperty ("AndroidNdkDirectory", androidNdkPath); + // CoreCLR tests won't work with PublishAot == true + if (value) { + RemoveProperty ("UseMonoRuntime"); + } + // NuGet feed needed as Microsoft.Android.Runtime.NativeAOT packs not installed in workload by default var source = Path.Combine (XABuildPaths.BuildOutputDirectory, "nuget-unsigned"); if (value) { From 4a1d9e9270354b2fcaeda846d3ca1cdf96593397 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 7 Mar 2025 23:23:00 +0100 Subject: [PATCH 12/39] Fix locations of native *.include files --- .../xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs b/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs index 4fecf7d4f43..149f08116dc 100644 --- a/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs +++ b/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs @@ -69,6 +69,8 @@ void CopyExtraBuildFiles (string destinationRoot, Context context) filesToCopyPreserveRelative.AddRange (Directory.GetFiles (javaInteropBuildConfigDir, "*.props")); } + filesToCopyPreserveRelative.AddRange (Directory.GetFiles (Path.Combine (BuildPaths.XamarinAndroidSourceRoot, "src", "native", "mono", "pinvoke-override"), "*.include.*")); + var buildConfigDir = Path.Combine (BuildPaths.XamarinAndroidSourceRoot, "bin", $"Build{context.Configuration}"); if (Directory.Exists (buildConfigDir)) { foreach (var fileMatch in buildConfigFiles) { From f2caf24009cec19396b15759f60754eb6169201d Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 7 Mar 2025 23:23:46 +0100 Subject: [PATCH 13/39] Update CoreCLR packages in the workload manifest --- .../WorkloadManifest.in.json | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json index 5f9e689ad17..75571790f71 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json @@ -6,11 +6,13 @@ "packs": [ "Microsoft.Android.Sdk.net10", "Microsoft.Android.Sdk.net9", - "Microsoft.Android.Ref.36", - "Microsoft.Android.Runtime.Mono.36.android-arm", - "Microsoft.Android.Runtime.Mono.36.android-arm64", - "Microsoft.Android.Runtime.Mono.36.android-x86", - "Microsoft.Android.Runtime.Mono.36.android-x64", + "Microsoft.Android.Ref.35", + "Microsoft.Android.Runtime.Mono.35.android-arm", + "Microsoft.Android.Runtime.Mono.35.android-arm64", + "Microsoft.Android.Runtime.Mono.35.android-x86", + "Microsoft.Android.Runtime.Mono.35.android-x64", + "Microsoft.Android.Runtime.CoreCLR.35.android-arm64", + "Microsoft.Android.Runtime.CoreCLR.35.android-x64", "Microsoft.Android.Templates" ], "platforms": [ "win-x64", "win-arm64", "linux-x64", "linux-arm64", "osx-x64", "osx-arm64" ], From 5378d9bc04c8d8602aa73a2969fcae7ea904758e Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 10 Mar 2025 12:49:17 +0100 Subject: [PATCH 14/39] Use `android-arm64`, since it's supported by all the runtimes --- .../Tests/Xamarin.Android.Build.Tests/XASdkTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs index 20e919022ee..d7b4c855402 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs @@ -218,7 +218,7 @@ public void DotNetPublish ([Values (false, true)] bool isRelease, [ValueSource(n Assert.Ignore ($"Test for API level {apiLevel} was skipped as it matched the default or latest stable API level."); var targetFramework = $"{dotnetVersion}-{platform}"; - const string runtimeIdentifier = "android-arm"; + const string runtimeIdentifier = "android-arm64"; var proj = new XamarinAndroidApplicationProject { TargetFramework = targetFramework, IsRelease = isRelease, From 7edcf4d987a688d486212100c21a81c842781d47 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 10 Mar 2025 13:08:40 +0100 Subject: [PATCH 15/39] CoreCLR doesn't support all RIDs --- .../Xamarin.Android.Build.Tests/BuildTest.cs | 4 ++++ .../Xamarin.Android.Build.Tests/BuildTest2.cs | 7 ++++++ .../Utilities/TargetRuntimeHelper.cs | 23 +++++++++++++++++++ .../Xamarin.Android.Common.targets | 5 ++++ 4 files changed, 39 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index acf0300f113..4648fa43e1a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -28,6 +28,10 @@ public partial class BuildTest : BaseTest [NonParallelizable] // On MacOS, parallel /restore causes issues public void DotNetBuild (string runtimeIdentifiers, bool isRelease, bool aot, bool usesAssemblyStore) { + if (TargetRuntimeHelper.UseCoreCLR && !TargetRuntimeHelper.CoreClrSupportsAllRIDs (runtimeIdentifiers)) { + Assert.Ignore ($"One or more RIDs aren't supported by CoreCLR: '{runtimeIdentifiers}'"); + } + var proj = new XamarinAndroidApplicationProject { IsRelease = isRelease, EnableDefaultItems = true, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index b9701f8c3ba..c6a8e68a401 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -427,6 +427,13 @@ public void BuildHasTrimmerWarnings (string properties, string [] codes, bool is var proj = new XamarinAndroidApplicationProject { IsRelease = isRelease, }; + if (totalWarnings != null && TargetRuntimeHelper.UseCoreCLR && TargetRuntimeHelper.CoreClrIsExperimental) { + // Experimental runtimes will issue warning XA1040 + totalWarnings++; + var newCodes = new List (codes); + newCodes.Add ("XA1040"); + codes = newCodes.ToArray (); + } proj.SetRuntimeIdentifier ("arm64-v8a"); proj.MainActivity = proj.DefaultMainActivity .Replace ("//${FIELDS}", "Type type = typeof (List<>);") diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs index 74d7bde7e07..142784a8e26 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using Xamarin.Android.Tasks; + namespace Xamarin.ProjectTools; public class TargetRuntimeHelper @@ -19,9 +21,30 @@ static TargetRuntimeHelper () } } + /// + /// This must be changed when we're ready to release. It is used to make tests which require a certain amount of warnings to + /// work when the XA1040 warning is issued (see Xamarin.Android.Common.targets, the `_CheckNonIdealAppConfigurations` target) + /// + public static bool CoreClrIsExperimental => true; public static bool UseMonoRuntime => useMonoRuntime; public static bool UseCoreCLR => !useMonoRuntime; public static string[] CoreClrSupportedAbis => coreClrSupportedAbis; public static bool CoreClrSupportsAbi (string abiName) => coreClrAbis.Contains (abiName); + + /// + /// contains a list of semicolon-separated RIDs (a single RID without + /// semicolons is also fine) which will be checked against the list of RIDs supported by CoreCLR. If even + /// a single RID isn't supported, `false` is returned. + /// + public static bool CoreClrSupportsAllRIDs (string runtimeIdentifiers) + { + foreach (string rid in runtimeIdentifiers.Split (';', StringSplitOptions.RemoveEmptyEntries)) { + if (!CoreClrSupportsAbi (MonoAndroidHelper.RidToAbi (rid))) { + return false; + } + } + + return true; + } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 5339fa643ea..cafb62b4dc7 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -568,6 +568,11 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. FormatArguments="AndroidFastDeploymentType;9" Condition=" '$(AndroidFastDeploymentType)' != '' " /> + + Date: Mon, 10 Mar 2025 13:10:42 +0100 Subject: [PATCH 16/39] Switch to `arm64-v8a`, because all runtimes support it --- .../IncrementalBuildTest.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs index bb7a266ed08..91e399f4bb6 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs @@ -311,7 +311,7 @@ public void ResolveNativeLibrariesInManagedReferences () IsRelease = true, ProjectGuid = Guid.NewGuid ().ToString (), OtherBuildItems = { - new BuildItem (AndroidBuildActions.EmbeddedNativeLibrary, "libs/armeabi-v7a/libfoo.so") { + new BuildItem (AndroidBuildActions.EmbeddedNativeLibrary, "libs/arm64-v8a/libfoo.so") { TextContent = () => string.Empty, Encoding = Encoding.ASCII, } @@ -332,14 +332,14 @@ public Class1 () }, }, }; - var so = lib.OtherBuildItems.First (x => x.Include () == "libs/armeabi-v7a/libfoo.so"); + var so = lib.OtherBuildItems.First (x => x.Include () == "libs/arm64-v8a/libfoo.so"); var lib2 = new XamarinAndroidLibraryProject () { ProjectName = "Lib2", ProjectGuid = Guid.NewGuid ().ToString (), IsRelease = true, OtherBuildItems = { - new BuildItem (AndroidBuildActions.EmbeddedNativeLibrary, "libs/armeabi-v7a/libfoo2.so") { + new BuildItem (AndroidBuildActions.EmbeddedNativeLibrary, "libs/arm64-v8a/libfoo2.so") { TextContent = () => string.Empty, Encoding = Encoding.ASCII, }, @@ -378,12 +378,12 @@ public Class2 () new BuildItem.ProjectReference (@"..\Lib2\Lib2.csproj", "Lib2", lib2.ProjectGuid), } }; - app.SetAndroidSupportedAbis ("armeabi-v7a"); + app.SetAndroidSupportedAbis ("arm64-v8a"); using (var builder = CreateApkBuilder (Path.Combine (path, "App"))) { Assert.IsTrue (builder.Build (app), "app 1st. build failed"); var libfoo = ZipHelper.ReadFileFromZip (Path.Combine (Root, builder.ProjectDirectory, app.OutputPath, app.PackageName + "-Signed.apk"), - "lib/armeabi-v7a/libfoo.so"); + "lib/arm64-v8a/libfoo.so"); Assert.IsNotNull (libfoo, "libfoo.so should exist in the .apk"); so.TextContent = () => "newValue"; @@ -395,10 +395,10 @@ public Class2 () Assert.IsNotNull (libfoo, "libfoo.so should exist in the .apk"); libfoo = ZipHelper.ReadFileFromZip (Path.Combine (Root, builder.ProjectDirectory, app.OutputPath, app.PackageName + "-Signed.apk"), - "lib/armeabi-v7a/libfoo.so"); + "lib/arm64-v8a/libfoo.so"); Assert.AreEqual (so.TextContent ().Length, libfoo.Length, "compressed size mismatch"); var libfoo2 = ZipHelper.ReadFileFromZip (Path.Combine (Root, builder.ProjectDirectory, app.OutputPath, app.PackageName + "-Signed.apk"), - "lib/armeabi-v7a/libfoo2.so"); + "lib/arm64-v8a/libfoo2.so"); Assert.IsNotNull (libfoo2, "libfoo2.so should exist in the .apk"); Directory.Delete (path, recursive: true); } From 02859ba8f7f322c2beea9c67b9e57dcf4d9cd90e Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 10 Mar 2025 13:13:03 +0100 Subject: [PATCH 17/39] Interpreter isn't supported by CoreCLR --- .../Tests/Xamarin.Android.Build.Tests/InvalidConfigTests.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/InvalidConfigTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/InvalidConfigTests.cs index da64e5e428e..9b3e3c34d30 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/InvalidConfigTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/InvalidConfigTests.cs @@ -103,6 +103,10 @@ public void XA0119AAB () [Test] public void XA0119Interpreter () { + if (TargetRuntimeHelper.UseCoreCLR) { + Assert.Ignore ("Not supported by CoreCLR"); + } + var proj = new XamarinAndroidApplicationProject { IsRelease = true, AotAssemblies = true, From c1f63a77991580d9756bc616fe7292c2ce30218b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 10 Mar 2025 13:17:21 +0100 Subject: [PATCH 18/39] Ignore test for unsupported ABIs --- .../ManifestTest.cs | 4 ++++ .../Utilities/TargetRuntimeHelper.cs | 20 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs index 2164f147f8f..94960029493 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs @@ -475,6 +475,10 @@ public void DirectBootAwareAttribute () [TestCaseSource(nameof (VersionCodeTestSource))] public void VersionCodeTests (bool seperateApk, string abis, string versionCode, bool useLegacy, string versionCodePattern, string versionCodeProperties, bool shouldBuild, string expectedVersionCode) { + if (TargetRuntimeHelper.UseCoreCLR && !TargetRuntimeHelper.CoreClrSupportsAllABIs (abis)) { + Assert.Ignore ($"One or more ABIs aren't supported by CoreCLR: '{abis}'"); + } + var proj = new XamarinAndroidApplicationProject () { IsRelease = true, MinSdkVersion = "21", diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs index 142784a8e26..d7fa3e185af 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs @@ -33,8 +33,8 @@ static TargetRuntimeHelper () public static bool CoreClrSupportsAbi (string abiName) => coreClrAbis.Contains (abiName); /// - /// contains a list of semicolon-separated RIDs (a single RID without - /// semicolons is also fine) which will be checked against the list of RIDs supported by CoreCLR. If even + /// contains a list of semicolon-separated RIDs (a single RID without + /// semicolon is also fine) which will be checked against the list of RIDs supported by CoreCLR. If even /// a single RID isn't supported, `false` is returned. /// public static bool CoreClrSupportsAllRIDs (string runtimeIdentifiers) @@ -47,4 +47,20 @@ public static bool CoreClrSupportsAllRIDs (string runtimeIdentifiers) return true; } + + /// + /// contains a list of semicolon-separated ABIs (a single ABI without + /// semicolon is also fine) which will be checked against the list of ABIs supported by CoreCLR. If even + /// a single ABI isn't supported, `false` is returned. + /// + public static bool CoreClrSupportsAllABIs (string abis) + { + foreach (string abi in abis.Split (';', StringSplitOptions.RemoveEmptyEntries)) { + if (!CoreClrSupportsAbi (abi)) { + return false; + } + } + + return true; + } } From eae315a0a600fdd9df088441cf6e0252dd172a3e Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 10 Mar 2025 13:26:14 +0100 Subject: [PATCH 19/39] CoreCLR doesn't support 32-bit ABIs --- .../PackagingTest.cs | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs index e2bee620c1e..82c9e2f8152 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs @@ -392,10 +392,14 @@ public void CheckSignApk ([Values(true, false)] bool useApkSigner, [Values(true, proj.SetProperty (proj.ReleaseProperties, "AndroidSigningKeyPass", Uri.EscapeDataString (pass)); proj.SetProperty (proj.ReleaseProperties, "AndroidSigningStorePass", Uri.EscapeDataString (pass)); proj.SetProperty (proj.ReleaseProperties, KnownProperties.AndroidCreatePackagePerAbi, perAbiApk); - if (perAbiApk) { + + bool thirtyTwoBitAbisSupported = + !TargetRuntimeHelper.UseCoreCLR || + (TargetRuntimeHelper.CoreClrSupportsAbi ("armeabi-v7a") && TargetRuntimeHelper.CoreClrSupportsAbi ("x86")); + if (perAbiApk && thirtyTwoBitAbisSupported) { // CoreCLR doesn't support 32-bit ABIs proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86", "arm64-v8a", "x86_64"); } else { - proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86"); + proj.SetAndroidSupportedAbis ("arm64-v8a", "x86_64"); } using (var b = CreateApkBuilder (Path.Combine ("temp", TestName, "App"))) { var bin = Path.Combine (Root, b.ProjectDirectory, proj.OutputPath); @@ -415,9 +419,21 @@ public void CheckSignApk ([Values(true, false)] bool useApkSigner, [Values(true, int x86ManifestCode = GetVersionCodeFromIntermediateManifest (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "x86", "AndroidManifest.xml")); int arm64ManifestCode = GetVersionCodeFromIntermediateManifest (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "arm64-v8a", "AndroidManifest.xml")); int x86_64ManifestCode = GetVersionCodeFromIntermediateManifest (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "x86_64", "AndroidManifest.xml")); - var versionList = new List { armManifestCode, x86ManifestCode, arm64ManifestCode, x86_64ManifestCode }; - Assert.True (versionList.Distinct ().Count () == versionList.Count, - $"APK version codes were not unique - armeabi-v7a: {armManifestCode}, x86: {x86ManifestCode}, arm64-v8a: {arm64ManifestCode}, x86_64: {x86_64ManifestCode}"); + List versionList; + if (thirtyTwoBitAbisSupported) { + versionList = new List { armManifestCode, x86ManifestCode, arm64ManifestCode, x86_64ManifestCode }; + } else { + versionList = new List { arm64ManifestCode, x86_64ManifestCode }; + } + + string errorMessage; + if (thirtyTwoBitAbisSupported) { + errorMessage = $"APK version codes were not unique - armeabi-v7a: {armManifestCode}, x86: {x86ManifestCode}, arm64-v8a: {arm64ManifestCode}, x86_64: {x86_64ManifestCode}"; + } else { + errorMessage = $"APK version codes were not unique - arm64-v8a: {arm64ManifestCode}, x86_64: {x86_64ManifestCode}"; + } + + Assert.True (versionList.Distinct ().Count () == versionList.Count, errorMessage); } var item = proj.AndroidResources.First (x => x.Include () == "Resources\\values\\Strings.xml"); From 44f75fbbf5bf57950357f25e5d68913fcca4473f Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 10 Mar 2025 13:28:04 +0100 Subject: [PATCH 20/39] CoreCLR doesn't support MonoVM-style AOT --- .../Tests/Xamarin.Android.Build.Tests/AotTests.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs index 5a135444ca7..a7e1847a9c8 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs @@ -163,6 +163,10 @@ public void BuildAotApplicationWithNdkAndBundleAndÜmläüts (string supportedAb if (IsWindows) Assert.Ignore ("https://github.com/dotnet/runtime/issues/88625"); + if (TargetRuntimeHelper.UseCoreCLR) { + Assert.Ignore ("CoreCLR doesn't support MonoVM-style AOT builds"); + } + var abisSanitized = supportedAbis.Replace (";", "").Replace ("-", "").Replace ("_", ""); var path = Path.Combine ("temp", string.Format ("BuildAotNdk AndÜmläüts_{0}_{1}_{2}", abisSanitized, enableLLVM, usesAssemblyBlobs)); var proj = new XamarinAndroidApplicationProject () { From 597b85531ca6186dad243372a631c300c15e7415 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 10 Mar 2025 13:37:35 +0100 Subject: [PATCH 21/39] Use only 64-bit ABIs --- .../EnvironmentContentTests.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/EnvironmentContentTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/EnvironmentContentTests.cs index 1d8ff21e199..eb0a127d18b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/EnvironmentContentTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/EnvironmentContentTests.cs @@ -17,7 +17,7 @@ public class EnvironmentContentTests : BaseTest [NonParallelizable] public void BuildApplicationWithMonoEnvironment ([Values ("", "Normal", "Offline")] string sequencePointsMode) { - const string supportedAbis = "armeabi-v7a;x86"; + const string supportedAbis = "arm64-v8a;x86_64"; var lib = new XamarinAndroidLibraryProject { ProjectName = "Library1", @@ -77,7 +77,7 @@ public void BuildApplicationWithMonoEnvironment ([Values ("", "Normal", "Offline [Test] public void CheckMonoDebugIsAddedToEnvironment ([Values ("", "Normal", "Offline")] string sequencePointsMode) { - const string supportedAbis = "armeabi-v7a;x86"; + const string supportedAbis = "arm64-v8a;x86_64"; var proj = new XamarinAndroidApplicationProject () { IsRelease = true, @@ -108,6 +108,10 @@ public void CheckMonoDebugIsAddedToEnvironment ([Values ("", "Normal", "Offline" [Test] public void CheckConcurrentGC () { + if (TargetRuntimeHelper.UseCoreCLR) { + Assert.Ignore ("Mono GC isn't supported on CoreCLR"); + } + var proj = new XamarinAndroidApplicationProject () { IsRelease = true, }; @@ -160,7 +164,7 @@ public void CheckHttpClientHandlerType () var expectedDefaultValue = "System.Net.Http.SocketsHttpHandler, System.Net.Http"; var expectedUpdatedValue = "Xamarin.Android.Net.AndroidMessageHandler"; - var supportedAbis = "armeabi-v7a;arm64-v8a"; + var supportedAbis = "arm64-v8a;x86_64"; proj.SetAndroidSupportedAbis (supportedAbis); proj.PackageReferences.Add (new Package() { Id = "System.Net.Http", Version = "*" }); proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}", "var _ = new System.Net.Http.HttpClient ();"); From dd0a026e40c6ba7db4fa9e3af2bf9ede91d42811 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 10 Mar 2025 13:37:59 +0100 Subject: [PATCH 22/39] Don't do that, we will ignore the entire category eventually --- .../Tests/Xamarin.Android.Build.Tests/AotTests.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs index a7e1847a9c8..5a135444ca7 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs @@ -163,10 +163,6 @@ public void BuildAotApplicationWithNdkAndBundleAndÜmläüts (string supportedAb if (IsWindows) Assert.Ignore ("https://github.com/dotnet/runtime/issues/88625"); - if (TargetRuntimeHelper.UseCoreCLR) { - Assert.Ignore ("CoreCLR doesn't support MonoVM-style AOT builds"); - } - var abisSanitized = supportedAbis.Replace (";", "").Replace ("-", "").Replace ("_", ""); var path = Path.Combine ("temp", string.Format ("BuildAotNdk AndÜmläüts_{0}_{1}_{2}", abisSanitized, enableLLVM, usesAssemblyBlobs)); var proj = new XamarinAndroidApplicationProject () { From 78d9e9808e6eeb48f5ff28ae98a4b65e52034b1b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 10 Mar 2025 13:41:47 +0100 Subject: [PATCH 23/39] Switch more tests to 64-bit ABIs --- .../Tests/Xamarin.Android.Build.Tests/BuildTest.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index 4648fa43e1a..ecaf55817a6 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -229,6 +229,10 @@ public void DotNetBuild (string runtimeIdentifiers, bool isRelease, bool aot, bo [TestCaseSource (nameof (MonoComponentMaskChecks))] public void CheckMonoComponentsMask (bool enableProfiler, bool useInterpreter, bool debugBuild, uint expectedMask) { + if (TargetRuntimeHelper.UseCoreCLR) { + Assert.Ignore ("CoreCLR does not support MonoVM components"); + } + var proj = new XamarinFormsAndroidApplicationProject () { IsRelease = !debugBuild, }; @@ -271,13 +275,17 @@ public void CheckMonoComponentsMask (bool enableProfiler, bool useInterpreter, b [NonParallelizable] public void CheckAssemblyCounts (bool isRelease, bool aot) { + if (aot && TargetRuntimeHelper.UseCoreCLR) { + Assert.Ignore ("CoreCLR doesn't support MonoVM-style AOT"); + } + var proj = new XamarinFormsAndroidApplicationProject { IsRelease = isRelease, EmbedAssembliesIntoApk = true, AotAssemblies = aot, }; - var abis = new [] { "armeabi-v7a", "x86" }; + var abis = new [] { "arm64-v8a", "x86_64" }; proj.SetRuntimeIdentifiers (abis); proj.SetProperty (proj.ActiveConfigurationProperties, "AndroidUseAssemblyStore", "True"); @@ -1273,7 +1281,7 @@ public void PackageNamingPolicy ([Values ("LowercaseMD5", "LowercaseCrc64")] str var proj = new XamarinAndroidApplicationProject (); proj.SetProperty ("UseInterpreter", "true"); proj.SetProperty ("AndroidPackageNamingPolicy", packageNamingPolicy); - proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86"); + proj.SetAndroidSupportedAbis ("arm64-v8a", "x86_64"); using (var b = CreateApkBuilder ()) { Assert.IsTrue (b.Build (proj), "build should have succeeded."); var environment = b.Output.GetIntermediaryPath (Path.Combine ("__environment__.txt")); From 7530646375cc836056de794ce86c18a4ed97bcfa Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 11 Mar 2025 10:25:43 +0100 Subject: [PATCH 24/39] Let's see what this changes --- .../Utilities/AssertionExtensions.cs | 22 +++++++++++++-- .../Xamarin.Android.Build.Tests/XASdkTests.cs | 4 +-- .../XamarinAndroidApplicationProject.cs | 27 ++++++++++++------- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/AssertionExtensions.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/AssertionExtensions.cs index a6bc7f20c4b..f4a4db9ad71 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/AssertionExtensions.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/AssertionExtensions.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Diagnostics; using System.IO; using NUnit.Framework; @@ -125,16 +126,33 @@ public static void AssertEntryContents (this ZipArchive zip, string zipPath, str } } + static void AllowCoreCLRWarning (IEnumerable lastBuildOutput, string logFile) + { + // With CoreCLR being experimental, we allow a single warning (XA1040) + Assert.IsTrue (StringAssertEx.ContainsText (lastBuildOutput, " 1 Warning(s)"), $"{logFile} should have at most 1 MSBuild warning."); + Assert.True (StringAssertEx.ContainsText (lastBuildOutput, "XA1040"), "Should receive XA1040 warning"); + } + [DebuggerHidden] public static void AssertHasNoWarnings (this ProjectBuilder builder) { - Assert.IsTrue (StringAssertEx.ContainsText (builder.LastBuildOutput, " 0 Warning(s)"), $"{builder.BuildLogFile} should have no MSBuild warnings."); + if (!TargetRuntimeHelper.UseCoreCLR || !TargetRuntimeHelper.CoreClrIsExperimental) { + Assert.IsTrue (StringAssertEx.ContainsText (builder.LastBuildOutput, " 0 Warning(s)"), $"{builder.BuildLogFile} should have no MSBuild warnings."); + return; + } + + AllowCoreCLRWarning (builder.LastBuildOutput, builder.BuildLogFile); } [DebuggerHidden] public static void AssertHasNoWarnings (this DotNetCLI dotnet) { - Assert.IsTrue (StringAssertEx.ContainsText (dotnet.LastBuildOutput, " 0 Warning(s)"), $"{dotnet.BuildLogFile} should have no MSBuild warnings."); + if (!TargetRuntimeHelper.UseCoreCLR || !TargetRuntimeHelper.CoreClrIsExperimental) { + Assert.IsTrue (StringAssertEx.ContainsText (dotnet.LastBuildOutput, " 0 Warning(s)"), $"{dotnet.BuildLogFile} should have no MSBuild warnings."); + return; + } + + AllowCoreCLRWarning (dotnet.LastBuildOutput, dotnet.BuildLogFile); } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs index d7b4c855402..e42604073e3 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs @@ -203,7 +203,7 @@ public void DotNetPublishDefaultValues([Values (false, true)] bool isRelease) } [Test] - public void DotNetPublish ([Values (false, true)] bool isRelease, [ValueSource(nameof(DotNetTargetFrameworks))] object[] data) + public void DotNetPublish ([Values (false, true)] bool isRelease, [ValueSource(nameof(DotNetTargetFrameworks))] object[] data, [Values ("Mono", "CoreCLR")] string runtime) { var dotnetVersion = (string)data[0]; var platform = (string)data[1]; @@ -249,8 +249,6 @@ public void DotNetPublish ([Values (false, true)] bool isRelease, [ValueSource(n var expectedMonoAndroidRefPath = Path.Combine (refDirectory, "ref", dotnetVersion, "Mono.Android.dll"); Assert.IsTrue (dotnet.LastBuildOutput.ContainsText (expectedMonoAndroidRefPath), $"Build should be using {expectedMonoAndroidRefPath}"); - // TODO: We could parameterize this later - const string runtime = "Mono"; var runtimeApiLevel = (apiLevel == XABuildConfig.AndroidDefaultTargetDotnetApiLevel && apiLevel < XABuildConfig.AndroidLatestStableApiLevel) ? XABuildConfig.AndroidLatestStableApiLevel : apiLevel; var runtimeDirectory = Directory.GetDirectories (Path.Combine (TestEnvironment.DotNetPreviewPacksDirectory, $"Microsoft.Android.Runtime.{runtime}.{runtimeApiLevel}.{runtimeIdentifier}")).LastOrDefault (); var expectedMonoAndroidRuntimePath = Path.Combine (runtimeDirectory, "runtimes", runtimeIdentifier, "lib", dotnetVersion, "Mono.Android.dll"); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs index 744c9ddaa58..67a4e9e5f44 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs @@ -70,10 +70,13 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug" Sources.Add (new BuildItem.Source (() => "MainActivity" + Language.DefaultExtension) { TextContent = () => ProcessSourceTemplate (MainActivity ?? DefaultMainActivity) }); - // This is a quick hack to get all the tests executing in the CoreCLR context to work only for the, currently limited, - // subset of ABIs supported by CoreCLR without having to modify each test individually. Eventually it shouldn't be necessary. if (TargetRuntimeHelper.UseCoreCLR) { + // This is a quick hack to get all the tests executing in the CoreCLR context to work only for the, currently limited, + // subset of ABIs supported by CoreCLR without having to modify each test individually. Eventually it shouldn't be necessary. this.SetRuntimeIdentifiers (TargetRuntimeHelper.CoreClrSupportedAbis); + + // NuGet feed needed as Microsoft.Android.Runtime.CoreCLR packs not installed in workload by default + AddOrRemoveLocalNugetFeedPath (add: true); } } @@ -176,6 +179,18 @@ private bool PublishAot { set { SetProperty (KnownProperties.PublishAot, value.ToString ()); } } + void AddOrRemoveLocalNugetFeedPath (bool add) + { + var source = Path.Combine (XABuildPaths.BuildOutputDirectory, "nuget-unsigned"); + if (add) { + if (!ExtraNuGetConfigSources.Contains (source)) { + ExtraNuGetConfigSources.Add (source); + } + } else { + ExtraNuGetConfigSources.Remove (source); + } + } + /// /// Sets properties required for $(PublishAot)=true /// @@ -193,13 +208,7 @@ public void SetPublishAot (bool value, string androidNdkPath) } // NuGet feed needed as Microsoft.Android.Runtime.NativeAOT packs not installed in workload by default - var source = Path.Combine (XABuildPaths.BuildOutputDirectory, "nuget-unsigned"); - if (value) { - if (!ExtraNuGetConfigSources.Contains (source)) - ExtraNuGetConfigSources.Add (source); - } else { - ExtraNuGetConfigSources.Remove (source); - } + AddOrRemoveLocalNugetFeedPath (add: value); } public string AndroidManifest { get; set; } From 600743a856b442e64ffcb7064ca4cbe5c370f1ed Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 10 Mar 2025 20:37:45 +0100 Subject: [PATCH 25/39] Address feedback --- build-tools/scripts/Ndk.projitems.in | 18 ++++++++++++++++++ .../WorkloadManifest.in.json | 2 -- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/build-tools/scripts/Ndk.projitems.in b/build-tools/scripts/Ndk.projitems.in index e767b8c460f..82a451a5b87 100644 --- a/build-tools/scripts/Ndk.projitems.in +++ b/build-tools/scripts/Ndk.projitems.in @@ -58,4 +58,22 @@ True + + + + $(AndroidNdkApiLevel_ArmV8a) + $(AndroidNdkApiLevel_Arm64) + android-arm64 + + + + $(AndroidNdkApiLevel_X86_64) + $(AndroidNdkApiLevel_X64) + android-x64 + + diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json index 75571790f71..f3a51a493d5 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json @@ -11,8 +11,6 @@ "Microsoft.Android.Runtime.Mono.35.android-arm64", "Microsoft.Android.Runtime.Mono.35.android-x86", "Microsoft.Android.Runtime.Mono.35.android-x64", - "Microsoft.Android.Runtime.CoreCLR.35.android-arm64", - "Microsoft.Android.Runtime.CoreCLR.35.android-x64", "Microsoft.Android.Templates" ], "platforms": [ "win-x64", "win-arm64", "linux-x64", "linux-arm64", "osx-x64", "osx-arm64" ], From cb1e7f93bfedf3eea0f433caaa9a83c8c81e89da Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 11 Mar 2025 16:08:52 +0100 Subject: [PATCH 26/39] Address feedback --- build-tools/scripts/Ndk.projitems.in | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/build-tools/scripts/Ndk.projitems.in b/build-tools/scripts/Ndk.projitems.in index 82a451a5b87..e767b8c460f 100644 --- a/build-tools/scripts/Ndk.projitems.in +++ b/build-tools/scripts/Ndk.projitems.in @@ -58,22 +58,4 @@ True - - - - $(AndroidNdkApiLevel_ArmV8a) - $(AndroidNdkApiLevel_Arm64) - android-arm64 - - - - $(AndroidNdkApiLevel_X86_64) - $(AndroidNdkApiLevel_X64) - android-x64 - - From 17fb6e68f8fa0de537e682f424cc66c686f07cdb Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 11 Mar 2025 17:40:33 +0100 Subject: [PATCH 27/39] Hopefully fix a handful of tests --- .../Xamarin.Android.Build.Tests/BuildTest.cs | 16 +- .../Utilities/EnvironmentHelper.CoreCLR.cs | 207 ++++++++++++++++++ .../Utilities/EnvironmentHelper.cs | 23 +- .../Xamarin.Android.Build.Tests/XASdkTests.cs | 2 + .../Utilities/TargetRuntimeHelper.cs | 14 ++ 5 files changed, 254 insertions(+), 8 deletions(-) create mode 100644 src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.CoreCLR.cs diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index ecaf55817a6..f7ba70b3aa0 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -273,6 +273,7 @@ public void CheckMonoComponentsMask (bool enableProfiler, bool useInterpreter, b [Test] [TestCaseSource (nameof (CheckAssemblyCountsSource))] [NonParallelizable] + [Category ("CoreCLR")] public void CheckAssemblyCounts (bool isRelease, bool aot) { if (aot && TargetRuntimeHelper.UseCoreCLR) { @@ -294,8 +295,17 @@ public void CheckAssemblyCounts (bool isRelease, bool aot) string objPath = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath); List envFiles = EnvironmentHelper.GatherEnvironmentFiles (objPath, String.Join (";", abis), true); - EnvironmentHelper.ApplicationConfig app_config = EnvironmentHelper.ReadApplicationConfig (envFiles); - Assert.That (app_config, Is.Not.Null, "application_config must be present in the environment files"); + uint number_of_assemblies_in_apk; + + if (TargetRuntimeHelper.UseMonoRuntime) { + EnvironmentHelper.ApplicationConfig app_config = EnvironmentHelper.ReadApplicationConfig (envFiles); + Assert.That (app_config, Is.Not.Null, "(MonoVM) application_config must be present in the environment files"); + number_of_assemblies_in_apk = app_config.number_of_assemblies_in_apk; + } else { + EnvironmentHelper.ApplicationConfigCLR app_config = EnvironmentHelper.ReadApplicationConfigCLR (envFiles); + Assert.That (app_config, Is.Not.Null, "(CoreCLR) application_config must be present in the environment files"); + number_of_assemblies_in_apk = app_config.number_of_assemblies_in_apk; + } if (aot) { foreach (var env in envFiles) { @@ -309,7 +319,7 @@ public void CheckAssemblyCounts (bool isRelease, bool aot) foreach (string abi in abis) { AndroidTargetArch arch = MonoAndroidHelper.AbiToTargetArch (abi); Assert.AreEqual ( - app_config.number_of_assemblies_in_apk, + number_of_assemblies_in_apk, helper.GetNumberOfAssemblies (arch: arch), $"Assembly count must be equal between ApplicationConfig and the archive contents for architecture {arch} (ABI: {abi})" ); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.CoreCLR.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.CoreCLR.cs new file mode 100644 index 00000000000..874785b5dc3 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.CoreCLR.cs @@ -0,0 +1,207 @@ +using System; +using System.Collections.Generic; + +using NUnit.Framework; +namespace Xamarin.Android.Build.Tests; + +partial class EnvironmentHelper +{ + // This must be identical to the like-named structure in src/native/clr/include/xamarin-app.hh + public sealed class ApplicationConfigCLR + { + public bool uses_assembly_preload; + public bool jni_add_native_method_registration_attribute_present; + public bool marshal_methods_enabled; + public bool ignore_split_configs; + public uint number_of_runtime_properties; + public uint package_naming_policy; + public uint environment_variable_count; + public uint system_property_count; + public uint number_of_assemblies_in_apk; + public uint bundled_assembly_name_width; + public uint number_of_dso_cache_entries; + public uint number_of_aot_cache_entries; + public uint number_of_shared_libraries; + public uint android_runtime_jnienv_class_token; + public uint jnienv_initialize_method_token; + public uint jnienv_registerjninatives_method_token; + public uint jni_remapping_replacement_type_count; + public uint jni_remapping_replacement_method_index_entry_count; + public string android_package_name = String.Empty; + public bool managed_marshal_methods_lookup_enabled; + } + + const uint ApplicationConfigFieldCountCLR = 20; + + static readonly string[] requiredSharedLibrarySymbolsCLR = { + "app_system_properties", + "init_runtime_property_names", + "init_runtime_property_values", + "java_to_managed_hashes", + "java_to_managed_map", + "java_type_count", + "java_type_names", + "managed_to_java_map", + "managed_to_java_map_module_count", + AppEnvironmentVariablesSymbolName, + ApplicationConfigSymbolName, + }; + + // Reads all the environment files, makes sure they all have identical contents in the + // `application_config` structure and returns the config if the condition is true + public static ApplicationConfigCLR? ReadApplicationConfigCLR (List envFilePaths) + { + if (envFilePaths.Count == 0) { + return null; + } + + ApplicationConfigCLR app_config = ReadApplicationConfigCLR (envFilePaths [0]); + + for (int i = 1; i < envFilePaths.Count; i++) { + AssertApplicationConfigIsIdentical (app_config, envFilePaths [0].Path, ReadApplicationConfigCLR (envFilePaths[i]), envFilePaths[i].Path); + } + + return app_config; + } + + static ApplicationConfigCLR? ReadApplicationConfigCLR (EnvironmentFile envFile) + { + (NativeAssemblyParser parser, NativeAssemblyParser.AssemblerSymbol appConfigSymbol) = GetAssemblyParserAndValidateConfig (envFile); + + var pointers = new List (); + var ret = new ApplicationConfigCLR (); + uint fieldCount = 0; + string[] field; + + foreach (NativeAssemblyParser.AssemblerSymbolItem item in appConfigSymbol.Contents) { + field = GetField (envFile.Path, parser.SourceFilePath, item.Contents, item.LineNumber); + + if (CanIgnoreAssemblerField (field[0])) { + continue; + } + + switch (fieldCount) { + case 0: // uses_assembly_preload: bool / .byte + AssertFieldType (envFile.Path, parser.SourceFilePath, ".byte", field [0], item.LineNumber); + ret.uses_assembly_preload = ConvertFieldToBool ("uses_assembly_preload", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 1: // jni_add_native_method_registration_attribute_present: bool / .byte + AssertFieldType (envFile.Path, parser.SourceFilePath, ".byte", field [0], item.LineNumber); + ret.jni_add_native_method_registration_attribute_present = ConvertFieldToBool ("jni_add_native_method_registration_attribute_present", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 2: // marshal_methods_enabled: bool / .byte + AssertFieldType (envFile.Path, parser.SourceFilePath, ".byte", field [0], item.LineNumber); + ret.marshal_methods_enabled = ConvertFieldToBool ("marshal_methods_enabled", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 3: // ignore_split_configs: bool / .byte + AssertFieldType (envFile.Path, parser.SourceFilePath, ".byte", field [0], item.LineNumber); + ret.ignore_split_configs = ConvertFieldToBool ("ignore_split_configs", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 4: // number_of_runtime_properties: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.number_of_runtime_properties = ConvertFieldToUInt32 ("number_of_runtime_properties", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 5: // package_naming_policy: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.package_naming_policy = ConvertFieldToUInt32 ("package_naming_policy", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 6: // environment_variable_count: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.environment_variable_count = ConvertFieldToUInt32 ("environment_variable_count", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 7: // system_property_count: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.system_property_count = ConvertFieldToUInt32 ("system_property_count", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 8: // number_of_assemblies_in_apk: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.number_of_assemblies_in_apk = ConvertFieldToUInt32 ("number_of_assemblies_in_apk", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 9: // bundled_assembly_name_width: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.bundled_assembly_name_width = ConvertFieldToUInt32 ("bundled_assembly_name_width", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 10: // number_of_dso_cache_entries: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.number_of_dso_cache_entries = ConvertFieldToUInt32 ("number_of_dso_cache_entries", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 11: // number_of_aot_cache_entries: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.number_of_aot_cache_entries = ConvertFieldToUInt32 ("number_of_aot_cache_entries", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 12: // number_of_shared_libraries: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.number_of_shared_libraries = ConvertFieldToUInt32 ("number_of_shared_libraries", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 13: // android_runtime_jnienv_class_token: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.android_runtime_jnienv_class_token = ConvertFieldToUInt32 ("android_runtime_jnienv_class_token", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 14: // jnienv_initialize_method_token: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.jnienv_initialize_method_token = ConvertFieldToUInt32 ("jnienv_initialize_method_token", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 15: // jnienv_registerjninatives_method_token: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.jnienv_registerjninatives_method_token = ConvertFieldToUInt32 ("jnienv_registerjninatives_method_token", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 16: // jni_remapping_replacement_type_count: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.jni_remapping_replacement_type_count = ConvertFieldToUInt32 ("jni_remapping_replacement_type_count", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 17: // jni_remapping_replacement_method_index_entry_count: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.jni_remapping_replacement_method_index_entry_count = ConvertFieldToUInt32 ("jni_remapping_replacement_method_index_entry_count", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 18: // android_package_name: string / [pointer type] + Assert.IsTrue (expectedPointerTypes.Contains (field [0]), $"Unexpected pointer field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + pointers.Add (field [1].Trim ()); + break; + + case 19: // managed_marshal_methods_lookup_enabled: bool / .byte + AssertFieldType (envFile.Path, parser.SourceFilePath, ".byte", field [0], item.LineNumber); + ret.managed_marshal_methods_lookup_enabled = ConvertFieldToBool ("managed_marshal_methods_lookup_enabled", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + } + fieldCount++; + } + + Assert.AreEqual (1, pointers.Count, $"Invalid number of string pointers in 'application_config' structure in environment file '{envFile.Path}'"); + + NativeAssemblyParser.AssemblerSymbol androidPackageNameSymbol = GetRequiredSymbol (pointers[0], envFile, parser); + ret.android_package_name = GetStringContents (androidPackageNameSymbol, envFile, parser); + + Assert.AreEqual (ApplicationConfigFieldCountCLR, fieldCount, $"Invalid 'application_config' field count in environment file '{envFile.Path}'"); + Assert.IsFalse (String.IsNullOrEmpty (ret.android_package_name), $"Package name field in 'application_config' in environment file '{envFile.Path}' must not be null or empty"); + + return ret; + } + + static void AssertApplicationConfigIsIdentical (ApplicationConfigCLR firstAppConfig, string firstEnvFile, ApplicationConfigCLR secondAppConfig, string secondEnvFile) + { + Assert.AreEqual (firstAppConfig.uses_assembly_preload, secondAppConfig.uses_assembly_preload, $"Field 'uses_assembly_preload' has different value in environment file '{secondEnvFile}' than in environment file '{firstEnvFile}'"); + Assert.AreEqual (firstAppConfig.marshal_methods_enabled, secondAppConfig.marshal_methods_enabled, $"Field 'marshal_methods_enabled' has different value in environment file '{secondEnvFile}' than in environment file '{firstEnvFile}'"); + Assert.AreEqual (firstAppConfig.environment_variable_count, secondAppConfig.environment_variable_count, $"Field 'environment_variable_count' has different value in environment file '{secondEnvFile}' than in environment file '{firstEnvFile}'"); + Assert.AreEqual (firstAppConfig.system_property_count, secondAppConfig.system_property_count, $"Field 'system_property_count' has different value in environment file '{secondEnvFile}' than in environment file '{firstEnvFile}'"); + Assert.AreEqual (firstAppConfig.android_package_name, secondAppConfig.android_package_name, $"Field 'android_package_name' has different value in environment file '{secondEnvFile}' than in environment file '{firstEnvFile}'"); + Assert.AreEqual (firstAppConfig.managed_marshal_methods_lookup_enabled, secondAppConfig.managed_marshal_methods_lookup_enabled, $"Field 'managed_marshal_methods_lookup_enabled' has different value in environment file '{secondEnvFile}' than in environment file '{firstEnvFile}'"); + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs index 7a86601ce43..840217ff502 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs @@ -14,7 +14,7 @@ namespace Xamarin.Android.Build.Tests { - class EnvironmentHelper + partial class EnvironmentHelper { public sealed class EnvironmentFile { @@ -36,7 +36,7 @@ public EnvironmentFile (string path, string abi) } } - // This must be identical to the like-named structure in src/native/xamarin-app-stub/xamarin-app.hh + // This must be identical to the like-named structure in src/native/mono/xamarin-app-stub/xamarin-app.hh public sealed class ApplicationConfig { public bool uses_mono_llvm; @@ -183,7 +183,7 @@ public static ApplicationConfig ReadApplicationConfig (List env return app_config; } - static ApplicationConfig ReadApplicationConfig (EnvironmentFile envFile) + static (NativeAssemblyParser parser, NativeAssemblyParser.AssemblerSymbol appConfigSymbol) GetAssemblyParserAndValidateConfig (EnvironmentFile envFile) { NativeAssemblyParser parser = CreateAssemblyParser (envFile); @@ -193,6 +193,19 @@ static ApplicationConfig ReadApplicationConfig (EnvironmentFile envFile) Assert.IsTrue (appConfigSymbol.Size != 0, $"{ApplicationConfigSymbolName} size as specified in the '.size' directive must not be 0"); + return (parser, appConfigSymbol); + } + + static bool CanIgnoreAssemblerField (string field) + { + // padding, we can safely ignore it + return String.Compare (".zero", field, StringComparison.Ordinal) == 0; + } + + static ApplicationConfig ReadApplicationConfig (EnvironmentFile envFile) + { + (NativeAssemblyParser parser, NativeAssemblyParser.AssemblerSymbol appConfigSymbol) = GetAssemblyParserAndValidateConfig (envFile); + var pointers = new List (); var ret = new ApplicationConfig (); uint fieldCount = 0; @@ -201,8 +214,8 @@ static ApplicationConfig ReadApplicationConfig (EnvironmentFile envFile) foreach (NativeAssemblyParser.AssemblerSymbolItem item in appConfigSymbol.Contents) { field = GetField (envFile.Path, parser.SourceFilePath, item.Contents, item.LineNumber); - if (String.Compare (".zero", field[0], StringComparison.Ordinal) == 0) { - continue; // padding, we can safely ignore it + if (CanIgnoreAssemblerField (field[0])) { + continue; } switch (fieldCount) { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs index e42604073e3..77d0a3ef76b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs @@ -205,6 +205,8 @@ public void DotNetPublishDefaultValues([Values (false, true)] bool isRelease) [Test] public void DotNetPublish ([Values (false, true)] bool isRelease, [ValueSource(nameof(DotNetTargetFrameworks))] object[] data, [Values ("Mono", "CoreCLR")] string runtime) { + TargetRuntimeHelper.IgnoreOnIncompatibleRuntime (runtime); + var dotnetVersion = (string)data[0]; var platform = (string)data[1]; var apiLevel = (int)data[2]; diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs index d7fa3e185af..fdcc432b736 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; +using NUnit.Framework; using Xamarin.Android.Tasks; namespace Xamarin.ProjectTools; @@ -13,6 +14,8 @@ public class TargetRuntimeHelper static TargetRuntimeHelper () { + // TODO: this detection should probably depend on something more than an envvar. We can detect Mono + // by looking for one of the Mono-specific types, can we do something similar to detect NativeAOT? string? envvar = Environment.GetEnvironmentVariable ("USE_MONO_RUNTIME"); if (envvar == null || envvar.Length == 0 || String.Compare ("true", envvar, StringComparison.OrdinalIgnoreCase) == 0) { useMonoRuntime = true; @@ -63,4 +66,15 @@ public static bool CoreClrSupportsAllABIs (string abis) return true; } + + public static void IgnoreOnIncompatibleRuntime (string runtime) + { + if (UseCoreCLR && String.Compare (runtime, "CoreCLR", StringComparison.OrdinalIgnoreCase) != 0) { + Assert.Ignore ($"{runtime} tests not supported under CoreCLR"); + } + + if (UseMonoRuntime && String.Compare (runtime, "Mono", StringComparison.OrdinalIgnoreCase) != 0) { + Assert.Ignore ($"{runtime} tests not supported under MonoVM"); + } + } } From 31b4aff71b850ab385cba661bf1094eff9c3eff9 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 11 Mar 2025 17:59:44 +0100 Subject: [PATCH 28/39] Another portion of fixes, hopefully --- .../Tests/Xamarin.Android.Build.Tests/BuildTest.cs | 5 +++++ .../IncrementalBuildTest.cs | 13 +++++++------ .../Utilities/AssertionExtensions.cs | 10 ++++++++-- .../Utilities/EnvironmentHelper.cs | 13 +++++++++++-- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index f7ba70b3aa0..5ca82acd550 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -357,6 +357,11 @@ public static string GetLinkedPath (ProjectBuilder builder, bool isRelease, stri [Test] [TestCaseSource (nameof (RuntimeChecks))] public void CheckWhichRuntimeIsIncluded (string supportedAbi, bool debugSymbols, bool? optimize, bool? embedAssemblies, string expectedRuntime) { + + if (TargetRuntimeHelper.UseCoreCLR && !TargetRuntimeHelper.CoreClrSupportsAllABIs (supportedAbi)) { + Assert.Ignore ($"ABI '{supportedAbi}' not supported on CoreCLR"); + } + var proj = new XamarinAndroidApplicationProject (); proj.SetAndroidSupportedAbis (supportedAbi); proj.SetProperty (proj.ActiveConfigurationProperties, "DebugSymbols", debugSymbols); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs index 91e399f4bb6..61d28247a59 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs @@ -983,6 +983,7 @@ public void CasingOnJavaLangObject () } [Test] + [Category ("CoreCLR")] public void GenerateJavaStubsAndAssembly ([Values (true, false)] bool isRelease) { var targets = new [] { @@ -992,7 +993,7 @@ public void GenerateJavaStubsAndAssembly ([Values (true, false)] bool isRelease) var proj = new XamarinAndroidApplicationProject { IsRelease = isRelease, }; - proj.SetAndroidSupportedAbis ("armeabi-v7a"); + proj.SetAndroidSupportedAbis ("arm64-v8a"); proj.OtherBuildItems.Add (new AndroidItem.AndroidEnvironment ("Foo.txt") { TextContent = () => "Foo=Bar", }); @@ -1024,11 +1025,11 @@ public void GenerateJavaStubsAndAssembly ([Values (true, false)] bool isRelease) } readonly string [] ExpectedAssemblyFiles = new [] { - Path.Combine ("android", "environment.armeabi-v7a.o"), - Path.Combine ("android", "environment.armeabi-v7a.ll"), - Path.Combine ("android", "typemaps.armeabi-v7a.o"), - Path.Combine ("android", "typemaps.armeabi-v7a.ll"), - Path.Combine ("app_shared_libraries", "armeabi-v7a", "libxamarin-app.so") + Path.Combine ("android", "environment.arm64-v8a.o"), + Path.Combine ("android", "environment.arm64-v8a.ll"), + Path.Combine ("android", "typemaps.arm64-v8a.o"), + Path.Combine ("android", "typemaps.arm64-v8a.ll"), + Path.Combine ("app_shared_libraries", "arm64-v8a", "libxamarin-app.so") }; void AssertAssemblyFilesInFileWrites (XamarinAndroidApplicationProject proj, ProjectBuilder b) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/AssertionExtensions.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/AssertionExtensions.cs index f4a4db9ad71..357634b2fb9 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/AssertionExtensions.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/AssertionExtensions.cs @@ -129,8 +129,14 @@ public static void AssertEntryContents (this ZipArchive zip, string zipPath, str static void AllowCoreCLRWarning (IEnumerable lastBuildOutput, string logFile) { // With CoreCLR being experimental, we allow a single warning (XA1040) - Assert.IsTrue (StringAssertEx.ContainsText (lastBuildOutput, " 1 Warning(s)"), $"{logFile} should have at most 1 MSBuild warning."); - Assert.True (StringAssertEx.ContainsText (lastBuildOutput, "XA1040"), "Should receive XA1040 warning"); + // Library builds won't have warnings, though, so we must account for that too. + bool hasNoWarnings = StringAssertEx.ContainsText (lastBuildOutput, " 0 Warning(s)"); + bool hasOneWarning = StringAssertEx.ContainsText (lastBuildOutput, " 1 Warning(s)"); + + Assert.IsTrue (hasNoWarnings || hasOneWarning, $"{logFile} should have at most 1 MSBuild warning."); + if (hasOneWarning) { + Assert.True (StringAssertEx.ContainsText (lastBuildOutput, "XA1040"), "Should receive XA1040 warning"); + } } [DebuggerHidden] diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs index 840217ff502..602996ddd99 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs @@ -534,8 +534,17 @@ static void AssertSharedLibraryHasRequiredSymbols (string dsoPath, string readEl symbols.Add (symbolName); } - foreach (string symbol in requiredSharedLibrarySymbols) { - Assert.IsTrue (symbols.Contains (symbol), $"Symbol '{symbol}' is missing from '{dsoPath}'"); + if (TargetRuntimeHelper.UseMonoRuntime) { + EnsureSymbols (requiredSharedLibrarySymbols); + } else if (TargetRuntimeHelper.UseCoreCLR) { + EnsureSymbols (requiredSharedLibrarySymbolsCLR); + } + + void EnsureSymbols (IEnumerable requiredSymbols) + { + foreach (string symbol in requiredSymbols) { + Assert.IsTrue (symbols.Contains (symbol), $"Symbol '{symbol}' is missing from '{dsoPath}'"); + } } } From fb47b4f3a30b66c0e3ecd16fafe698cda93a0b3f Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 12 Mar 2025 15:01:10 +0100 Subject: [PATCH 29/39] Fix artifact names + some more test fixes --- .../automation/yaml-templates/run-msbuild-tests.yaml | 2 +- build-tools/automation/yaml-templates/variables.yaml | 2 ++ .../Tests/Xamarin.Android.Build.Tests/BuildTest.cs | 6 +++--- .../Tests/Xamarin.Android.Build.Tests/BuildTest2.cs | 6 ++++-- .../BuildWithLibraryTests.cs | 2 +- .../IncrementalBuildTest.cs | 11 ++++++++--- .../Xamarin.Android.Build.Tests/PackagingTest.cs | 4 ++-- .../Utilities/TargetRuntimeHelper.cs | 1 + .../Utilities/ApplicationConfig.cs | 2 +- .../Utilities/ApplicationConfigCLR.cs | 2 +- 10 files changed, 24 insertions(+), 14 deletions(-) diff --git a/build-tools/automation/yaml-templates/run-msbuild-tests.yaml b/build-tools/automation/yaml-templates/run-msbuild-tests.yaml index 4ca12ca5214..760a8377080 100644 --- a/build-tools/automation/yaml-templates/run-msbuild-tests.yaml +++ b/build-tools/automation/yaml-templates/run-msbuild-tests.yaml @@ -62,7 +62,7 @@ jobs: - template: /build-tools/automation/yaml-templates/upload-results.yaml parameters: - artifactName: Test Results - MSBuild - ${{ parameters.testOS }}-${{ parameters.runtimeName }} + artifactName: Test Results - MSBuild - ${{ parameters.testOS }}-${{ parameters.runtimeName }}-$(System.JobPositionInPhase) xaSourcePath: ${{ parameters.xaSourcePath }} use1ESTemplate: ${{ parameters.use1ESTemplate }} diff --git a/build-tools/automation/yaml-templates/variables.yaml b/build-tools/automation/yaml-templates/variables.yaml index f01382d246f..33f35c6621a 100644 --- a/build-tools/automation/yaml-templates/variables.yaml +++ b/build-tools/automation/yaml-templates/variables.yaml @@ -68,3 +68,5 @@ variables: value: 'cat != SystemApplication & cat != TimeZoneInfo & cat != Localization' - name: RunMAUITestJob value: true +- name: CoreCLRExcludedNunitCategories + value: 'cat != AOT' diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index 5ca82acd550..fc10c758b0f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -1406,21 +1406,21 @@ public void NUnitLiteNugetWorks () /* enableProguard */ null, /* androidEnableProguard */ "true", /* expectedBuildResult */ true, - /* expectedWarning */ "0 Warning(s)", + /* expectedWarning */ TargetRuntimeHelper.UseCoreCLR && TargetRuntimeHelper.CoreClrIsExperimental ? "1 Warning(s)" : "0 Warning(s)", }, new object [] { /* linkTool */ "proguard", /* enableProguard */ null, /* androidEnableProguard */ "true", /* expectedBuildResult */ false, - /* expectedWarning */ "0 Warning(s)", + /* expectedWarning */ TargetRuntimeHelper.UseCoreCLR && TargetRuntimeHelper.CoreClrIsExperimental ? "1 Warning(s)" : "0 Warning(s)", }, new object [] { /* linkTool */ null, /* enableProguard */ null, /* androidEnableProguard */ null, /* expectedBuildResult */ true, - /* expectedWarning */ "0 Warning(s)", + /* expectedWarning */ TargetRuntimeHelper.UseCoreCLR && TargetRuntimeHelper.CoreClrIsExperimental ? "1 Warning(s)" : "0 Warning(s)", }, new object [] { /* linkTool */ null, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index c6a8e68a401..80774487b6f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -427,12 +427,14 @@ public void BuildHasTrimmerWarnings (string properties, string [] codes, bool is var proj = new XamarinAndroidApplicationProject { IsRelease = isRelease, }; - if (totalWarnings != null && TargetRuntimeHelper.UseCoreCLR && TargetRuntimeHelper.CoreClrIsExperimental) { + if (TargetRuntimeHelper.UseCoreCLR && TargetRuntimeHelper.CoreClrIsExperimental) { // Experimental runtimes will issue warning XA1040 - totalWarnings++; var newCodes = new List (codes); newCodes.Add ("XA1040"); codes = newCodes.ToArray (); + if (totalWarnings != null) { + totalWarnings++; + } } proj.SetRuntimeIdentifier ("arm64-v8a"); proj.MainActivity = proj.DefaultMainActivity diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs index b911192418f..e967144af0c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs @@ -456,7 +456,7 @@ public void BuildWithNativeLibraryUnknownAbi () }, } }; - proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86"); + proj.SetAndroidSupportedAbis ("arm64-v8a", "x64"); using (var builder = CreateApkBuilder (Path.Combine ("temp", TestName))) { builder.ThrowOnBuildFailure = false; diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs index 61d28247a59..56163923301 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs @@ -1307,10 +1307,15 @@ public void MissingProjectReference () libBuilder.ThrowOnBuildFailure = appBuilder.ThrowOnBuildFailure = false; + int expectedWarnings = 1; + if (TargetRuntimeHelper.UseCoreCLR && TargetRuntimeHelper.CoreClrIsExperimental) { + expectedWarnings++; // Warning XA1040 will be issued + } + // Build app before library is built Assert.IsFalse (appBuilder.Build (app), "app build should have failed."); Assert.IsTrue (StringAssertEx.ContainsText (appBuilder.LastBuildOutput, "warning MSB9008"), "Should receive MSB9008"); - Assert.IsTrue (StringAssertEx.ContainsText (appBuilder.LastBuildOutput, " 1 Warning(s)"), "Should receive 1 Warning"); + Assert.IsTrue (StringAssertEx.ContainsText (appBuilder.LastBuildOutput, $" {expectedWarnings} Warning(s)"), $"Should receive {expectedWarnings} Warning(s)"); Assert.IsTrue (StringAssertEx.ContainsText (appBuilder.LastBuildOutput, "error CS0246"), "Should receive CS0246"); Assert.IsTrue (StringAssertEx.ContainsText (appBuilder.LastBuildOutput, " 1 Error(s)"), "Should receive 1 Error"); @@ -1435,10 +1440,10 @@ public void AndroidAssetMissing () public void ChangeSupportedAbis () { var proj = new XamarinFormsAndroidApplicationProject (); - proj.SetAndroidSupportedAbis ("armeabi-v7a"); + proj.SetAndroidSupportedAbis ("arm64-v8a"); using (var b = CreateApkBuilder ()) { b.Build (proj); - b.Build (proj, parameters: new [] { $"{KnownProperties.RuntimeIdentifier}=android-x86" }, doNotCleanupOnUpdate: true); + b.Build (proj, parameters: new [] { $"{KnownProperties.RuntimeIdentifier}=android-x64" }, doNotCleanupOnUpdate: true); } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs index 82c9e2f8152..9677fd9a203 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs @@ -415,8 +415,8 @@ public void CheckSignApk ([Values(true, false)] bool useApkSigner, [Values(true, // Make sure the APKs have unique version codes if (perAbiApk) { - int armManifestCode = GetVersionCodeFromIntermediateManifest (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "armeabi-v7a", "AndroidManifest.xml")); - int x86ManifestCode = GetVersionCodeFromIntermediateManifest (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "x86", "AndroidManifest.xml")); + int armManifestCode = thirtyTwoBitAbisSupported ? GetVersionCodeFromIntermediateManifest (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "armeabi-v7a", "AndroidManifest.xml")) : 0; + int x86ManifestCode = thirtyTwoBitAbisSupported ? GetVersionCodeFromIntermediateManifest (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "x86", "AndroidManifest.xml")) : 0; int arm64ManifestCode = GetVersionCodeFromIntermediateManifest (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "arm64-v8a", "AndroidManifest.xml")); int x86_64ManifestCode = GetVersionCodeFromIntermediateManifest (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "x86_64", "AndroidManifest.xml")); List versionList; diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs index fdcc432b736..4754286180f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs @@ -32,6 +32,7 @@ static TargetRuntimeHelper () public static bool UseMonoRuntime => useMonoRuntime; public static bool UseCoreCLR => !useMonoRuntime; public static string[] CoreClrSupportedAbis => coreClrSupportedAbis; + public string RuntimeName => UseMonoRuntime ? "MonoVM" : "CoreCLR"; public static bool CoreClrSupportsAbi (string abiName) => coreClrAbis.Contains (abiName); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs index 40ea29ee665..4fc992a49f4 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs @@ -3,7 +3,7 @@ namespace Xamarin.Android.Tasks { // Declaration order of fields and their types must correspond *exactly* to that in - // src/native/xamarin-app-stub/xamarin-app.hh ApplicationConfig structure + // src/native/mono/xamarin-app-stub/xamarin-app.hh ApplicationConfig structure // // Type mappings: // diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs index 0efed3ccc3c..9f9c46b3b45 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs @@ -3,7 +3,7 @@ namespace Xamarin.Android.Tasks; // Declaration order of fields and their types must correspond *exactly* to that in -// src/native/clr/xamarin-app-stub/xamarin-app.hh ApplicationConfig structure +// src/native/clr/include/xamarin-app.hh ApplicationConfig structure // // Type mappings: // From 424141d02b643b123c0701c060866347eb33eb4b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 12 Mar 2025 17:23:57 +0100 Subject: [PATCH 30/39] More fixes and fixlets --- .../Xamarin.Android.Build.Tests/BuildTest.cs | 6 ++++- .../Xamarin.Android.Build.Tests/BuildTest2.cs | 2 ++ .../BuildWithLibraryTests.cs | 2 +- .../InvalidConfigTests.cs | 2 ++ .../PackagingTest.cs | 4 ++++ .../Tasks/LinkerTests.cs | 22 ++++++++++++++++--- .../Utilities/TargetRuntimeHelper.cs | 7 ++++++ 7 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index fc10c758b0f..1fa9c6403d4 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -99,6 +99,10 @@ public void DotNetBuild (string runtimeIdentifiers, bool isRelease, bool aot, bo }); if (!runtimeIdentifiers.Contains (";")) { proj.SetProperty (KnownProperties.RuntimeIdentifier, runtimeIdentifiers); + + // When targeting CoreCLR, XamarinAndroidApplicationProject sets `RuntimeIdentifiers` to make sure that only 64-bit + // targets are built. It interferes with this test when `RuntimeIdentifier` is set. + proj.RemoveProperty (KnownProperties.RuntimeIdentifiers); } else { proj.SetProperty (KnownProperties.RuntimeIdentifiers, runtimeIdentifiers); } @@ -1701,7 +1705,7 @@ public void SimilarAndroidXAssemblyNames ([Values(true, false)] bool publishTrim { var proj = new XamarinAndroidApplicationProject { IsRelease = true, - AotAssemblies = publishTrimmed, + AotAssemblies = publishTrimmed && !TargetRuntimeHelper.UseCoreCLR, PackageReferences = { new Package { Id = "Xamarin.AndroidX.CustomView", Version = "1.1.0.17" }, new Package { Id = "Xamarin.AndroidX.CustomView.PoolingContainer", Version = "1.0.0.4" }, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index 80774487b6f..1651c915be7 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -585,6 +585,8 @@ static void Test () [NonParallelizable] // parallel NuGet restore causes failures public void BuildBasicApplicationFSharp (bool isRelease, bool aot) { + TargetRuntimeHelper.IgnoreIfIncompatibleWithMonoAOT (aot); + var proj = new XamarinAndroidApplicationProject { Language = XamarinAndroidProjectLanguage.FSharp, IsRelease = isRelease, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs index e967144af0c..2c67dbfb78f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs @@ -456,7 +456,7 @@ public void BuildWithNativeLibraryUnknownAbi () }, } }; - proj.SetAndroidSupportedAbis ("arm64-v8a", "x64"); + proj.SetAndroidSupportedAbis ("arm64-v8a", "x86_64"); using (var builder = CreateApkBuilder (Path.Combine ("temp", TestName))) { builder.ThrowOnBuildFailure = false; diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/InvalidConfigTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/InvalidConfigTests.cs index 9b3e3c34d30..ac0c3a42930 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/InvalidConfigTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/InvalidConfigTests.cs @@ -45,6 +45,8 @@ public class InvalidConfigTests : BaseTest [TestCaseSource (nameof (SettingCombinationsSource))] public void SettingCombinations (bool isRelease, bool useInterpreter, bool publishTrimmed, bool aot, bool expected) { + TargetRuntimeHelper.IgnoreIfIncompatibleWithMonoAOT (aot); + var proj = new XamarinAndroidApplicationProject { IsRelease = isRelease, EnableDefaultItems = true, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs index 9677fd9a203..ca5df45955e 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs @@ -85,6 +85,10 @@ public void CheckDebugModeWithTrimming () [NonParallelizable] // Commonly fails NuGet restore public void CheckIncludedAssemblies ([Values (false, true)] bool usesAssemblyStores) { + if (!usesAssemblyStores && TargetRuntimeHelper.UseCoreCLR) { + Assert.Ignore ("CoreCLR supports only assembly stores"); + } + var proj = new XamarinAndroidApplicationProject { IsRelease = true }; diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs index 035fca0f5c5..20d5c24643c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -649,7 +650,18 @@ public abstract class MyRunner { }" }); var proj = new XamarinAndroidApplicationProject { IsRelease = true, ProjectName = "App1" }; - proj.SetRuntimeIdentifiers(["armeabi-v7a", "arm64-v8a", "x86", "x86_64"]); + + bool thirtyTwoBitAbisSupported = + !TargetRuntimeHelper.UseCoreCLR || + (TargetRuntimeHelper.CoreClrSupportsAbi ("armeabi-v7a") && TargetRuntimeHelper.CoreClrSupportsAbi ("x86")); + + var rids = new List { "arm64-v8a", "x86_64" }; + if (thirtyTwoBitAbisSupported) { + rids.Add ("armeabi-v7a"); + rids.Add ("x86"); + } + + proj.SetRuntimeIdentifiers (rids); proj.References.Add(new BuildItem.ProjectReference (Path.Combine ("..", "Lib1", "Lib1.csproj"), "Lib1")); proj.MainActivity = proj.DefaultMainActivity.Replace ( "base.OnCreate (bundle);", @@ -665,11 +677,15 @@ public abstract class MyRunner { var intermediate = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath); var dll = $"{lib.ProjectName}.dll"; - Assert64Bit ("android-arm", expected64: false); + Assert64Bit ("android-arm64", expected64: true); - Assert64Bit ("android-x86", expected64: false); Assert64Bit ("android-x64", expected64: true); + if (thirtyTwoBitAbisSupported) { + Assert64Bit ("android-arm", expected64: false); + Assert64Bit ("android-x86", expected64: false); + } + void Assert64Bit(string rid, bool expected64) { var assembly = AssemblyDefinition.ReadAssembly (Path.Combine (intermediate, rid, "linked", "shrunk", dll)); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs index 4754286180f..34f6643cc28 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/TargetRuntimeHelper.cs @@ -78,4 +78,11 @@ public static void IgnoreOnIncompatibleRuntime (string runtime) Assert.Ignore ($"{runtime} tests not supported under MonoVM"); } } + + public static void IgnoreIfIncompatibleWithMonoAOT (bool aot) + { + if (aot && UseCoreCLR) { + Assert.Ignore ("CoreCLR runtime doesn't support MonoVM-style AOT"); + } + } } From 5ad3eb74c404f15cfdba7d92ca692b22075eb1ec Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 13 Mar 2025 12:04:07 +0100 Subject: [PATCH 31/39] A few more steps forward --- build-tools/automation/azure-pipelines.yaml | 1 + .../yaml-templates/stage-msbuild-tests.yaml | 3 + .../Xamarin.Android.Build.Tests/BuildTest.cs | 12 ++-- .../BuildWithLibraryTests.cs | 52 +++++++-------- .../Xamarin.Android.Build.Tests/XASdkTests.cs | 2 +- .../Common/IShortFormProject.cs | 1 + .../BuildReleaseArm64SimpleDotNet.apkdesc | 66 +++++++++++++------ .../Utilities/AbiUtils.cs | 13 +--- .../Utilities/ProjectExtensions.cs | 62 ++++++++++++++--- .../Utilities/MonoAndroidHelper.Basic.cs | 14 ++++ 10 files changed, 155 insertions(+), 71 deletions(-) diff --git a/build-tools/automation/azure-pipelines.yaml b/build-tools/automation/azure-pipelines.yaml index 6ae6834e2e3..9d70bed1ac8 100644 --- a/build-tools/automation/azure-pipelines.yaml +++ b/build-tools/automation/azure-pipelines.yaml @@ -122,6 +122,7 @@ extends: - template: /build-tools/automation/yaml-templates/stage-msbuild-tests.yaml@self parameters: runtimeName: "CoreCLR" + testFilter: $(CoreCLRExcludedNunitCategories) - template: /build-tools/automation/yaml-templates/stage-msbuild-emulator-tests.yaml@self parameters: diff --git a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml index 71b341ca714..1d71487400e 100644 --- a/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml +++ b/build-tools/automation/yaml-templates/stage-msbuild-tests.yaml @@ -2,6 +2,7 @@ parameters: runtimeName: '' + testFilter: '' # Filter used to select tests (NUnit test selection language, not dotnet test filter language) stageName: msbuild_dotnet stageCondition: succeeded() dependsOn: mac_build @@ -22,6 +23,7 @@ stages: parameters: testOS: macOS runtimeName: ${{ parameters.runtimeName }} + testFilter: ${{ parameters.testFilter }} jobName: mac_msbuild_tests jobDisplayName: macOS > Tests > MSBuild agentCount: 10 @@ -35,6 +37,7 @@ stages: parameters: testOS: Windows runtimeName: ${{ parameters.runtimeName }} + testFilter: ${{ parameters.testFilter }} jobName: win_msbuild_tests jobDisplayName: Windows > Tests > MSBuild agentCount: 8 diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index 1fa9c6403d4..2c198d06b33 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -99,10 +99,6 @@ public void DotNetBuild (string runtimeIdentifiers, bool isRelease, bool aot, bo }); if (!runtimeIdentifiers.Contains (";")) { proj.SetProperty (KnownProperties.RuntimeIdentifier, runtimeIdentifiers); - - // When targeting CoreCLR, XamarinAndroidApplicationProject sets `RuntimeIdentifiers` to make sure that only 64-bit - // targets are built. It interferes with this test when `RuntimeIdentifier` is set. - proj.RemoveProperty (KnownProperties.RuntimeIdentifiers); } else { proj.SetProperty (KnownProperties.RuntimeIdentifiers, runtimeIdentifiers); } @@ -178,7 +174,13 @@ public void DotNetBuild (string runtimeIdentifiers, bool isRelease, bool aot, bo helper.AssertContainsEntry ($"assemblies/de-DE/{proj.ProjectName}.resources.dll", shouldContainEntry: expectEmbeddedAssembies); foreach (var abi in rids.Select (AndroidRidAbiHelper.RuntimeIdentifierToAbi)) { helper.AssertContainsEntry ($"lib/{abi}/libmonodroid.so"); - helper.AssertContainsEntry ($"lib/{abi}/libmonosgen-2.0.so"); + + if (TargetRuntimeHelper.UseCoreCLR) { + helper.AssertContainsEntry ($"lib/{abi}/libcoreclr.so"); + } else { + helper.AssertContainsEntry ($"lib/{abi}/libmonosgen-2.0.so"); + } + if (rids.Length > 1) { helper.AssertContainsEntry ($"assemblies/{abi}/System.Private.CoreLib.dll", shouldContainEntry: expectEmbeddedAssembies); } else { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs index 2c67dbfb78f..e7b3e70334a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs @@ -370,15 +370,15 @@ public void BuildWithNativeLibraries ([Values (true, false)] bool isRelease) ProjectName = "Library1", IsRelease = isRelease, OtherBuildItems = { - new AndroidItem.EmbeddedNativeLibrary ("foo\\armeabi-v7a\\libtest.so") { + new AndroidItem.EmbeddedNativeLibrary ("foo\\arm64-v8a\\libtest.so") { BinaryContent = () => new byte[10], - MetadataValues = "Link=libs\\armeabi-v7a\\libtest.so", + MetadataValues = "Link=libs\\arm64-v8a\\libtest.so", }, - new AndroidItem.EmbeddedNativeLibrary ("foo\\x86\\libtest.so") { + new AndroidItem.EmbeddedNativeLibrary ("foo\\x86_64\\libtest.so") { BinaryContent = () => new byte[10], - MetadataValues = "Link=libs\\x86\\libtest.so", + MetadataValues = "Link=libs\\x86_64\\libtest.so", }, - new AndroidItem.AndroidNativeLibrary ("armeabi-v7a\\libRSSupport.so") { + new AndroidItem.AndroidNativeLibrary ("arm64-v8a\\libRSSupport.so") { BinaryContent = () => new byte[10], }, }, @@ -390,13 +390,13 @@ public void BuildWithNativeLibraries ([Values (true, false)] bool isRelease) new BuildItem ("ProjectReference","..\\Library1\\Library1.csproj"), }, OtherBuildItems = { - new AndroidItem.EmbeddedNativeLibrary ("foo\\armeabi-v7a\\libtest1.so") { + new AndroidItem.EmbeddedNativeLibrary ("foo\\arm64-v8a\\libtest1.so") { BinaryContent = () => new byte[10], - MetadataValues = "Link=libs\\armeabi-v7a\\libtest1.so", + MetadataValues = "Link=libs\\arm64-v8a\\libtest1.so", }, - new AndroidItem.EmbeddedNativeLibrary ("foo\\x86\\libtest1.so") { + new AndroidItem.EmbeddedNativeLibrary ("foo\\x86_64\\libtest1.so") { BinaryContent = () => new byte[10], - MetadataValues = "Link=libs\\x86\\libtest1.so", + MetadataValues = "Link=libs\\x86_64\\libtest1.so", }, }, }; @@ -407,12 +407,12 @@ public void BuildWithNativeLibraries ([Values (true, false)] bool isRelease) new BuildItem ("ProjectReference","..\\Library2\\Library2.csproj"), }, OtherBuildItems = { - new AndroidItem.AndroidNativeLibrary ("armeabi-v7a\\libRSSupport.so") { + new AndroidItem.AndroidNativeLibrary ("arm64-v8a\\libRSSupport.so") { BinaryContent = () => new byte[10], }, } }; - proj.SetRuntimeIdentifiers (["armeabi-v7a", "x86"]); + proj.SetRuntimeIdentifiers (["arm64-v8a", "x86_64"]); var path = Path.Combine (Root, "temp", string.Format ("BuildWithNativeLibraries_{0}", isRelease)); using (var b1 = CreateDllBuilder (Path.Combine (path, dll2.ProjectName))) { Assert.IsTrue (b1.Build (dll2), "Build should have succeeded."); @@ -423,23 +423,23 @@ public void BuildWithNativeLibraries ([Values (true, false)] bool isRelease) var apk = Path.Combine (Root, builder.ProjectDirectory, proj.OutputPath, $"{proj.PackageName}-Signed.apk"); FileAssert.Exists (apk); - Assert.IsTrue (StringAssertEx.ContainsText (builder.LastBuildOutput, "warning XA4301: APK already contains the item lib/armeabi-v7a/libRSSupport.so; ignoring."), + Assert.IsTrue (StringAssertEx.ContainsText (builder.LastBuildOutput, "warning XA4301: APK already contains the item lib/arm64-v8a/libRSSupport.so; ignoring."), "warning about skipping libRSSupport.so should have been raised"); using (var zipFile = ZipHelper.OpenZip (apk)) { - var data = ZipHelper.ReadFileFromZip (zipFile, "lib/x86/libtest.so"); - Assert.IsNotNull (data, "libtest.so for x86 should exist in the apk."); - data = ZipHelper.ReadFileFromZip (zipFile, "lib/armeabi-v7a/libtest.so"); - Assert.IsNotNull (data, "libtest.so for armeabi-v7a should exist in the apk."); - data = ZipHelper.ReadFileFromZip (zipFile, "lib/x86/libtest1.so"); - Assert.IsNotNull (data, "libtest1.so for x86 should exist in the apk."); - data = ZipHelper.ReadFileFromZip (zipFile, "lib/armeabi-v7a/libtest1.so"); - Assert.IsNotNull (data, "libtest1.so for armeabi-v7a should exist in the apk."); - data = ZipHelper.ReadFileFromZip (zipFile, "lib/armeabi-v7a/libRSSupport.so"); - Assert.IsNotNull (data, "libRSSupport.so for armeabi-v7a should exist in the apk."); - data = ZipHelper.ReadFileFromZip (zipFile, "lib/x86/libSystem.Native.so"); - Assert.IsNotNull (data, "libSystem.Native.so for x86 should exist in the apk."); - data = ZipHelper.ReadFileFromZip (zipFile, "lib/armeabi-v7a/libSystem.Native.so"); - Assert.IsNotNull (data, "libSystem.Native.so for armeabi-v7a should exist in the apk."); + var data = ZipHelper.ReadFileFromZip (zipFile, "lib/x86_64/libtest.so"); + Assert.IsNotNull (data, "libtest.so for x86_64 should exist in the apk."); + data = ZipHelper.ReadFileFromZip (zipFile, "lib/arm64-v8a/libtest.so"); + Assert.IsNotNull (data, "libtest.so for arm64-v8a should exist in the apk."); + data = ZipHelper.ReadFileFromZip (zipFile, "lib/x86_64/libtest1.so"); + Assert.IsNotNull (data, "libtest1.so for x86_64 should exist in the apk."); + data = ZipHelper.ReadFileFromZip (zipFile, "lib/arm64-v8a/libtest1.so"); + Assert.IsNotNull (data, "libtest1.so for arm64-v8a should exist in the apk."); + data = ZipHelper.ReadFileFromZip (zipFile, "lib/arm64-v8a/libRSSupport.so"); + Assert.IsNotNull (data, "libRSSupport.so for arm64-v8a should exist in the apk."); + data = ZipHelper.ReadFileFromZip (zipFile, "lib/x86_64/libSystem.Native.so"); + Assert.IsNotNull (data, "libSystem.Native.so for x86_64 should exist in the apk."); + data = ZipHelper.ReadFileFromZip (zipFile, "lib/arm64-v8a/libSystem.Native.so"); + Assert.IsNotNull (data, "libSystem.Native.so for arm64-v8a should exist in the apk."); } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs index 77d0a3ef76b..4a24692c62f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs @@ -226,7 +226,7 @@ public void DotNetPublish ([Values (false, true)] bool isRelease, [ValueSource(n IsRelease = isRelease, EnableDefaultItems = true, }; - proj.SetProperty (KnownProperties.RuntimeIdentifier, runtimeIdentifier); + proj.SetRuntimeIdentifier (runtimeIdentifier); var preview = IsPreviewFrameworkVersion (targetFramework); if (preview) { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/IShortFormProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/IShortFormProject.cs index c1b27a070a1..1b38f33ba20 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/IShortFormProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/IShortFormProject.cs @@ -18,5 +18,6 @@ public interface IShortFormProject IList> ItemGroupList { get; } IList Imports { get; } void SetProperty (string name, string value, string condition = null); + bool RemoveProperty (string name); } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc index 0d09c5250f4..675da985b43 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc @@ -5,52 +5,76 @@ "Size": 3036 }, "classes.dex": { - "Size": 22484 + "Size": 22268 }, "lib/arm64-v8a/lib__Microsoft.Android.Resource.Designer.dll.so": { "Size": 18288 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { - "Size": 86688 + "Size": 91792 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 117712 + "Size": 119960 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 22384 + "Size": 23240 + }, + "lib/arm64-v8a/lib_System.Collections.Immutable.dll.so": { + "Size": 26432 }, "lib/arm64-v8a/lib_System.Console.dll.so": { - "Size": 24392 + "Size": 24416 + }, + "lib/arm64-v8a/lib_System.Diagnostics.StackTrace.dll.so": { + "Size": 22544 + }, + "lib/arm64-v8a/lib_System.IO.Compression.dll.so": { + "Size": 30624 + }, + "lib/arm64-v8a/lib_System.IO.MemoryMappedFiles.dll.so": { + "Size": 32664 }, "lib/arm64-v8a/lib_System.Linq.dll.so": { - "Size": 25336 + "Size": 25464 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 628216 + "Size": 827080 + }, + "lib/arm64-v8a/lib_System.Reflection.Metadata.dll.so": { + "Size": 65952 }, "lib/arm64-v8a/lib_System.Runtime.dll.so": { - "Size": 20056 + "Size": 20088 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 21480 + "Size": 21496 }, "lib/arm64-v8a/lib_UnnamedProject.dll.so": { "Size": 20024 }, - "lib/arm64-v8a/libarc.bin.so": { - "Size": 18872 + "lib/arm64-v8a/libclrgc.so": { + "Size": 972344 + }, + "lib/arm64-v8a/libclrgcexp.so": { + "Size": 1025664 }, - "lib/arm64-v8a/libmono-component-marshal-ilgen.so": { - "Size": 36440 + "lib/arm64-v8a/libclrjit.so": { + "Size": 3088992 + }, + "lib/arm64-v8a/libcoreclr.so": { + "Size": 6649000 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 1524752 + "Size": 1216032 + }, + "lib/arm64-v8a/libmscordaccore.so": { + "Size": 2708168 }, - "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3101112 + "lib/arm64-v8a/libmscordbi.so": { + "Size": 1946872 }, "lib/arm64-v8a/libSystem.Globalization.Native.so": { - "Size": 71976 + "Size": 71952 }, "lib/arm64-v8a/libSystem.IO.Compression.Native.so": { "Size": 758896 @@ -62,16 +86,16 @@ "Size": 165000 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 19536 + "Size": 30560 }, "META-INF/BNDLTOOL.RSA": { "Size": 1221 }, "META-INF/BNDLTOOL.SF": { - "Size": 3266 + "Size": 4157 }, "META-INF/MANIFEST.MF": { - "Size": 3139 + "Size": 4030 }, "res/drawable-hdpi-v4/icon.png": { "Size": 2178 @@ -98,5 +122,5 @@ "Size": 1904 } }, - "PackageSize": 3078677 + "PackageSize": 8490176 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/AbiUtils.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/AbiUtils.cs index 5873229dff2..5dc9e4cc607 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/AbiUtils.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/AbiUtils.cs @@ -1,21 +1,14 @@ using System; +using Xamarin.Android.Tasks; + namespace Xamarin.ProjectTools { public static class AbiUtils { public static string AbiToRuntimeIdentifier (string androidAbi) { - if (androidAbi == "armeabi-v7a") { - return "android-arm"; - } else if (androidAbi == "arm64-v8a") { - return "android-arm64"; - } else if (androidAbi == "x86") { - return "android-x86"; - } else if (androidAbi == "x86_64") { - return "android-x64"; - } - throw new InvalidOperationException ($"Unknown abi: {androidAbi}"); + return MonoAndroidHelper.AbiToRidMaybe (androidAbi); } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/ProjectExtensions.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/ProjectExtensions.cs index 9492df1738c..e9a729b3ae1 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/ProjectExtensions.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/ProjectExtensions.cs @@ -10,39 +10,76 @@ namespace Xamarin.ProjectTools public static class ProjectExtensions { /// - /// Sets $(AndroidSupportedAbis) or $(RuntimeIdentifiers) depending if running under dotnet + /// Sets $(AndroidSupportedAbis) or $(RuntimeIdentifiers) depending if running under dotnet. If + /// is `true` (the default), remove potentially set properties that may break the build with `RuntimeIdentifiers` present. Currently, it + /// means removing the `RuntimeIdentifier` /// [Obsolete ("SetAndroidSupportedAbis is deprecated, please use SetRuntimeIdentifiers instead.")] - public static void SetAndroidSupportedAbis (this IShortFormProject project, params string [] abis) + public static void SetAndroidSupportedAbis (this IShortFormProject project, bool removeConflictingProperties, params string [] abis) { project.SetRuntimeIdentifiers (abis); } /// - /// Sets $(AndroidSupportedAbis) or $(RuntimeIdentifiers) depending if running under dotnet + /// Sets $(AndroidSupportedAbis) or $(RuntimeIdentifiers) depending if running under dotnet. + /// Remove potentially set properties that may break the build + /// with `RuntimeIdentifiers` present. Currently, it means removing the `RuntimeIdentifier` property. + /// + [Obsolete ("SetAndroidSupportedAbis is deprecated, please use SetRuntimeIdentifiers instead.")] + public static void SetAndroidSupportedAbis (this IShortFormProject project, params string [] abis) + { + project.SetAndroidSupportedAbis (removeConflictingProperties: true, abis); + } + + /// + /// Sets $(AndroidSupportedAbis) or $(RuntimeIdentifiers) depending if running under dotnet. If + /// is `true` (the default), remove potentially set properties that may break the build with `RuntimeIdentifiers` present. Currently, it + /// means removing the `RuntimeIdentifier` /// /// A semi-colon-delimited list of ABIs [Obsolete ("SetAndroidSupportedAbis is deprecated, please use SetRuntimeIdentifiers instead.")] - public static void SetAndroidSupportedAbis (this IShortFormProject project, string abis) + public static void SetAndroidSupportedAbis (this IShortFormProject project, string abis, bool removeConflictingProperties = true) { - project.SetRuntimeIdentifiers (abis.Split (';')); + project.SetRuntimeIdentifiers (abis.Split (';'), removeConflictingProperties); } - public static void SetRuntimeIdentifier (this IShortFormProject project, string androidAbi) + /// + /// Set the `$(RuntimeIdentifier)` property to the specified value. If is `true` (the default), remove + /// potentially set properties that may break the build with `RuntimeIdentifier` present. Currently, it means removing the `RuntimeIdentifiers` + /// property. + /// + public static void SetRuntimeIdentifier (this IShortFormProject project, string androidAbi, bool removeConflictingProperties = true) { project.SetProperty (KnownProperties.RuntimeIdentifier, AbiUtils.AbiToRuntimeIdentifier (androidAbi)); + if (removeConflictingProperties) { + project.RemoveProperty (KnownProperties.RuntimeIdentifiers); + } } - public static void SetRuntimeIdentifiers (this IShortFormProject project, IEnumerable androidAbis) + /// + /// Set the `$(RuntimeIdentifiers)` property to the specified value. If is `true` (the default), remove + /// potentially set properties that may break the build with `RuntimeIdentifiers` present. Currently, it means removing the `RuntimeIdentifier` + /// property. + /// + public static void SetRuntimeIdentifiers (this IShortFormProject project, IEnumerable androidAbis, bool removeConflictingProperties = true) { var abis = new List (); foreach (var androidAbi in androidAbis) { abis.Add (AbiUtils.AbiToRuntimeIdentifier (androidAbi)); } project.SetProperty (KnownProperties.RuntimeIdentifiers, string.Join (";", abis)); + + if (removeConflictingProperties) { + project.RemoveProperty (KnownProperties.RuntimeIdentifier); + } } - public static void SetRuntimeIdentifiers (this IShortFormProject project, params AndroidTargetArch[] targetArches) + /// + /// Set the `$(RuntimeIdentifiers)` property to the specified value. If is `true`, remove + /// potentially set properties that may break the build with `RuntimeIdentifiers` present. Currently, it means removing the `RuntimeIdentifier` + /// property. + /// + public static void SetRuntimeIdentifiers (this IShortFormProject project, bool removeConflictingProperties, params AndroidTargetArch[] targetArches) { if (targetArches == null || targetArches.Length == 0) { throw new ArgumentException ("must not be null or empty", nameof (targetArches)); @@ -51,6 +88,15 @@ public static void SetRuntimeIdentifiers (this IShortFormProject project, params project.SetProperty (KnownProperties.RuntimeIdentifiers, String.Join (";", targetArches.Select (arch => MonoAndroidHelper.ArchToRid (arch)))); } + /// + /// Set the `$(RuntimeIdentifiers)` property to the specified value. Remove potentially set properties that may break the build + /// with `RuntimeIdentifiers` present. Currently, it means removing the `RuntimeIdentifier` property. + /// + public static void SetRuntimeIdentifiers (this IShortFormProject project, params AndroidTargetArch[] targetArches) + { + project.SetRuntimeIdentifiers (removeConflictingProperties: true, targetArches); + } + public static HashSet GetRuntimeIdentifiers (this XamarinProject project) { var ridsPropValue = project.GetProperty (KnownProperties.RuntimeIdentifiers); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.Basic.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.Basic.cs index a0c5bc10cbe..0849aa144ab 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.Basic.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.Basic.cs @@ -102,6 +102,20 @@ public static string AbiToRid (string abi) return rid; } + /// + /// Return RID corresponding to the parameter. If `abiOrRid` is already a + /// valid RID, it is returned without changes. Otherwise an attempt is made to convert its value from + /// Android ABI name to .NET RID. + /// + public static string AbiToRidMaybe (string abiOrRid) + { + if (RidToAbiMap.ContainsKey (abiOrRid)) { + return abiOrRid; + } + + return AbiToRid (abiOrRid); + } + public static string RidToAbi (string rid) { if (!RidToAbiMap.TryGetValue (rid, out string abi)) { From 990acb88c19e93ef8ea1404858651b9b4cb832aa Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 13 Mar 2025 18:46:27 +0100 Subject: [PATCH 32/39] Let's see again... --- .../Tests/Xamarin.Android.Build.Tests/PackagingTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs index ca5df45955e..29d90b1cecd 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs @@ -177,7 +177,7 @@ public void CheckIncludedNativeLibraries ([Values (true, false)] bool compressNa IsRelease = true, }; proj.PackageReferences.Add(KnownPackages.SQLitePCLRaw_Core); - proj.SetAndroidSupportedAbis ("x86"); + proj.SetRuntimeIdentifier ("android-x64"); proj.SetProperty (proj.ReleaseProperties, "AndroidStoreUncompressedFileExtensions", compressNativeLibraries ? "" : "so"); using (var b = CreateApkBuilder ()) { b.ThrowOnBuildFailure = false; @@ -187,9 +187,9 @@ public void CheckIncludedNativeLibraries ([Values (true, false)] bool compressNa CompressionMethod method = compressNativeLibraries ? CompressionMethod.Deflate : CompressionMethod.Store; using (var zip = ZipHelper.OpenZip (apk)) { var libFiles = zip.Where (x => x.FullName.StartsWith("lib/", StringComparison.Ordinal) && !x.FullName.Equals("lib/", StringComparison.InvariantCultureIgnoreCase)); - var abiPaths = new string[] { "lib/x86/" }; + var abiPaths = new string[] { "lib/x86_64/" }; foreach (var file in libFiles) { - Assert.IsTrue (abiPaths.Any (x => file.FullName.Contains (x)), $"Apk contains an unnesscary lib file: {file.FullName}"); + Assert.IsTrue (abiPaths.Any (x => file.FullName.Contains (x)), $"Apk contains an unnecessary lib file: {file.FullName}"); Assert.IsTrue (file.CompressionMethod == method, $"{file.FullName} should have been CompressionMethod.{method} in the apk, but was CompressionMethod.{file.CompressionMethod}"); } } From 06b121af331432025d0044b81b8bd9274a466cf4 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 13 Mar 2025 19:37:13 +0100 Subject: [PATCH 33/39] This causes too many problems, alas --- .../Android/XamarinAndroidApplicationProject.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs index 67a4e9e5f44..66a07f9efc3 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs @@ -71,10 +71,6 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug" Sources.Add (new BuildItem.Source (() => "MainActivity" + Language.DefaultExtension) { TextContent = () => ProcessSourceTemplate (MainActivity ?? DefaultMainActivity) }); if (TargetRuntimeHelper.UseCoreCLR) { - // This is a quick hack to get all the tests executing in the CoreCLR context to work only for the, currently limited, - // subset of ABIs supported by CoreCLR without having to modify each test individually. Eventually it shouldn't be necessary. - this.SetRuntimeIdentifiers (TargetRuntimeHelper.CoreClrSupportedAbis); - // NuGet feed needed as Microsoft.Android.Runtime.CoreCLR packs not installed in workload by default AddOrRemoveLocalNugetFeedPath (add: true); } From 2de49555cfce702062dce87d61a17dd1dde8fb2b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 17 Mar 2025 11:47:26 +0100 Subject: [PATCH 34/39] Let's try to see what's going on there... --- .../Tests/Xamarin.Android.Build.Tests/BuildTest2.cs | 2 +- .../Tests/Xamarin.Android.Build.Tests/PackagingTest.cs | 2 +- .../Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index 1651c915be7..a7ff4320cb5 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -42,7 +42,7 @@ public partial class BuildTest2 : BaseTest [TestCaseSource (nameof (MarshalMethodsDefaultStatusSource))] public void MarshalMethodsDefaultEnabledStatus (bool isRelease, bool marshalMethodsEnabled) { - var abis = new [] { "armeabi-v7a", "x86" }; + var abis = new [] { "am64-v8a", "x86_64" }; AndroidTargetArch[] supportedArches = new [] { AndroidTargetArch.Arm, AndroidTargetArch.X86, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs index 29d90b1cecd..87198f09a0c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs @@ -177,7 +177,7 @@ public void CheckIncludedNativeLibraries ([Values (true, false)] bool compressNa IsRelease = true, }; proj.PackageReferences.Add(KnownPackages.SQLitePCLRaw_Core); - proj.SetRuntimeIdentifier ("android-x64"); + proj.SetAndroidSupportedAbis ("x86_64"); proj.SetProperty (proj.ReleaseProperties, "AndroidStoreUncompressedFileExtensions", compressNativeLibraries ? "" : "so"); using (var b = CreateApkBuilder ()) { b.ThrowOnBuildFailure = false; diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs index 52f4a8ba835..4fc67e4d439 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs @@ -143,7 +143,10 @@ orderby version descending /// public static bool UseLocalBuildOutput { get { + Console.WriteLine ($"UseLocalBuildOutput: local sdk dir == '{LocalDotNetAndroidSdkDirectory}'"); var msbuildDir = Path.Combine (LocalDotNetAndroidSdkDirectory, "tools"); + bool tasksExist = File.Exists (Path.Combine (msbuildDir, "Xamarin.Android.Build.Tasks.dll")); + Console.WriteLine ($"UseLocalBuildOutput: msbuild dir == '{msbuildDir}' (tasks exist? {tasksExist})"); return Directory.Exists (msbuildDir) && File.Exists (Path.Combine (msbuildDir, "Xamarin.Android.Build.Tasks.dll")); } } @@ -176,4 +179,3 @@ static Version ParseVersion (string path) public static bool IsUsingJdk11 => AndroidSdkResolver.GetJavaSdkVersionString ().Contains ("11.0"); } } - From 5230c383f62b79751378c6d34e4b46c58ca58cca Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 17 Mar 2025 14:34:17 +0100 Subject: [PATCH 35/39] A bit more printf debugging --- .../Tests/Xamarin.Android.Build.Tests/BuildTest2.cs | 6 +++--- .../Xamarin.Android.Build.Tests/PackagingTest.cs | 7 +++++-- .../Xamarin.ProjectTools/Common/TestEnvironment.cs | 11 ++++++++++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index a7ff4320cb5..0a79b916eba 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -42,10 +42,10 @@ public partial class BuildTest2 : BaseTest [TestCaseSource (nameof (MarshalMethodsDefaultStatusSource))] public void MarshalMethodsDefaultEnabledStatus (bool isRelease, bool marshalMethodsEnabled) { - var abis = new [] { "am64-v8a", "x86_64" }; + var abis = new [] { "arm64-v8a", "x86_64" }; AndroidTargetArch[] supportedArches = new [] { - AndroidTargetArch.Arm, - AndroidTargetArch.X86, + AndroidTargetArch.Arm64, + AndroidTargetArch.X86_64, }; var proj = new XamarinAndroidApplicationProject { IsRelease = isRelease diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs index 87198f09a0c..02b0334e53a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs @@ -94,7 +94,7 @@ public void CheckIncludedAssemblies ([Values (false, true)] bool usesAssemblySto }; AndroidTargetArch[] supportedArches = new[] { - AndroidTargetArch.Arm, + AndroidTargetArch.Arm64, }; proj.SetProperty ("AndroidUseAssemblyStore", usesAssemblyStores.ToString ()); @@ -133,9 +133,12 @@ public void CheckIncludedAssemblies ([Values (false, true)] bool usesAssemblySto "System.Collections.dll", "System.Collections.Concurrent.dll", "System.Text.RegularExpressions.dll", - "libarc.bin.so", }; + if (!TargetRuntimeHelper.UseCoreCLR) { + expectedFiles.Add ("libarc.bin.so"); + } + using (var b = CreateApkBuilder ()) { Assert.IsTrue (b.Build (proj), "build should have succeeded."); var apk = Path.Combine (Root, b.ProjectDirectory, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs index 4fc67e4d439..bdc1745a112 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs @@ -124,15 +124,24 @@ static string GetDotNetAndroidSdkDir (string packsDirectory) IsWindows ? "Microsoft.Android.Sdk.Windows" : "Microsoft.Android.Sdk.Linux"; + Console.WriteLine ($"GetDotNetAndroidSdkDir (\"{packsDirectory}\")"); var sdkDir = Path.Combine (packsDirectory, sdkName); - if (!Directory.Exists (sdkDir)) + Console.WriteLine ($" sdkDir == '{sdkDir}'"); + if (!Directory.Exists (sdkDir)) { + Console.WriteLine (" doesn't exist, returning String.Empty"); return string.Empty; + } var dirs = from d in Directory.GetDirectories (sdkDir) let version = ParseVersion (d) orderby version descending select d; + Console.WriteLine (" Got dirs:"); + foreach (string dir in dirs) { + Console.WriteLine ($" {dir}"); + } + return dirs.FirstOrDefault (); } From 4ea6109a4e0104e452bacf54d940a7a06bbe20a5 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 17 Mar 2025 19:28:34 +0100 Subject: [PATCH 36/39] Let's see if this fixes DotNetPublish for API 35 on CoreCLR --- .../Microsoft.NET.Sdk.Android/WorkloadManifest.in.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json index f3a51a493d5..75571790f71 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json @@ -11,6 +11,8 @@ "Microsoft.Android.Runtime.Mono.35.android-arm64", "Microsoft.Android.Runtime.Mono.35.android-x86", "Microsoft.Android.Runtime.Mono.35.android-x64", + "Microsoft.Android.Runtime.CoreCLR.35.android-arm64", + "Microsoft.Android.Runtime.CoreCLR.35.android-x64", "Microsoft.Android.Templates" ], "platforms": [ "win-x64", "win-arm64", "linux-x64", "linux-arm64", "osx-x64", "osx-arm64" ], From bbe495ecc6261ebe75f576f4c27415629185ebd9 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 17 Mar 2025 19:28:53 +0100 Subject: [PATCH 37/39] MonoVM vs CoreCLR ApplicationConfig --- .../Xamarin.Android.Build.Tests/BuildTest2.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index 0a79b916eba..c77ff536a7b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -68,10 +68,20 @@ public void MarshalMethodsDefaultEnabledStatus (bool isRelease, bool marshalMeth String.Join (";", supportedArches.Select (arch => MonoAndroidHelper.ArchToAbi (arch))), true ); - EnvironmentHelper.ApplicationConfig app_config = EnvironmentHelper.ReadApplicationConfig (envFiles); - Assert.That (app_config, Is.Not.Null, "application_config must be present in the environment files"); - Assert.AreEqual (app_config.marshal_methods_enabled, shouldMarshalMethodsBeEnabled, $"Marshal methods enabled status should be '{shouldMarshalMethodsBeEnabled}', but it was '{app_config.marshal_methods_enabled}'"); + bool marshal_methods_enabled; + if (TargetRuntimeHelper.UseMonoRuntime) { + EnvironmentHelper.ApplicationConfig app_config = EnvironmentHelper.ReadApplicationConfig (envFiles); + + Assert.That (app_config, Is.Not.Null, "application_config must be present in the environment files"); + marshal_methods_enabled = app_config.marshal_methods_enabled; + } else { + EnvironmentHelper.ApplicationConfigCLR app_config = EnvironmentHelper.ReadApplicationConfigCLR (envFiles); + + Assert.That (app_config, Is.Not.Null, "application_config must be present in the environment files"); + marshal_methods_enabled = app_config.marshal_methods_enabled; + } + Assert.AreEqual (marshal_methods_enabled, shouldMarshalMethodsBeEnabled, $"Marshal methods enabled status should be '{shouldMarshalMethodsBeEnabled}', but it was '{marshal_methods_enabled}'"); } } From 0bfa0c9b2a77c5462116ac36cdd048d1dd90866e Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 18 Mar 2025 19:30:31 +0100 Subject: [PATCH 38/39] Maybe that works? --- .../Tests/Xamarin.Android.Build.Tests/BuildTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index 2c198d06b33..004e4e19535 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -1419,7 +1419,7 @@ public void NUnitLiteNugetWorks () /* enableProguard */ null, /* androidEnableProguard */ "true", /* expectedBuildResult */ false, - /* expectedWarning */ TargetRuntimeHelper.UseCoreCLR && TargetRuntimeHelper.CoreClrIsExperimental ? "1 Warning(s)" : "0 Warning(s)", + /* expectedWarning */ "0 Warning(s)", }, new object [] { /* linkTool */ null, From 9f7851eae5d2519838aac646f88277c74c4e5733 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 25 Mar 2025 16:56:18 +0100 Subject: [PATCH 39/39] Fix after rebase --- .../xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs b/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs index 149f08116dc..4fecf7d4f43 100644 --- a/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs +++ b/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs @@ -69,8 +69,6 @@ void CopyExtraBuildFiles (string destinationRoot, Context context) filesToCopyPreserveRelative.AddRange (Directory.GetFiles (javaInteropBuildConfigDir, "*.props")); } - filesToCopyPreserveRelative.AddRange (Directory.GetFiles (Path.Combine (BuildPaths.XamarinAndroidSourceRoot, "src", "native", "mono", "pinvoke-override"), "*.include.*")); - var buildConfigDir = Path.Combine (BuildPaths.XamarinAndroidSourceRoot, "bin", $"Build{context.Configuration}"); if (Directory.Exists (buildConfigDir)) { foreach (var fileMatch in buildConfigFiles) {