Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wasm] ManagedToNativeGenerator: Skip unmanaged dlls #81066

Merged
merged 3 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/mono/wasm/host/CommonConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal sealed class CommonConfiguration
public WasmHost Host { get; init; }
public HostConfig HostConfig { get; init; }
public WasmHostProperties HostProperties { get; init; }
public IEnumerable<string> HostArguments { get; init; }

private string? hostArg;
private string? _runtimeConfigPath;
Expand All @@ -30,11 +31,13 @@ internal sealed class CommonConfiguration

private CommonConfiguration(string[] args)
{
List<string> hostArgsList = new();
var options = new OptionSet
{
{ "debug|d", "Start debug server", _ => Debugging = true },
{ "host|h=", "Host config name", v => hostArg = v },
{ "runtime-config|r=", "runtimeconfig.json path for the app", v => _runtimeConfigPath = v }
{ "runtime-config|r=", "runtimeconfig.json path for the app", v => _runtimeConfigPath = v },
{ "extra-host-arg=", "Extra argument to be passed to the host", hostArgsList.Add },
};

RemainingArgs = options.Parse(args);
Expand Down Expand Up @@ -95,6 +98,9 @@ private CommonConfiguration(string[] args)
if (!Enum.TryParse(HostConfig.HostString, ignoreCase: true, out WasmHost wasmHost))
throw new CommandLineException($"Unknown host {HostConfig.HostString} in config named {HostConfig.Name}");
Host = wasmHost;

hostArgsList.AddRange(HostConfig.HostArguments);
HostArguments = hostArgsList;
}

public ProxyOptions ToProxyOptions()
Expand Down
5 changes: 2 additions & 3 deletions src/mono/wasm/host/JSEngineHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ public static async Task<int> InvokeAsync(CommonConfiguration commonArgs,

private async Task<int> RunAsync()
{
string[] engineArgs = Array.Empty<string>();

string engineBinary = _args.Host switch
{
WasmHost.V8 => "v8",
Expand Down Expand Up @@ -79,9 +77,10 @@ private async Task<int> RunAsync()
args.Add("--expose_wasm");
}

args.AddRange(_args.CommonConfig.HostArguments);

args.Add(_args.JSPath!);

args.AddRange(engineArgs);
if (_args.Host is WasmHost.V8 or WasmHost.JavaScriptCore)
{
// v8/jsc want arguments to the script separated by "--", others don't
Expand Down
2 changes: 2 additions & 0 deletions src/mono/wasm/host/RuntimeConfigJson.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
Expand Down Expand Up @@ -32,6 +33,7 @@ internal sealed record WasmHostProperties(

internal sealed record HostConfig(string? Name, [property: JsonPropertyName("host")] string? HostString)
{
[property: JsonPropertyName("host-args")] public string[] HostArguments { get; set; } = Array.Empty<string>();
// using an explicit property because the deserializer doesn't like
// extension data in the record constructor
[property: JsonExtensionData] public Dictionary<string, JsonElement>? Properties { get; set; }
Expand Down
8 changes: 6 additions & 2 deletions src/tasks/WasmAppBuilder/IcallTableGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ public IEnumerable<string> 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);
}
Expand Down
50 changes: 47 additions & 3 deletions src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
// 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;

public class ManagedToNativeGenerator : Task
{
[Required]
public string[]? Assemblies { get; set; }
public string[] Assemblies { get; set; } = Array.Empty<string>();

public string? RuntimeIcallTableFile { get; set; }

Expand Down Expand Up @@ -62,12 +65,14 @@ public override bool Execute()

private void ExecuteInternal()
{
string[] managedAssemblies = FilterOutUnmanagedBinaries(Assemblies);

var pinvoke = new PInvokeTableGenerator(FixupSymbolName, Log);
var icall = new IcallTableGenerator(FixupSymbolName, Log);

IEnumerable<string> 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);
Expand Down Expand Up @@ -110,4 +115,43 @@ public string FixupSymbolName(string name)
_symbolNameFixups[name] = fixedName;
return fixedName;
}

private string[] FilterOutUnmanagedBinaries(string[] assemblies)
{
List<string> 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.ToArray();
radical marked this conversation as resolved.
Show resolved Hide resolved
}

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;
}

}
8 changes: 6 additions & 2 deletions src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@ public IEnumerable<string> 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);
}
Expand Down