diff --git a/src/linker/Linker/Driver.cs b/src/linker/Linker/Driver.cs index d0456a604c38..1858b8d5f8e5 100644 --- a/src/linker/Linker/Driver.cs +++ b/src/linker/Linker/Driver.cs @@ -31,6 +31,7 @@ using System.Diagnostics; using System.IO; using System.Reflection; +using System.Runtime.Loader; using System.Text; using System.Xml.XPath; using Mono.Cecil; @@ -794,8 +795,11 @@ Assembly GetCustomAssembly (string arg) { if (Path.IsPathRooted (arg)) { var assemblyPath = Path.GetFullPath (arg); - if (File.Exists (assemblyPath)) - return Assembly.Load (File.ReadAllBytes (assemblyPath)); + if (File.Exists (assemblyPath)) { + // The CLR will return the already-loaded assembly if the same path is requested multiple times + // (or even if a different path specifies the "same" assembly, based on the MVID). + return AssemblyLoadContext.Default.LoadFromAssemblyPath (assemblyPath); + } context.LogError ($"The assembly '{arg}' specified for '--custom-step' option could not be found", 1022); } else context.LogError ($"The path to the assembly '{arg}' specified for '--custom-step' must be fully qualified", 1023); diff --git a/test/Mono.Linker.Tests.Cases/CommandLine/AddCustomStep.cs b/test/Mono.Linker.Tests.Cases/CommandLine/AddCustomStep.cs index b31040d8029d..79271dcfb573 100644 --- a/test/Mono.Linker.Tests.Cases/CommandLine/AddCustomStep.cs +++ b/test/Mono.Linker.Tests.Cases/CommandLine/AddCustomStep.cs @@ -7,11 +7,11 @@ namespace Mono.Linker.Tests.Cases.CommandLine #if !NETCOREAPP [IgnoreTestCase ("Can be enabled once MonoBuild produces a dll from which we can grab the types in the Mono.Linker namespace.")] #else - [SetupCompileBefore ("CustomStep.dll", new[] { "Dependencies/CustomStepDummy.cs" }, new[] { "illink.dll" })] + [SetupCompileBefore ("CustomStepDummy.dll", new[] { "Dependencies/CustomStepDummy.cs" }, new[] { "illink.dll" })] #endif - [SetupLinkerArgument ("--custom-step", "CustomStep.CustomStepDummy,CustomStep.dll")] - [SetupLinkerArgument ("--custom-step", "-CleanStep:CustomStep.CustomStepDummy,CustomStep.dll")] - [SetupLinkerArgument ("--custom-step", "+CleanStep:CustomStep.CustomStepDummy,CustomStep.dll")] + [SetupLinkerArgument ("--custom-step", "CustomStep.CustomStepDummy,CustomStepDummy.dll")] + [SetupLinkerArgument ("--custom-step", "-CleanStep:CustomStep.CustomStepDummy,CustomStepDummy.dll")] + [SetupLinkerArgument ("--custom-step", "+CleanStep:CustomStep.CustomStepDummy,CustomStepDummy.dll")] [SetupLinkerArgument ("--verbose")] [LogContains ("Custom step added")] public class AddCustomStep diff --git a/test/Mono.Linker.Tests.Cases/CommandLine/CustomStepData.cs b/test/Mono.Linker.Tests.Cases/CommandLine/CustomStepData.cs index c6ef3633af99..2530b7e62037 100644 --- a/test/Mono.Linker.Tests.Cases/CommandLine/CustomStepData.cs +++ b/test/Mono.Linker.Tests.Cases/CommandLine/CustomStepData.cs @@ -7,9 +7,9 @@ namespace Mono.Linker.Tests.Cases.CommandLine #if !NETCOREAPP [IgnoreTestCase ("Can be enabled once MonoBuild produces a dll from which we can grab the types in the Mono.Linker namespace.")] #else - [SetupCompileBefore ("CustomStep.dll", new[] { "Dependencies/CustomStepUser.cs" }, new[] { "illink.dll" })] + [SetupCompileBefore ("CustomStepUser.dll", new[] { "Dependencies/CustomStepUser.cs" }, new[] { "illink.dll" })] #endif - [SetupLinkerArgument ("--custom-step", "CustomStep.CustomStepUser,CustomStep.dll")] + [SetupLinkerArgument ("--custom-step", "CustomStep.CustomStepUser,CustomStepUser.dll")] [SetupLinkerArgument ("--custom-data", "NewKey=UserValue")] [SetupLinkerArgument ("--verbose")] [LogContains ("Custom step added with custom data of UserValue")] diff --git a/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepCanPreserveMethodsAfterMark.cs b/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepCanPreserveMethodsAfterMark.cs index a9da1fbd0278..d3e32e8169f9 100644 --- a/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepCanPreserveMethodsAfterMark.cs +++ b/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepCanPreserveMethodsAfterMark.cs @@ -6,8 +6,8 @@ namespace Mono.Linker.Tests.Cases.Extensibility #if !NETCOREAPP [IgnoreTestCase ("Specific to the illink build")] #endif - [SetupCompileBefore ("customstep.dll", new[] { "Dependencies/PreserveMethodsSubStep.cs" }, new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] - [SetupLinkerArgument ("--custom-step", "+MarkStep:PreserveMethodsSubStep,customstep.dll")] + [SetupCompileBefore ("CustomStepAfterMark.dll", new[] { "Dependencies/PreserveMethodsSubStep.cs" }, new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] + [SetupLinkerArgument ("--custom-step", "+MarkStep:PreserveMethodsSubStep,CustomStepAfterMark.dll")] public class CustomStepCanPreserveMethodsAfterMark { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepCanPreserveMethodsBeforeMark.cs b/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepCanPreserveMethodsBeforeMark.cs index 17ca281af1e9..d479cfcc97b5 100644 --- a/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepCanPreserveMethodsBeforeMark.cs +++ b/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepCanPreserveMethodsBeforeMark.cs @@ -6,8 +6,8 @@ namespace Mono.Linker.Tests.Cases.Extensibility #if !NETCOREAPP [IgnoreTestCase ("Specific to the illink build")] #endif - [SetupCompileBefore ("customstep.dll", new[] { "Dependencies/PreserveMethodsSubStep.cs" }, new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] - [SetupLinkerArgument ("--custom-step", "-MarkStep:PreserveMethodsSubStep,customstep.dll")] + [SetupCompileBefore ("CustomStepBeforeMark.dll", new[] { "Dependencies/PreserveMethodsSubStep.cs" }, new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] + [SetupLinkerArgument ("--custom-step", "-MarkStep:PreserveMethodsSubStep,CustomStepBeforeMark.dll")] public class CustomStepCanPreserveMethodsBeforeMark { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepsCanShareState.cs b/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepsCanShareState.cs new file mode 100644 index 000000000000..94771aaecf33 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Extensibility/CustomStepsCanShareState.cs @@ -0,0 +1,24 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Extensibility +{ + [SetupCompileBefore ("SharedCustomSteps.dll", new[] { "Dependencies/CustomStepsWithSharedState.cs" }, new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] + [SetupLinkerArgument ("--custom-step", "SharedStateHandler2,SharedCustomSteps.dll")] + [SetupLinkerArgument ("--custom-step", "SharedStateHandler1,SharedCustomSteps.dll")] + public class CustomStepsCanShareState + { + public static void Main () + { + } + + [Kept] + public static void MarkedMethod () + { + } + + public static void UnmarkedMethod () + { + } + } +} \ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/Extensibility/Dependencies/CustomStepsWithSharedState.cs b/test/Mono.Linker.Tests.Cases/Extensibility/Dependencies/CustomStepsWithSharedState.cs new file mode 100644 index 000000000000..8b6ba1d769bc --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Extensibility/Dependencies/CustomStepsWithSharedState.cs @@ -0,0 +1,61 @@ +using Mono.Cecil; +using Mono.Linker; +using Mono.Linker.Steps; + +public class SharedAnnotation +{ + public bool Mark { get; set; } + + public static void Set (LinkContext context, MethodDefinition method, SharedAnnotation value) + { + context.Annotations.SetCustomAnnotation (nameof (SharedAnnotation), method, value); + } + + public static SharedAnnotation Get (LinkContext context, MethodDefinition method) { + return context.Annotations.GetCustomAnnotation (nameof (SharedAnnotation), method) as SharedAnnotation; + } +} + +public class SharedStateHandler1 : IMarkHandler +{ + LinkContext context; + + public void Initialize (LinkContext context, MarkContext markContext) + { + this.context = context; + markContext.RegisterMarkTypeAction (ProcessType); + } + + public void ProcessType (TypeDefinition type) + { + if (!type.HasMethods) + return; + + foreach (var method in type.Methods) { + if (method.Name == "MarkedMethod") + SharedAnnotation.Set (context, method, new SharedAnnotation () { Mark = true }); + } + } +} + +public class SharedStateHandler2 : IMarkHandler +{ + LinkContext context; + + public void Initialize (LinkContext context, MarkContext markContext) + { + this.context = context; + markContext.RegisterMarkTypeAction (ProcessType); + } + + public void ProcessType (TypeDefinition type) + { + if (!type.HasMethods) + return; + + foreach (var method in type.Methods) { + if (SharedAnnotation.Get (context, method) is SharedAnnotation annotation && annotation.Mark) + context.Annotations.Mark (method); + } + } +} \ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/Extensibility/SubStepDispatcherFields.cs b/test/Mono.Linker.Tests.Cases/Extensibility/SubStepDispatcherFields.cs index 2bda035ebbfb..74fb34927305 100644 --- a/test/Mono.Linker.Tests.Cases/Extensibility/SubStepDispatcherFields.cs +++ b/test/Mono.Linker.Tests.Cases/Extensibility/SubStepDispatcherFields.cs @@ -6,8 +6,8 @@ namespace Mono.Linker.Tests.Cases.Extensibility #if !NETCOREAPP [IgnoreTestCase ("Specific to the illink build")] #endif - [SetupCompileBefore ("MyDispatcher.dll", new[] { "Dependencies/MyDispatcher.cs", "Dependencies/CustomSubStepFields.cs" }, new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] - [SetupLinkerArgument ("--custom-step", "-MarkStep:MyDispatcher,MyDispatcher.dll")] + [SetupCompileBefore ("MyDispatcherFields.dll", new[] { "Dependencies/MyDispatcher.cs", "Dependencies/CustomSubStepFields.cs" }, new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] + [SetupLinkerArgument ("--custom-step", "-MarkStep:MyDispatcher,MyDispatcherFields.dll")] public class SubStepDispatcherFields { public static void Main () diff --git a/test/Mono.Linker.Tests.Cases/Extensibility/SubStepDispatcherUsage.cs b/test/Mono.Linker.Tests.Cases/Extensibility/SubStepDispatcherUsage.cs index 7a539d73514d..7dbdbc9947b3 100644 --- a/test/Mono.Linker.Tests.Cases/Extensibility/SubStepDispatcherUsage.cs +++ b/test/Mono.Linker.Tests.Cases/Extensibility/SubStepDispatcherUsage.cs @@ -6,8 +6,8 @@ namespace Mono.Linker.Tests.Cases.Extensibility #if !NETCOREAPP [IgnoreTestCase ("Specific to the illink build")] #endif - [SetupCompileBefore ("MyDispatcher.dll", new[] { "Dependencies/MyDispatcher.cs", "Dependencies/CustomSubStep.cs" }, new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] - [SetupLinkerArgument ("--custom-step", "-MarkStep:MyDispatcher,MyDispatcher.dll")] + [SetupCompileBefore ("MyDispatcherUsage.dll", new[] { "Dependencies/MyDispatcher.cs", "Dependencies/CustomSubStep.cs" }, new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] + [SetupLinkerArgument ("--custom-step", "-MarkStep:MyDispatcher,MyDispatcherUsage.dll")] public class SubStepDispatcherUsage { public static void Main ()