diff --git a/NuGet.config b/NuGet.config index 82b1ce9063aa65..1eaea524958636 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + diff --git a/src/tasks/WasmAppBuilder/IcallTableGenerator.cs b/src/tasks/WasmAppBuilder/IcallTableGenerator.cs index 7a59ce7bbf7fb3..802ec18190057c 100644 --- a/src/tasks/WasmAppBuilder/IcallTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/IcallTableGenerator.cs @@ -34,7 +34,7 @@ public IcallTableGenerator(Func fixupSymbolName, TaskLoggingHelp // The runtime icall table should be generated using // mono --print-icall-table // - public IEnumerable Generate(string? runtimeIcallTableFile, string[] assemblies, string? outputPath) + public IEnumerable Generate(string? runtimeIcallTableFile, IEnumerable assemblies, string? outputPath) { _icalls.Clear(); _signatures.Clear(); @@ -44,9 +44,13 @@ public IEnumerable Generate(string? runtimeIcallTableFile, string[] asse var resolver = new PathAssemblyResolver(assemblies); using var mlc = new MetadataLoadContext(resolver, "System.Private.CoreLib"); - foreach (var aname in assemblies) + foreach (var asmPath in assemblies) { - var a = mlc.LoadFromAssemblyPath(aname); + if (!File.Exists(asmPath)) + throw new LogAsErrorException($"Cannot find assembly {asmPath}"); + + Log.LogMessage(MessageImportance.Low, $"Loading {asmPath} to scan for icalls"); + var a = mlc.LoadFromAssemblyPath(asmPath); foreach (var type in a.GetTypes()) ProcessType(type); } diff --git a/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs b/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs index 1dff74a9dcc1c1..9b04d02c670f99 100644 --- a/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs @@ -1,9 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Linq; +using System.Reflection.PortableExecutable; using System.Text; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -11,7 +14,7 @@ public class ManagedToNativeGenerator : Task { [Required] - public string[]? Assemblies { get; set; } + public string[] Assemblies { get; set; } = Array.Empty(); public string? RuntimeIcallTableFile { get; set; } @@ -62,12 +65,14 @@ public override bool Execute() private void ExecuteInternal() { + List managedAssemblies = FilterOutUnmanagedBinaries(Assemblies); + var pinvoke = new PInvokeTableGenerator(FixupSymbolName, Log); var icall = new IcallTableGenerator(FixupSymbolName, Log); IEnumerable cookies = Enumerable.Concat( - pinvoke.Generate(PInvokeModules, Assemblies!, PInvokeOutputPath!), - icall.Generate(RuntimeIcallTableFile, Assemblies!, IcallOutputPath) + pinvoke.Generate(PInvokeModules, managedAssemblies, PInvokeOutputPath!), + icall.Generate(RuntimeIcallTableFile, managedAssemblies, IcallOutputPath) ); var m2n = new InterpToNativeGenerator(Log); @@ -110,4 +115,43 @@ public string FixupSymbolName(string name) _symbolNameFixups[name] = fixedName; return fixedName; } + + private List FilterOutUnmanagedBinaries(string[] assemblies) + { + List managedAssemblies = new(assemblies.Length); + foreach (string asmPath in Assemblies) + { + if (!File.Exists(asmPath)) + throw new LogAsErrorException($"Cannot find assembly {asmPath}"); + + try + { + if (!IsManagedAssembly(asmPath)) + { + Log.LogMessage(MessageImportance.Low, $"Skipping unmanaged {asmPath}."); + continue; + } + } + catch (Exception ex) + { + Log.LogMessage(MessageImportance.Low, $"Failed to read assembly {asmPath}: {ex}"); + throw new LogAsErrorException($"Failed to read assembly {asmPath}: {ex.Message}"); + } + + managedAssemblies.Add(asmPath); + } + + return managedAssemblies; + } + + private static bool IsManagedAssembly(string filePath) + { + if (!File.Exists(filePath)) + return false; + + using FileStream fileStream = File.OpenRead(filePath); + using PEReader reader = new(fileStream, PEStreamOptions.Default); + return reader.HasMetadata; + } + } diff --git a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs index 932a8424d513a4..12836d3d5a71e5 100644 --- a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -24,7 +24,7 @@ public PInvokeTableGenerator(Func fixupSymbolName, TaskLoggingHe _fixupSymbolName = fixupSymbolName; } - public IEnumerable Generate(string[] pinvokeModules, string[] assemblies, string outputPath) + public IEnumerable Generate(string[] pinvokeModules, IEnumerable assemblies, string outputPath) { var modules = new Dictionary(); foreach (var module in pinvokeModules) @@ -37,9 +37,14 @@ public IEnumerable Generate(string[] pinvokeModules, string[] assemblies var resolver = new PathAssemblyResolver(assemblies); using var mlc = new MetadataLoadContext(resolver, "System.Private.CoreLib"); - foreach (var aname in assemblies) + + foreach (var asmPath in assemblies) { - var a = mlc.LoadFromAssemblyPath(aname); + if (!File.Exists(asmPath)) + throw new LogAsErrorException($"Cannot find assembly {asmPath}"); + + Log.LogMessage(MessageImportance.Low, $"Loading {asmPath} to scan for pinvokes"); + var a = mlc.LoadFromAssemblyPath(asmPath); foreach (var type in a.GetTypes()) CollectPInvokes(pinvokes, callbacks, signatures, type); }