From 582c449e18855d88ddf1cfe7deaf3510af4db523 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 4e4e6b311c8..bf0cabf2701 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 249e3bf3a94a267f288a7c6eda2a6344fb95e9dd 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 0cff9317f4f..3a379836024 100644 --- a/build-tools/automation/azure-pipelines.yaml +++ b/build-tools/automation/azure-pipelines.yaml @@ -102,12 +102,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 6ca1c64971d7a079531ed10db63723a90b35a9bf 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 9d47610a3f8040b370b8ed3645c4f6c1821f12b5 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 f3942de6cf7397c7f602ac6cbaa65dc51196bed4 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 ed36b39e7810eede819cd9c9b721eb64c44b4724 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 4c45845205fc0087625c48050612724b59accdfa 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 3ddedf3a87cb58e8d9a007ec66c4eba0121709d4 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 b0e94e40f379c4c406869363f01ced14d66bcab0 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 a2760d8c845..d673322aabd 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 084b8f9178a78105856d039dad1cc09cab151c13 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 ecd575022fd5ceeb64b3788e845b7e530c9aab49 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 06cacd2c06f4c3446dfcb79f60f7747f2bfae56f 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 6f9a9e89c99f02bf5545e015f96f9f716f287133 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 8affe10051da03ba38f66c1cd4afb5c7fb4dc01e 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 f60897cbe825951f313a895e78cc027e2037b9aa 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 944333118ea..a44a8cd3706 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, ProjectName = "Test Me", 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 bf0cabf2701..8cffd6e70cc 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 @@ -422,6 +422,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 526bc869aaa..756dae10221 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 b56172cc5fe84addb73cd7e7cede63c6068def21 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 a5d0e7ab4cbbb4bed25268e34f022614898de7f3 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 dca71b5f5c96f5679d2ed505f1b820cf17a7ed56 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 a27e0943bb2..89d2039320e 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 @@ -414,10 +414,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); @@ -437,9 +441,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 e92fd837ee2d020f02ab6e9f7bd711b9fe71c87b 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 b60c4b60a4659bf0095ddf3f7801225264f96dd4 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 0acd0b8262eb92c3269139deff697beef100ee92 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 8d2a1dfd131a5ad334a14df2ac10ba1a427d70a6 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 a44a8cd3706..cfbeb1bcc10 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 @@ -231,6 +231,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, }; @@ -273,13 +277,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"); @@ -1275,7 +1283,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 97181d64b2bc662330222ed5416a533c6849fe50 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 5b60d1a9a5a494ed3419901de46587c7b4194ba7 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 1365db4e431674c731809e80bce1f383f405a521 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 31c4f16b0dbaa6482f300791a5f858281da77c84 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 cfbeb1bcc10..5dd8b4c8278 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 @@ -275,6 +275,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) { @@ -296,8 +297,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) { @@ -311,7 +321,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 7e5e57a24bf842d412a2a2bdc10109b841e53b63 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 5dd8b4c8278..fc5ea3867a7 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 @@ -359,6 +359,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 c3d9f0651c47e90e9d4d32999614fbb82c9af895 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 fc5ea3867a7..91b40e1c3bf 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 @@ -1408,21 +1408,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 8cffd6e70cc..8bb3feacb24 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 @@ -422,12 +422,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 89d2039320e..f46b8099a33 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 @@ -437,8 +437,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 9a1a2c0dd8d89f7d8eea5a62d55b6b5062533d23 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 91b40e1c3bf..6a939a1c099 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 @@ -101,6 +101,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); } @@ -1703,7 +1707,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 8bb3feacb24..8970a05bdac 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 @@ -580,6 +580,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 f46b8099a33..98d07232371 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 55ed1a0a6fc99ff9b71396e67c30acc39882d83a 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 3a379836024..4b63b39f75d 100644 --- a/build-tools/automation/azure-pipelines.yaml +++ b/build-tools/automation/azure-pipelines.yaml @@ -121,6 +121,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 6a939a1c099..c852781a94e 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 @@ -101,10 +101,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); } @@ -180,7 +176,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 95fd0957b615f1824056cdb3262c9e98d68a8526 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 98d07232371..2479b05dd4e 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 @@ -199,7 +199,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; @@ -209,9 +209,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 98fee59ef3a5ca2a374479e9551468f3e64c9cfc 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 fa0e7aa749d1316193581233c7110452004e50ba 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 8970a05bdac..1d86c4f0532 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 2479b05dd4e..c284a07faf4 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 @@ -199,7 +199,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 ff7bdd58ce5adedba4903a9287dce56ee9589f40 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 1d86c4f0532..d9040bcb3be 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 c284a07faf4..743be82dde0 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 29b0f38305c9d4264dc750c96cfe2dbfdf248692 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 7150188be3f8fe01ce3806fa86a0a50c9274eed3 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 d9040bcb3be..05322d945de 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 241866d215313a2dd8fe5d8a5ce745cced845176 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 c852781a94e..362db57f24b 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 @@ -1421,7 +1421,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 88cecfaf7200a63d410291e849901a623a3b87f1 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) {