Add linker to wasm build task
This commit is contained in:
parent
664bcbb8ec
commit
7d70351418
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "Ooui.Wasm.Build.Tasks/linker"]
|
||||||
|
path = Ooui.Wasm.Build.Tasks/linker
|
||||||
|
url = git@github.com:mono/linker.git
|
|
@ -9,6 +9,9 @@ using Microsoft.Build.Framework;
|
||||||
using Microsoft.Build.Utilities;
|
using Microsoft.Build.Utilities;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Mono.Cecil;
|
using Mono.Cecil;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Mono.Linker;
|
||||||
|
using Mono.Linker.Steps;
|
||||||
|
|
||||||
namespace Ooui.Wasm.Build.Tasks
|
namespace Ooui.Wasm.Build.Tasks
|
||||||
{
|
{
|
||||||
|
@ -82,9 +85,6 @@ namespace Ooui.Wasm.Build.Tasks
|
||||||
distPath = Path.Combine (outputPath, "dist");
|
distPath = Path.Combine (outputPath, "dist");
|
||||||
managedPath = Path.Combine (distPath, "managed");
|
managedPath = Path.Combine (distPath, "managed");
|
||||||
Directory.CreateDirectory (managedPath);
|
Directory.CreateDirectory (managedPath);
|
||||||
//foreach (var dll in Directory.GetFiles (managedPath, "*.dll")) {
|
|
||||||
// File.Delete (dll);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyRuntime ()
|
void CopyRuntime ()
|
||||||
|
@ -99,35 +99,124 @@ namespace Ooui.Wasm.Build.Tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> linkedAsmNames;
|
|
||||||
List<string> linkedAsmPaths;
|
List<string> linkedAsmPaths;
|
||||||
|
|
||||||
void LinkAssemblies ()
|
void LinkAssemblies ()
|
||||||
{
|
{
|
||||||
var references = ReferencePath.Split (';').Select (x => x.Trim ()).Where (x => x.Length > 0).ToList ();
|
var references = ReferencePath.Split (';').Select (x => x.Trim ()).Where (x => x.Length > 0).ToList ();
|
||||||
references.Add (Path.GetFullPath (Assembly));
|
var refpaths = new List<string> ();
|
||||||
|
|
||||||
linkedAsmPaths = new List<string> ();
|
|
||||||
foreach (var r in references) {
|
foreach (var r in references) {
|
||||||
var name = Path.GetFileName (r);
|
var name = Path.GetFileName (r);
|
||||||
if (bclAssemblies.ContainsKey (name)) {
|
if (bclAssemblies.ContainsKey (name)) {
|
||||||
linkedAsmPaths.Add (bclAssemblies[name]);
|
refpaths.Add (bclAssemblies[name]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
linkedAsmPaths.Add (r);
|
refpaths.Add (r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
linkedAsmNames = new List<string> ();
|
var asmPath = Path.GetFullPath (Assembly);
|
||||||
foreach (var l in linkedAsmPaths) {
|
|
||||||
var name = Path.GetFileName (l);
|
var pipeline = GetLinkerPipeline ();
|
||||||
linkedAsmNames.Add (name);
|
using (var context = new LinkContext (pipeline)) {
|
||||||
var dest = Path.Combine (managedPath, name);
|
context.CoreAction = AssemblyAction.CopyUsed;
|
||||||
if (bclAssemblies.ContainsKey (name) && File.Exists (dest))
|
context.UserAction = AssemblyAction.CopyUsed;
|
||||||
continue;
|
context.OutputDirectory = managedPath;
|
||||||
File.Copy (l, dest, true);
|
|
||||||
Log.LogMessage ($"Managed {l} -> {dest}");
|
pipeline.PrependStep (new ResolveFromAssemblyStep (asmPath, ResolveFromAssemblyStep.RootVisibility.Any));
|
||||||
|
|
||||||
|
var refdirs = refpaths.Select (x => Path.GetDirectoryName (x)).Distinct ().ToList ();
|
||||||
|
refdirs.Insert (0, Path.Combine (bclPath, "Facades"));
|
||||||
|
refdirs.Insert (0, bclPath);
|
||||||
|
foreach (var d in refdirs.Distinct ()) {
|
||||||
|
context.Resolver.AddSearchDirectory (d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pipeline.AddStepAfter (typeof (LoadReferencesStep), new LoadI18nAssemblies (I18nAssemblies.None));
|
||||||
|
|
||||||
|
foreach (var dll in Directory.GetFiles (managedPath, "*.dll")) {
|
||||||
|
File.Delete (dll);
|
||||||
|
}
|
||||||
|
pipeline.Process (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
linkedAsmPaths = Directory.GetFiles (managedPath, "*.dll").OrderBy (x => Path.GetFileName (x)).ToList ();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PreserveUsingAttributesStep : ResolveStep
|
||||||
|
{
|
||||||
|
readonly HashSet<string> ignoreAsmNames;
|
||||||
|
|
||||||
|
public PreserveUsingAttributesStep (IEnumerable<string> ignoreAsmNames)
|
||||||
|
{
|
||||||
|
this.ignoreAsmNames = new HashSet<string> (ignoreAsmNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Process ()
|
||||||
|
{
|
||||||
|
var asms = Context.GetAssemblies ();
|
||||||
|
foreach (var a in asms.Where (x => !ignoreAsmNames.Contains (x.Name.Name))) {
|
||||||
|
foreach (var m in a.Modules) {
|
||||||
|
foreach (var t in m.Types) {
|
||||||
|
PreserveTypeIfRequested (t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreserveTypeIfRequested (TypeDefinition type)
|
||||||
|
{
|
||||||
|
var typePreserved = IsTypePreserved (type);
|
||||||
|
if (IsTypePreserved (type)) {
|
||||||
|
MarkAndPreserveAll (type);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foreach (var m in type.Methods.Where (IsMethodPreserved)) {
|
||||||
|
Annotations.AddPreservedMethod (type, m);
|
||||||
|
}
|
||||||
|
foreach (var t in type.NestedTypes) {
|
||||||
|
PreserveTypeIfRequested (t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsTypePreserved (TypeDefinition m)
|
||||||
|
{
|
||||||
|
return m.CustomAttributes.FirstOrDefault (x => x.AttributeType.Name.StartsWith ("Preserve", StringComparison.Ordinal)) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsMethodPreserved (MethodDefinition m)
|
||||||
|
{
|
||||||
|
return m.CustomAttributes.FirstOrDefault (x => x.AttributeType.Name.StartsWith ("Preserve", StringComparison.Ordinal)) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkAndPreserveAll (TypeDefinition type)
|
||||||
|
{
|
||||||
|
Annotations.MarkAndPush (type);
|
||||||
|
Annotations.SetPreserve (type, TypePreserve.All);
|
||||||
|
if (!type.HasNestedTypes) {
|
||||||
|
Tracer.Pop ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (TypeDefinition nested in type.NestedTypes)
|
||||||
|
MarkAndPreserveAll (nested);
|
||||||
|
Tracer.Pop ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pipeline GetLinkerPipeline ()
|
||||||
|
{
|
||||||
|
var p = new Pipeline ();
|
||||||
|
p.AppendStep (new LoadReferencesStep ());
|
||||||
|
p.AppendStep (new PreserveUsingAttributesStep (bclAssemblies.Values.Select (Path.GetFileNameWithoutExtension)));
|
||||||
|
p.AppendStep (new BlacklistStep ());
|
||||||
|
p.AppendStep (new TypeMapStep ());
|
||||||
|
p.AppendStep (new MarkStep ());
|
||||||
|
p.AppendStep (new SweepStep ());
|
||||||
|
p.AppendStep (new CleanStep ());
|
||||||
|
p.AppendStep (new RegenerateGuidStep ());
|
||||||
|
p.AppendStep (new OutputStep ());
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractClientJs ()
|
void ExtractClientJs ()
|
||||||
|
@ -182,7 +271,7 @@ namespace Ooui.Wasm.Build.Tasks
|
||||||
<script type=""text/javascript"">
|
<script type=""text/javascript"">
|
||||||
var assemblies = [");
|
var assemblies = [");
|
||||||
var head = "";
|
var head = "";
|
||||||
foreach (var l in linkedAsmNames) {
|
foreach (var l in linkedAsmPaths.Select (x => Path.GetFileName (x))) {
|
||||||
w.Write (head);
|
w.Write (head);
|
||||||
w.Write ('\"');
|
w.Write ('\"');
|
||||||
w.Write (l);
|
w.Write (l);
|
||||||
|
|
|
@ -16,4 +16,12 @@
|
||||||
<ProjectReference Include="..\Ooui\Ooui.csproj" />
|
<ProjectReference Include="..\Ooui\Ooui.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="linker\**" />
|
||||||
|
<Compile Include="linker\linker\Linker\**" />
|
||||||
|
<Compile Remove="linker\linker\Linker\Driver.cs" />
|
||||||
|
<Compile Include="linker\linker\Linker.Steps\**" />
|
||||||
|
<Compile Remove="linker\linker\Linker\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit a4f1133b0b06ec3d152b41186732f485413bd1c9
|
|
@ -0,0 +1,8 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ooui
|
||||||
|
{
|
||||||
|
class PreserveAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ooui
|
namespace Ooui
|
||||||
{
|
{
|
||||||
|
@ -596,6 +597,7 @@ namespace Ooui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Preserve]
|
||||||
public static void StartWebAssemblySession (string sessionId, string globalElementId, string initialSize)
|
public static void StartWebAssemblySession (string sessionId, string globalElementId, string initialSize)
|
||||||
{
|
{
|
||||||
Element element;
|
Element element;
|
||||||
|
@ -613,6 +615,7 @@ namespace Ooui
|
||||||
g.StartSession ();
|
g.StartSession ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Preserve]
|
||||||
public static void ReceiveWebAssemblySessionMessageJson (string sessionId, string json)
|
public static void ReceiveWebAssemblySessionMessageJson (string sessionId, string json)
|
||||||
{
|
{
|
||||||
WebAssemblySession g;
|
WebAssemblySession g;
|
||||||
|
|
Loading…
Reference in New Issue