From dc2f8a1b4c372dfb0c05166b26ffab1c32b0018e Mon Sep 17 00:00:00 2001 From: Rob LaDuca Date: Tue, 10 Dec 2019 15:22:13 -0800 Subject: [PATCH 1/5] Stop using MSBuild Locator to find IL tools. Instead, use a private set of matched tools (from .NET 4.7.2) so that we can always ensure round-tripping works and we do not need to require .NET Framework SDKs to be installed. --- eng/Versions.props | 1 + .../tools/InjectModuleInitializer.targets | 848 +++++++++--------- global.json | 3 +- 3 files changed, 411 insertions(+), 441 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 3fe3ad70c71..4c82af33b24 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -73,6 +73,7 @@ 5.28.1.1-1 0.0.0.1 + 0.0.0.1 diff --git a/eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets b/eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets index f70fd663d88..e4cfd5a0550 100644 --- a/eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets +++ b/eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets @@ -1,440 +1,408 @@ - - - - - - - - - - - - - $(Pkgruntime_win-x86_Microsoft_NETCore_ILDAsm)\runtimes\$(WpfRuntimeIdentifier)\native\ - $(Pkgruntime_win-x86_Microsoft_NETCore_ILAsm)\runtimes\$(WpfRuntimeIdentifier)\native\ - $(Pkgruntime_win-x86_Microsoft_NETCore_Runtime_CoreCLR)\runtimes\$(WpfRuntimeIdentifier)\native\ - - - - $(Pkgruntime_win-x64_Microsoft_NETCore_ILDAsm)\runtimes\$(WpfRuntimeIdentifier)\native\ - $(Pkgruntime_win-x64_Microsoft_NETCore_ILAsm)\runtimes\$(WpfRuntimeIdentifier)\native\ - $(Pkgruntime_win-x64_Microsoft_NETCore_Runtime_CoreCLR)\runtimes\$(WpfRuntimeIdentifier)\native\ - - - - - $(ArtifactsTmpDir)\iltools\$(PackageRuntimeIdentifierPrefix)\ - $(ILToolsPath)ildasm.exe - $(ILToolsPath)ilasm.exe - - - - - - - RoslynCodeTaskFactory - $(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Bitness64 - Bitness32 - - - - - - - - - - - $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName)$(TargetExt)')) - $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName).il')) - - - - - - - - - - - - $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName).il')) - $(WpfArcadeSdkToolsDir)InjectModuleInitializer\ModuleInitializer.il - $(WpfArcadeSdkToolsDir)InjectModuleInitializer\MsCorLibAssemblySection.il - - - - - - - - - - $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName)$(TargetExt)')) - $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName).res')) - $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName).il')) - - - - - false - true - - - - - - - - - - - + + + + + + + + + + + + + $(Pkgruntime_win-x86_Microsoft_NETCore_ILDAsm)\runtimes\$(WpfRuntimeIdentifier)\native\ + $(Pkgruntime_win-x86_Microsoft_NETCore_ILAsm)\runtimes\$(WpfRuntimeIdentifier)\native\ + $(Pkgruntime_win-x86_Microsoft_NETCore_Runtime_CoreCLR)\runtimes\$(WpfRuntimeIdentifier)\native\ + + + + $(Pkgruntime_win-x64_Microsoft_NETCore_ILDAsm)\runtimes\$(WpfRuntimeIdentifier)\native\ + $(Pkgruntime_win-x64_Microsoft_NETCore_ILAsm)\runtimes\$(WpfRuntimeIdentifier)\native\ + $(Pkgruntime_win-x64_Microsoft_NETCore_Runtime_CoreCLR)\runtimes\$(WpfRuntimeIdentifier)\native\ + + + + + $(ArtifactsTmpDir)\iltools\$(PackageRuntimeIdentifierPrefix)\ + $(ILToolsPath)ildasm.exe + $(ILToolsPath)ilasm.exe + + + + + + + $(RepositoryToolsDir)native\bin\net-framework-472-iltools\$(NetFramework472IlToolsVersion)\ + $(Net472IlToolsDir)ildasm.exe + $(Net472IlToolsDir)ilasm.exe + + + + + + RoslynCodeTaskFactory + $(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName)$(TargetExt)')) + $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName).il')) + + + + + + + + + + + + $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName).il')) + $(WpfArcadeSdkToolsDir)InjectModuleInitializer\ModuleInitializer.il + $(WpfArcadeSdkToolsDir)InjectModuleInitializer\MsCorLibAssemblySection.il + + + + + + + + + + $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName)$(TargetExt)')) + $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName).res')) + $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(AssemblyName).il')) + + + + + false + true + + + + + + + + + + + diff --git a/global.json b/global.json index 50ef0bb08f6..e6be00cdcac 100644 --- a/global.json +++ b/global.json @@ -19,6 +19,7 @@ "strawberry-perl": "5.28.1.1-1", "net-framework-48-ref-assemblies": "0.0.0.1", "dotnet-api-docs_netcoreapp3.0": "0.0.0.2", - "msvcurt-c1xx": "0.0.0.8" + "msvcurt-c1xx": "0.0.0.8", + "net-framework-472-iltools": "0.0.0.1" } } From 1d70b7e1b84c5f500d1096d498c9d3ec53590015 Mon Sep 17 00:00:00 2001 From: Rob LaDuca Date: Tue, 10 Dec 2019 16:08:07 -0800 Subject: [PATCH 2/5] Ensure the mscorlib reference is added prior to the module constructor that needs it. This allows ILAsm to properly create the module reference without inference (which fails for private tools not run from Framework installations). --- .../AddModuleConstructorTask.cs | 160 +++++++++--------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs index 2e0739b8c32..407779661f9 100644 --- a/eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs +++ b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs @@ -1,80 +1,80 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Text.RegularExpressions; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace WpfArcadeSdk.Build.Tasks -{ - /// - /// Append the supplied module constructor to the supplied IL file. - /// Using this requires that the DLL has implemented a static class named - /// ModuleInitializer with a static void Initialize function. This class - /// is called from the module initializer. - /// - public class AddModuleConstructorTask : Task - { - /// - /// The original IL file to manipulate - /// - [Required] - public string ILFile { get; set; } - - /// - /// Contains the IL section referencing mscorlib. - /// This is inserted if not already present. - /// - [Required] - public string MsCorLibAssemblySectionIL { get; set; } - - /// - /// Contains the IL of the module constructor - /// - [Required] - public string ModuleConstructorIL { get; set; } - - public override bool Execute() - { - try - { - var moduleConstructorIL = File.ReadAllText(ModuleConstructorIL); - var msCorLibAssemblySectionIL = File.ReadAllText(MsCorLibAssemblySectionIL); - var sourceIL = File.ReadAllText(ILFile); - - using (var outputIL = new StreamWriter(File.Open(ILFile, FileMode.Truncate))) - { - if (Regex.Match(sourceIL, @"\.class.+?ModuleInitializer.+?\.method.+?static.+?Initialize\(\).+?end of class ModuleInitializer", RegexOptions.Singleline) == Match.Empty) - { - Log.LogError("Inserting a module initializer requires the assembly to implement a class named ModuleInitializer with a static parameterless method named Initialize."); - return false; - } - - if (Regex.Match(sourceIL, @"\.assembly extern mscorlib", RegexOptions.Singleline) == Match.Empty) - { - outputIL.WriteLine(msCorLibAssemblySectionIL); - } - - if (Regex.Match(sourceIL, @"\.class private auto ansi '\'.+?\.method private hidebysig specialname rtspecialname static void \.cctor \(\) cil managed ", RegexOptions.Singleline) == Match.Empty) - { - outputIL.WriteLine(moduleConstructorIL); - } - else - { - Log.LogError("Cannot insert a module initializer into an assembly that already contains one."); - return false; - } - - outputIL.WriteLine(sourceIL); - } - - return true; - } - catch (Exception e) - { - Log.LogError(e.ToString() + Environment.NewLine + e.StackTrace); - return false; - } - } - } -} +using System; +using System.Diagnostics; +using System.IO; +using System.Text.RegularExpressions; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace WpfArcadeSdk.Build.Tasks +{ + /// + /// Append the supplied module constructor to the supplied IL file. + /// Using this requires that the DLL has implemented a static class named + /// ModuleInitializer with a static void Initialize function. This class + /// is called from the module initializer. + /// + public class AddModuleConstructorTask : Task + { + /// + /// The original IL file to manipulate + /// + [Required] + public string ILFile { get; set; } + + /// + /// Contains the IL section referencing mscorlib. + /// This is inserted if not already present. + /// + [Required] + public string MsCorLibAssemblySectionIL { get; set; } + + /// + /// Contains the IL of the module constructor + /// + [Required] + public string ModuleConstructorIL { get; set; } + + public override bool Execute() + { + try + { + var moduleConstructorIL = File.ReadAllText(ModuleConstructorIL); + var msCorLibAssemblySectionIL = File.ReadAllText(MsCorLibAssemblySectionIL); + var sourceIL = File.ReadAllText(ILFile); + + using (var outputIL = new StreamWriter(File.Open(ILFile, FileMode.Truncate))) + { + if (Regex.Match(sourceIL, @"\.assembly extern mscorlib", RegexOptions.Singleline) == Match.Empty) + { + outputIL.WriteLine(msCorLibAssemblySectionIL); + } + + if (Regex.Match(sourceIL, @"\.class.+?ModuleInitializer.+?\.method.+?static.+?Initialize\(\).+?end of class ModuleInitializer", RegexOptions.Singleline) == Match.Empty) + { + Log.LogError("Inserting a module initializer requires the assembly to implement a class named ModuleInitializer with a static parameterless method named Initialize."); + return false; + } + + if (Regex.Match(sourceIL, @"\.class private auto ansi '\'.+?\.method private hidebysig specialname rtspecialname static void \.cctor \(\) cil managed ", RegexOptions.Singleline) == Match.Empty) + { + outputIL.WriteLine(moduleConstructorIL); + } + else + { + Log.LogError("Cannot insert a module initializer into an assembly that already contains one."); + return false; + } + + outputIL.WriteLine(sourceIL); + } + + return true; + } + catch (Exception e) + { + Log.LogError(e.ToString() + Environment.NewLine + e.StackTrace); + return false; + } + } + } +} From 6f90d05eeef0f55940b1d252ff92637738e176f1 Mon Sep 17 00:00:00 2001 From: Rob LaDuca Date: Wed, 11 Dec 2019 10:31:44 -0800 Subject: [PATCH 3/5] Fix incorrect parameter passing in AddModuleConstructor Target --- eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets b/eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets index e4cfd5a0550..feecb93d894 100644 --- a/eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets +++ b/eng/WpfArcadeSdk/tools/InjectModuleInitializer.targets @@ -356,8 +356,8 @@ + MsCorLibAssemblySectionIL="$(MsCorLibAssemblySection)" + ModuleConstructorIL="$(ModuleInitializer)"/> From 5f9eb711d5a4936622a65055ccadea276dc8e802 Mon Sep 17 00:00:00 2001 From: Rob LaDuca Date: Wed, 11 Dec 2019 11:29:30 -0800 Subject: [PATCH 4/5] Removing .NET SDK req from the dev guide. --- Documentation/developer-guide.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/developer-guide.md b/Documentation/developer-guide.md index 85bc5d8463a..4621d98b8e9 100644 --- a/Documentation/developer-guide.md +++ b/Documentation/developer-guide.md @@ -16,7 +16,6 @@ WPF requires the following workloads and components be selected when installing * Required Individual Components: * C++/CLI support * Windows 10 SDK - * .NET 4.6.1 SDK or .NET 4.6.2 SDK (see [#2298](https://github.com/dotnet/wpf/issues/2298)) ## Workflow From 26ff0e2becd7ad96b76f72d2dca5df81e28a9394 Mon Sep 17 00:00:00 2001 From: Rob LaDuca Date: Wed, 11 Dec 2019 14:16:41 -0800 Subject: [PATCH 5/5] Fixup IL injection task to ensure that we always insert mscorlib reference then module initializer. In cases where there is an existing mscorlib reference, we just replace it with the combined ref + initializer. --- .../AddModuleConstructorTask.cs | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs index 407779661f9..37699d4cae6 100644 --- a/eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs +++ b/eng/WpfArcadeSdk/tools/InjectModuleInitializer/AddModuleConstructorTask.cs @@ -41,31 +41,33 @@ public override bool Execute() var moduleConstructorIL = File.ReadAllText(ModuleConstructorIL); var msCorLibAssemblySectionIL = File.ReadAllText(MsCorLibAssemblySectionIL); var sourceIL = File.ReadAllText(ILFile); + string ilToInject = msCorLibAssemblySectionIL + Environment.NewLine + moduleConstructorIL; using (var outputIL = new StreamWriter(File.Open(ILFile, FileMode.Truncate))) { - if (Regex.Match(sourceIL, @"\.assembly extern mscorlib", RegexOptions.Singleline) == Match.Empty) - { - outputIL.WriteLine(msCorLibAssemblySectionIL); - } - if (Regex.Match(sourceIL, @"\.class.+?ModuleInitializer.+?\.method.+?static.+?Initialize\(\).+?end of class ModuleInitializer", RegexOptions.Singleline) == Match.Empty) { Log.LogError("Inserting a module initializer requires the assembly to implement a class named ModuleInitializer with a static parameterless method named Initialize."); return false; } - if (Regex.Match(sourceIL, @"\.class private auto ansi '\'.+?\.method private hidebysig specialname rtspecialname static void \.cctor \(\) cil managed ", RegexOptions.Singleline) == Match.Empty) - { - outputIL.WriteLine(moduleConstructorIL); - } - else + if (Regex.Match(sourceIL, @"\.class private auto ansi '\'.+?\.method private hidebysig specialname rtspecialname static void \.cctor \(\) cil managed ", RegexOptions.Singleline) != Match.Empty) { Log.LogError("Cannot insert a module initializer into an assembly that already contains one."); return false; } - outputIL.WriteLine(sourceIL); + // Attempt to replace an existing mscorlib reference with the reference + module initializer. + string modifiedIL = Regex.Replace(sourceIL, @"\.assembly extern mscorlib.+};", ilToInject, RegexOptions.Singleline); + + // If we are given the same string back, there was nothing to replace. + // In that case write out the reference and initializer from scratch. + if (object.ReferenceEquals(modifiedIL, sourceIL)) + { + outputIL.WriteLine(ilToInject); + } + + outputIL.WriteLine(modifiedIL); } return true;