using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace ET
{
public static class LuaCompiler
{
private sealed class CompiledFail: Exception
{
public CompiledFail(string message): base(message)
{
}
}
public static readonly string outDir = Application.dataPath + "/Bundles/Lua/";
private const string dotnet = "dotnet";
private static readonly string toolsDir = "./Tools/CSharpLua";
private static readonly string csharpLua = toolsDir + "/CSharp.lua/CSharp.lua.Launcher.dll";
///
/// 编译Dll为Lua
///
/// Dll名
/// Dll文件夹
/// 输出Lua文件夹名
/// 需要被编译成Lua的Dll引用名
/// 是否其他模块被引用
public static void Compile(string dllName, string dllDir, string outDirName, List referencedLuaAssemblies, bool isModule)
{
if (!CheckDotnetInstall())
{
return;
}
if (!File.Exists(csharpLua))
{
throw new InvalidProgramException($"{csharpLua} not found");
}
var outputDir = outDir + outDirName;
if (Directory.Exists(outputDir))
{
Directory.Delete(outputDir, true);
}
HashSet libs = new HashSet();
FillUnityLibraries(libs);
AssemblyName assemblyName = new AssemblyName(dllName);
Assembly assembly = Assembly.Load(assemblyName);
foreach (var referenced in assembly.GetReferencedAssemblies())
{
if (referenced.Name != "mscorlib" && !referenced.Name.StartsWith("System"))
{
string libPath = Assembly.Load(referenced).Location;
if (referencedLuaAssemblies != null && referencedLuaAssemblies.Contains(referenced.Name))
{
libPath += "!";
}
libs.Add(libPath);
}
}
string lib = string.Join(";", libs.ToArray());
string args = $"{csharpLua} -s \"{dllDir}\" -d \"{outputDir}\" -l \"{lib}\" -m -c -a -e -ei";
UnityEngine.Debug.Log(args);
if (isModule)
{
args += " -module";
}
string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
if (!string.IsNullOrEmpty(definesString))
{
args += $" -csc -define:{definesString}";
}
var info = new ProcessStartInfo()
{
FileName = dotnet,
Arguments = args,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
StandardOutputEncoding = Encoding.UTF8,
StandardErrorEncoding = Encoding.UTF8,
CreateNoWindow = true
};
using (var p = Process.Start(info))
{
p.WaitForExit();
if (p.ExitCode == 0)
{
UnityEngine.Debug.Log("compile success");
}
else
{
string outString = p.StandardOutput.ReadToEnd();
string errorString = p.StandardError.ReadToEnd();
throw new CompiledFail($"Compile fail, {errorString}\n{outString}\n{dotnet} {args}");
}
}
}
private static void FillUnityLibraries(HashSet libs)
{
string unityObjectPath = typeof (UnityEngine.Object).Assembly.Location;
string baseDir = Path.GetDirectoryName(unityObjectPath);
foreach (string path in Directory.EnumerateFiles(baseDir, "*.dll"))
{
libs.Add(path);
}
}
private static bool CheckDotnetInstall()
{
bool has = InternalCheckDotnetInstall();
if (!has)
{
UnityEngine.Debug.LogWarning("not found dotnet");
if (EditorUtility.DisplayDialog("dotnet未安装", "未安装.NET Core 3.0+运行环境,点击确定前往安装", "确定", "取消"))
{
Application.OpenURL("https://www.microsoft.com/net/download");
}
}
return has;
}
private static bool InternalCheckDotnetInstall()
{
var info = new ProcessStartInfo()
{
FileName = dotnet,
Arguments = "--version",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
StandardOutputEncoding = Encoding.UTF8,
StandardErrorEncoding = Encoding.UTF8,
};
try
{
using (var p = Process.Start(info))
{
p.WaitForExit();
if (p.ExitCode == 0)
{
string version = p.StandardOutput.ReadToEnd();
UnityEngine.Debug.LogFormat("found dotnet {0}", version);
int major = version[0] - '0';
if (major >= 3)
{
return true;
}
else
{
UnityEngine.Debug.LogErrorFormat("dotnet verson {0} must >= 3.0", version);
}
}
return false;
}
}
catch (Exception e)
{
UnityEngine.Debug.LogException(e);
return false;
}
}
}
}