Skip to content

Instantly share code, notes, and snippets.

@wotakuro
Last active January 7, 2021 10:43
Show Gist options
  • Save wotakuro/296c6483638bcf17aa7d68a934a7c25d to your computer and use it in GitHub Desktop.
Save wotakuro/296c6483638bcf17aa7d68a934a7c25d to your computer and use it in GitHub Desktop.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEditor.UnityLinker;
using UnityEngine;
namespace UTJ
{
public class LinkerProcessor : IUnityLinkerProcessor
{
public int callbackOrder => 0;
private Dictionary<Assembly, HashSet<Type>> reservedInfo = new Dictionary<Assembly, HashSet<Type>>();
public string GenerateAdditionalLinkXmlFile(BuildReport report, UnityLinkerBuildPipelineData data)
{
ReserveAllType();
var sb = new StringBuilder();
// Header
sb.AppendLine("<linker>");
foreach (var kvs in reservedInfo)
{
var assembly = kvs.Key;
sb.AppendLine($" <assembly fullname=\"{assembly.GetName().Name}\">");
foreach (var type in kvs.Value)
{
sb.AppendLine($" <type fullname=\"{FormatForXml(ToCecilName(type.FullName))}\" preserve=\"all\"/>");
}
sb.AppendLine(" </assembly>");
}
sb.AppendLine("</linker>");
// Create a file with the content
var filePathName = Path.Combine(data.inputDirectory, "AppStripping.xml");
File.WriteAllText(filePathName, sb.ToString());
return filePathName;
}
// ココに追加したいものを列挙
protected virtual void ReserveAllType()
{
AddInterfaceImplClass(typeof(Unity.Entities.ICustomBootstrap));
/*
AddAllTypeInAssembly("Unity.Transforms.Generated");
AddAllTypeInAssembly("Unity.NetCode.Generated");
AddAllTypeInAssembly("Unity.Transforms.Generated");
AddAllTypeInAssembly("Unity.NetCode");
AddType(typeof(Unity.NetCode.ClientServerBootstrap));
*/
}
protected void AddType(Type t)
{
var asm = t.Assembly;
HashSet<Type> types;
if (!reservedInfo.TryGetValue(asm, out types))
{
types = new HashSet<Type>();
reservedInfo.Add(asm, types);
}
if (!types.Contains(t))
{
types.Add(t);
}
}
protected void AddAllTypeInAssembly(string assemlyName)
{
var asms = System.AppDomain.CurrentDomain.GetAssemblies();
foreach (var asm in asms)
{
if (asm.GetName().Name == assemlyName)
{
AddAllTypeInAssembly(asm);
return;
}
}
Debug.LogError("No match Assembly Name" + assemlyName);
}
protected void AddAllTypeInAssembly(Assembly asm)
{
HashSet<Type> types;
var allTypes = asm.GetTypes();
if (!reservedInfo.TryGetValue(asm, out types))
{
types = new HashSet<Type>();
reservedInfo.Add(asm, types);
}
foreach (var t in allTypes)
{
if (!types.Contains(t))
{
types.Add(t);
}
}
}
protected void AddInterfaceImplClass(Type interfaceType)
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
//参照していないものをスキップ
if (!IsReference(assembly, interfaceType.Assembly))
{
continue;
}
foreach (var type in assembly.GetTypes())
{
if (interfaceType.IsAssignableFrom(type))
{
this.AddType(type);
}
}
}
}
private bool IsReference(Assembly src, Assembly reference)
{
var asms = src.GetReferencedAssemblies();
string referenceName = reference.GetName().Name;
foreach (var asm in asms)
{
if (asm.Name == referenceName)
{
return true;
}
}
return false;
}
static string ToCecilName(string fullTypeName)
{
return fullTypeName.Replace('+', '/');
}
static string FormatForXml(string value)
{
return value.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;");
}
public void OnAfterRun(BuildReport report, UnityLinkerBuildPipelineData data)
{
}
public void OnBeforeRun(BuildReport report, UnityLinkerBuildPipelineData data)
{
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment