From adfc7f4a6536cef1ae52041e104a875c0902917d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Apr 2026 20:48:45 +0000
Subject: [PATCH 1/6] Initial plan
From a0331580d25ae02cb9abdcc44b8e4cb3bee0956a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Apr 2026 21:21:57 +0000
Subject: [PATCH 2/6] Compose DOTNET_STARTUP_HOOKS from runtime and environment
files
Agent-Logs-Url: https://github.com/dotnet/android/sessions/a0bba47d-8a89-476b-b420-c6c5e6914563
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
---
.../Microsoft.Android.Sdk.HotReload.targets | 11 ++---
.../EnvironmentContentTests.cs | 44 +++++++++++++++++++
.../Xamarin.Android.Common.targets | 37 +++++++++++++++-
3 files changed, 83 insertions(+), 9 deletions(-)
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets
index a1f29e119d7..b1ef8ccaff8 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.HotReload.targets
@@ -23,8 +23,7 @@ See: https://github.com/dotnet/sdk/pull/52581
$([System.IO.Path]::GetFileNameWithoutExtension('$(_AndroidHotReloadAgentAssemblyPath)'))
-
+
-
-
+ <_AndroidDotnetStartupHooks Include="$(_AndroidHotReloadAgentAssemblyName)" />
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 1f5d51ef909..e72fdffa481 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
@@ -14,6 +14,15 @@ namespace Xamarin.Android.Build.Tests
[Parallelizable (ParallelScope.Children)]
public class EnvironmentContentTests : BaseTest
{
+ class StartupHookEnvironmentProject : XamarinAndroidApplicationProject
+ {
+ protected override string ExtraDirectoryBuildTargetsContent => """
+
+
+
+ """;
+ }
+
[Test]
[NonParallelizable]
public void BuildApplicationWithMonoEnvironment ([Values ("", "Normal", "Offline")] string sequencePointsMode, [Values] AndroidRuntime runtime)
@@ -161,6 +170,41 @@ public void CheckConcurrentGC ()
}
}
+ [Test]
+ public void DotNetStartupHooksAreMergedFromRuntimeEnvironmentVariableAndAndroidEnvironment ()
+ {
+ const string supportedAbis = "armeabi-v7a;x86";
+
+ var proj = new StartupHookEnvironmentProject {
+ IsRelease = false,
+ OtherBuildItems = {
+ new BuildItem.NoActionResource ("hotreload/Microsoft.Extensions.DotNetDeltaApplier.dll") {
+ BinaryContent = () => [],
+ },
+ new AndroidItem.AndroidEnvironment ("startup.env") {
+ TextContent = () => "DOTNET_STARTUP_HOOKS=MyStartupHook.dll",
+ },
+ },
+ };
+ proj.SetRuntime (AndroidRuntime.MonoVM);
+ proj.SetAndroidSupportedAbis (supportedAbis);
+
+ using (var b = CreateApkBuilder ()) {
+ Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
+
+ string intermediateOutputDir = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath);
+ List envFiles = EnvironmentHelper.GatherEnvironmentFiles (intermediateOutputDir, supportedAbis, true, AndroidRuntime.MonoVM);
+ Dictionary envvars = EnvironmentHelper.ReadEnvironmentVariables (envFiles, AndroidRuntime.MonoVM);
+
+ Assert.IsTrue (envvars.TryGetValue ("DOTNET_STARTUP_HOOKS", out string startupHooks), "Environment should contain DOTNET_STARTUP_HOOKS");
+ CollectionAssert.AreEquivalent (
+ new [] { "Microsoft.Extensions.DotNetDeltaApplier", "MyStartupHook.dll" },
+ startupHooks.Split (':'),
+ "DOTNET_STARTUP_HOOKS should merge values from RuntimeEnvironmentVariable and AndroidEnvironment."
+ );
+ }
+ }
+
[Test]
public void CheckForInvalidHttpClientHandlerType ([Values] AndroidRuntime runtime)
{
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index 1f37f9198bc..8ec0160ca55 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -1587,7 +1587,42 @@ because xbuild doesn't support framework reference assemblies.
-
+
+
+ <_AndroidStartupHooksFromRuntimeEnvironmentVariable Include="@(RuntimeEnvironmentVariable->WithMetadataValue('Identity', 'DOTNET_STARTUP_HOOKS'))" />
+ <_AndroidStartupHooksFromRuntimeEnvironmentVariable Remove="@(_AndroidStartupHooksFromRuntimeEnvironmentVariable)"
+ Condition=" '$(_AndroidHotReloadAgentAssemblyPath)' != '' And '%(_AndroidStartupHooksFromRuntimeEnvironmentVariable.Value)' == '$(_AndroidHotReloadAgentAssemblyPath)' " />
+ <_AndroidDotnetStartupHooks Include="@(_AndroidStartupHooksFromRuntimeEnvironmentVariable->'%(Value)')" />
+ <_AndroidEnvironmentStartupHookFiles Include="@(AndroidEnvironment);@(LibraryEnvironments)" />
+
+
+
+
+
+
+
+ <_AndroidEnvironmentStartupHookLinesFiltered Include="@(_AndroidEnvironmentStartupHookLines)"
+ Condition="$([System.String]::Copy('%(_AndroidEnvironmentStartupHookLines.Identity)').StartsWith('DOTNET_STARTUP_HOOKS='))" />
+ <_AndroidDotnetStartupHooks Include="$([System.String]::Copy('%(_AndroidEnvironmentStartupHookLinesFiltered.Identity)').Substring(21))" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<_GeneratedAndroidEnvironment Include="mono.enable_assembly_preload=0" Condition=" '$(AndroidEnablePreloadAssemblies)' != 'True' " />
<_GeneratedAndroidEnvironment Include="DOTNET_MODIFIABLE_ASSEMBLIES=Debug" Condition=" '$(AndroidIncludeDebugSymbols)' == 'true' and '$(AndroidUseInterpreter)' == 'true' " />
From 74f6906796016ed111e4b622f0b93f9fbeec3ea0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Apr 2026 21:33:10 +0000
Subject: [PATCH 3/6] Document startup hook prefix length in composition target
Agent-Logs-Url: https://github.com/dotnet/android/sessions/a0bba47d-8a89-476b-b420-c6c5e6914563
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
---
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index 8ec0160ca55..be0459f9d3d 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -1604,6 +1604,7 @@ because xbuild doesn't support framework reference assemblies.
<_AndroidEnvironmentStartupHookLinesFiltered Include="@(_AndroidEnvironmentStartupHookLines)"
Condition="$([System.String]::Copy('%(_AndroidEnvironmentStartupHookLines.Identity)').StartsWith('DOTNET_STARTUP_HOOKS='))" />
+
<_AndroidDotnetStartupHooks Include="$([System.String]::Copy('%(_AndroidEnvironmentStartupHookLinesFiltered.Identity)').Substring(21))" />
From 120aedfc952fd8d92e16570ee81faa1934ca2c6b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 23 Apr 2026 07:52:57 +0000
Subject: [PATCH 4/6] Move DOTNET_STARTUP_HOOKS merge to EnvironmentBuilder
Agent-Logs-Url: https://github.com/dotnet/android/sessions/eaf7b02c-a819-4e2f-8bd5-fedfee6f1931
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
---
.../Utilities/EnvironmentBuilder.cs | 33 +++++++++++++++++--
.../Xamarin.Android.Common.targets | 12 -------
2 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs b/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs
index 51121c052bf..95d3e91733c 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs
@@ -7,6 +7,8 @@ namespace Xamarin.Android.Tasks;
class EnvironmentBuilder
{
+ const string DotNetStartupHooks = "DOTNET_STARTUP_HOOKS";
+
static readonly string[] defaultLogLevel = {"MONO_LOG_LEVEL", "info"};
static readonly string[] defaultMonoDebug = {"MONO_DEBUG", "gen-compact-seq-points"};
static readonly string defaultHttpMessageHandler = "System.Net.Http.HttpClientHandler, System.Net.Http";
@@ -50,10 +52,17 @@ public void Read (ITaskItem[]? envItems)
public void AddEnvironmentVariable (string name, string value)
{
+ string escapedName = ValidAssemblerString (name);
+ string escapedValue = ValidAssemblerString (value);
+
if (Char.IsUpper(name [0]) || !Char.IsLetter(name [0])) {
- environmentVariables [ValidAssemblerString (name)] = ValidAssemblerString (value);
+ if (name == DotNetStartupHooks && environmentVariables.TryGetValue (escapedName, out string? existingStartupHooks)) {
+ environmentVariables [escapedName] = MergeDotNetStartupHooks (existingStartupHooks, escapedValue);
+ } else {
+ environmentVariables [escapedName] = escapedValue;
+ }
} else {
- systemProperties [ValidAssemblerString (name)] = ValidAssemblerString (value);
+ systemProperties [escapedName] = escapedValue;
}
}
@@ -108,5 +117,25 @@ public void AddMonoGcParams (bool enableSgenConcurrent)
AddEnvironmentVariable ("MONO_GC_PARAMS", enableSgenConcurrent ? "major=marksweep-conc" : "major=marksweep");
}
+ static string MergeDotNetStartupHooks (string first, string second)
+ {
+ var mergedHooks = new List ();
+ var seenHooks = new HashSet (StringComparer.Ordinal);
+
+ foreach (string hook in first.Split (new char [] { ':' }, StringSplitOptions.RemoveEmptyEntries)) {
+ if (seenHooks.Add (hook)) {
+ mergedHooks.Add (hook);
+ }
+ }
+
+ foreach (string hook in second.Split (new char [] { ':' }, StringSplitOptions.RemoveEmptyEntries)) {
+ if (seenHooks.Add (hook)) {
+ mergedHooks.Add (hook);
+ }
+ }
+
+ return String.Join (":", mergedHooks);
+ }
+
static string ValidAssemblerString (string s) => s.Replace ("\\", "\\\\").Replace ("\"", "\\\"");
}
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index be0459f9d3d..7e21ca0b27c 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -1594,18 +1594,6 @@ because xbuild doesn't support framework reference assemblies.
<_AndroidStartupHooksFromRuntimeEnvironmentVariable Remove="@(_AndroidStartupHooksFromRuntimeEnvironmentVariable)"
Condition=" '$(_AndroidHotReloadAgentAssemblyPath)' != '' And '%(_AndroidStartupHooksFromRuntimeEnvironmentVariable.Value)' == '$(_AndroidHotReloadAgentAssemblyPath)' " />
<_AndroidDotnetStartupHooks Include="@(_AndroidStartupHooksFromRuntimeEnvironmentVariable->'%(Value)')" />
- <_AndroidEnvironmentStartupHookFiles Include="@(AndroidEnvironment);@(LibraryEnvironments)" />
-
-
-
-
-
-
-
- <_AndroidEnvironmentStartupHookLinesFiltered Include="@(_AndroidEnvironmentStartupHookLines)"
- Condition="$([System.String]::Copy('%(_AndroidEnvironmentStartupHookLines.Identity)').StartsWith('DOTNET_STARTUP_HOOKS='))" />
-
- <_AndroidDotnetStartupHooks Include="$([System.String]::Copy('%(_AndroidEnvironmentStartupHookLinesFiltered.Identity)').Substring(21))" />
From 22ec3833557e3578052e56875e0fbfe50caa8838 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 29 Apr 2026 20:23:13 +0000
Subject: [PATCH 5/6] Simplify startup hook composition and task flow
Agent-Logs-Url: https://github.com/dotnet/android/sessions/f4947bfc-48c4-4b7a-ab89-4760d3d73354
Co-authored-by: jonathanpeppers <840039+jonathanpeppers@users.noreply.github.com>
---
.../Microsoft.Android.Sdk.NativeAOT.targets | 1 +
...crosoft.Android.Sdk.TypeMap.LlvmIr.targets | 1 +
.../GenerateAdditionalProviderSources.cs | 2 ++
...ateNativeAotEnvironmentAssemblerSources.cs | 2 ++
.../GenerateNativeApplicationConfigSources.cs | 2 ++
.../Utilities/EnvironmentBuilder.cs | 23 +++++++++++++++++++
.../Xamarin.Android.Common.targets | 11 ++++-----
7 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
index 14eb57c1134..518372587c0 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
@@ -234,6 +234,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.LlvmIr.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.LlvmIr.targets
index 4b1cb9fcab0..e978518cd32 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.LlvmIr.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.LlvmIr.targets
@@ -146,6 +146,7 @@
AdditionalProviderSources="@(_AdditionalProviderSources)"
AndroidRuntime="$(_AndroidRuntime)"
Environments="@(_EnvironmentFiles)"
+ DotNetStartupHooks="@(_AndroidDotnetStartupHooksDistinct)"
HttpClientHandlerType="$(AndroidHttpClientHandlerType)"
EnableSGenConcurrent="$(AndroidEnableSGenConcurrent)"
CodeGenerationTarget="$(_AndroidJcwCodegenTarget)"
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateAdditionalProviderSources.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateAdditionalProviderSources.cs
index 36effd2b068..e8d9159834d 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateAdditionalProviderSources.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateAdditionalProviderSources.cs
@@ -31,6 +31,7 @@ public class GenerateAdditionalProviderSources : AndroidTask
public string TargetName { get; set; } = "";
public ITaskItem[]? Environments { get; set; }
+ public ITaskItem[]? DotNetStartupHooks { get; set; }
// We need to pass these two to the environment builder, otherwise not used
// by this task. See also GenerateNativeApplicationSources.cs
@@ -92,6 +93,7 @@ void Generate (NativeCodeGenStateObject codeGenState)
// We care only about environment variables here
var envBuilder = new EnvironmentBuilder (Log);
envBuilder.Read (Environments);
+ envBuilder.AddDotNetStartupHooks (DotNetStartupHooks);
GenerateNativeApplicationConfigSources.AddDefaultEnvironmentVariables (envBuilder, HttpClientHandlerType, EnableSGenConcurrent);
var envVarNames = new StringBuilder ();
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeAotEnvironmentAssemblerSources.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeAotEnvironmentAssemblerSources.cs
index 55e11752638..e810c09be74 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeAotEnvironmentAssemblerSources.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeAotEnvironmentAssemblerSources.cs
@@ -14,12 +14,14 @@ public class GenerateNativeAotEnvironmentAssemblerSources : AndroidTask
[Required]
public string RID { get; set; } = "";
public ITaskItem[]? Environments { get; set; }
+ public ITaskItem[]? DotNetStartupHooks { get; set; }
public string? HttpClientHandlerType { get; set; }
public override bool RunTask ()
{
var envBuilder = new EnvironmentBuilder (Log);
envBuilder.Read (Environments);
+ envBuilder.AddDotNetStartupHooks (DotNetStartupHooks);
// Environment variables are set by Java (code generated in the GenerateAdditionalProviderSources task)
// We still want to set system properties, if any
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs
index 7b01f6f08e5..bc97e380f6f 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs
@@ -64,6 +64,7 @@ public class GenerateNativeApplicationConfigSources : AndroidTask
public string? PackageNamingPolicy { get; set; }
public string? Debug { get; set; }
public ITaskItem[]? Environments { get; set; }
+ public ITaskItem[]? DotNetStartupHooks { get; set; }
public string? AndroidAotMode { get; set; }
public bool AndroidAotEnableLazyLoad { get; set; }
public bool EnableLLVM { get; set; }
@@ -113,6 +114,7 @@ public override bool RunTask ()
// files (generated by us) which weren't present by the time GeneratJavaStubs ran.
var envBuilder = new EnvironmentBuilder (Log, EnablePreloadAssembliesDefault, sequencePointsMode);
envBuilder.Read (Environments);
+ envBuilder.AddDotNetStartupHooks (DotNetStartupHooks);
if (_Debug) {
envBuilder.AddDefaultDebugBuildLogLevel ();
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs b/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs
index 95d3e91733c..c3583598471 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs
@@ -50,6 +50,29 @@ public void Read (ITaskItem[]? envItems)
}
}
+ public void AddDotNetStartupHooks (ITaskItem[]? startupHooks)
+ {
+ if (startupHooks == null || startupHooks.Length == 0) {
+ return;
+ }
+
+ var values = new List (startupHooks.Length);
+ foreach (ITaskItem hook in startupHooks) {
+ string value = hook.ItemSpec.Trim ();
+ if (value.IsNullOrWhiteSpace ()) {
+ continue;
+ }
+
+ values.Add (value);
+ }
+
+ if (values.Count == 0) {
+ return;
+ }
+
+ AddEnvironmentVariable (DotNetStartupHooks, String.Join (":", values));
+ }
+
public void AddEnvironmentVariable (string name, string value)
{
string escapedName = ValidAssemblerString (name);
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index 7e21ca0b27c..49b300ef3af 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -1600,22 +1600,20 @@ because xbuild doesn't support framework reference assemblies.
-
-
-
-
-
+
+
+
<_GeneratedAndroidEnvironment Include="mono.enable_assembly_preload=0" Condition=" '$(AndroidEnablePreloadAssemblies)' != 'True' " />
<_GeneratedAndroidEnvironment Include="DOTNET_MODIFIABLE_ASSEMBLIES=Debug" Condition=" '$(AndroidIncludeDebugSymbols)' == 'true' and '$(AndroidUseInterpreter)' == 'true' " />
<_GeneratedAndroidEnvironment Include="DOTNET_DiagnosticPorts=$(DiagnosticConfiguration)" Condition=" '$(DiagnosticConfiguration)' != '' " />
+ <_GeneratedAndroidEnvironment Include="DOTNET_STARTUP_HOOKS=$(_AndroidDotnetStartupHooksValue)" Condition=" '$(_AndroidDotnetStartupHooksValue)' != '' " />
<_GeneratedAndroidEnvironment Include="@(RuntimeEnvironmentVariable->'%(Identity)=%(Value)')" />
@@ -1758,6 +1756,7 @@ because xbuild doesn't support framework reference assemblies.
MonoComponents="@(_MonoComponent)"
EnvironmentOutputDirectory="$(IntermediateOutputPath)android"
Environments="@(_EnvironmentFiles)"
+ DotNetStartupHooks="@(_AndroidDotnetStartupHooksDistinct)"
AndroidAotMode="$(AndroidAotMode)"
AndroidAotEnableLazyLoad="$(AndroidAotEnableLazyLoad)"
EnableLLVM="$(EnableLLVM)"
From 56b9467bfa3f6b7fbf8a2c693f2a15fdb3e3d435 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 29 Apr 2026 20:32:28 +0000
Subject: [PATCH 6/6] Refine startup hook simplification per review feedback
Agent-Logs-Url: https://github.com/dotnet/android/sessions/f4947bfc-48c4-4b7a-ab89-4760d3d73354
Co-authored-by: jonathanpeppers <840039+jonathanpeppers@users.noreply.github.com>
---
.../Utilities/EnvironmentBuilder.cs | 4 ++--
.../Xamarin.Android.Common.targets | 10 ++++------
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs b/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs
index c3583598471..86ece8a0c97 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentBuilder.cs
@@ -58,11 +58,11 @@ public void AddDotNetStartupHooks (ITaskItem[]? startupHooks)
var values = new List (startupHooks.Length);
foreach (ITaskItem hook in startupHooks) {
- string value = hook.ItemSpec.Trim ();
- if (value.IsNullOrWhiteSpace ()) {
+ if (hook.ItemSpec.IsNullOrWhiteSpace ()) {
continue;
}
+ string value = hook.ItemSpec.Trim ();
values.Add (value);
}
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index 49b300ef3af..f45531a9b33 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -1600,16 +1600,14 @@ because xbuild doesn't support framework reference assemblies.
-
-
-
-
-
-
+
+ <_AndroidDotnetStartupHooksValue>@(_AndroidDotnetStartupHooksDistinct,':')
+
+
<_GeneratedAndroidEnvironment Include="mono.enable_assembly_preload=0" Condition=" '$(AndroidEnablePreloadAssemblies)' != 'True' " />
<_GeneratedAndroidEnvironment Include="DOTNET_MODIFIABLE_ASSEMBLIES=Debug" Condition=" '$(AndroidIncludeDebugSymbols)' == 'true' and '$(AndroidUseInterpreter)' == 'true' " />
<_GeneratedAndroidEnvironment Include="DOTNET_DiagnosticPorts=$(DiagnosticConfiguration)" Condition=" '$(DiagnosticConfiguration)' != '' " />