hybridclr_unity/Editor/Installer/InstallerController.cs

262 lines
9.2 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;
using System.Text.RegularExpressions;
namespace HybridCLR.Editor.Installer
{
public class InstallerController
{
private const string hybridclr_repo_path = "hybridclr_repo";
private const string il2cpp_plus_repo_path = "il2cpp_plus_repo";
public int MajorVersion => _curVersion.major;
private readonly UnityVersion _curVersion;
private readonly HybridclrVersionManifest _versionManifest;
private readonly HybridclrVersionInfo _curDefaultVersion;
public InstallerController()
{
_curVersion = ParseUnityVersion(Application.unityVersion);
_versionManifest = GetHybridCLRVersionManifest();
_curDefaultVersion = _versionManifest.versions.Find(v => v.unity_version == _curVersion.major.ToString());
}
private HybridclrVersionManifest GetHybridCLRVersionManifest()
{
string versionFile = $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/hybridclr_version.json";
return JsonUtility.FromJson<HybridclrVersionManifest>(File.ReadAllText(versionFile, Encoding.UTF8));
}
[Serializable]
class VersionDesc
{
public string branch;
//public string hash;
}
[Serializable]
class HybridclrVersionInfo
{
public string unity_version;
public VersionDesc hybridclr;
public VersionDesc il2cpp_plus;
}
[Serializable]
class HybridclrVersionManifest
{
public List<HybridclrVersionInfo> versions;
}
private class UnityVersion
{
public int major;
public int minor1;
public int minor2;
public override string ToString()
{
return $"{major}.{minor1}.{minor2}";
}
}
private static readonly Regex s_unityVersionPat = new Regex(@"(\d+)\.(\d+)\.(\d+)");
public const int min2021_3_CompatibleMinorVersion = 0;
public const int min2022_3_CompatibleMinorVersion = 0;
private UnityVersion ParseUnityVersion(string versionStr)
{
var matches = s_unityVersionPat.Matches(versionStr);
if (matches.Count == 0)
{
return null;
}
// 找最后一个匹配的
Match match = matches[matches.Count - 1];
// Debug.Log($"capture count:{match.Groups.Count} {match.Groups[1].Value} {match.Groups[2].Value}");
int major = int.Parse(match.Groups[1].Value);
int minor1 = int.Parse(match.Groups[2].Value);
int minor2 = int.Parse(match.Groups[3].Value);
return new UnityVersion { major = major, minor1 = minor1, minor2 = minor2 };
}
public string GetCurrentUnityVersionMinCompatibleVersionStr()
{
return GetMinCompatibleVersion(MajorVersion);
}
public string GetMinCompatibleVersion(int majorVersion)
{
switch(majorVersion)
{
case 2021: return $"2021.3.{min2021_3_CompatibleMinorVersion}";
case 2022: return $"2022.3.{min2022_3_CompatibleMinorVersion}";
default: throw new Exception($"not support version:{majorVersion}");
}
}
public bool IsComaptibleVersion()
{
UnityVersion version = _curVersion;
switch (version.major)
{
case 2021:
{
if (version.minor1 != 3)
{
return false;
}
return version.minor2 >= min2021_3_CompatibleMinorVersion;
}
case 2022:
{
if (version.minor1 != 3)
{
return false;
}
return version.minor2 >= min2022_3_CompatibleMinorVersion;
}
default: throw new Exception($"not support il2cpp_plus branch:{version.major}");
}
}
public string HybridclrLocalVersion => _curDefaultVersion.hybridclr.branch;
public string Il2cppPlusLocalVersion => _curDefaultVersion.il2cpp_plus.branch;
private string GetIl2CppPathByContentPath(string contentPath)
{
return $"{contentPath}/il2cpp";
}
public string ApplicationIl2cppPath => GetIl2CppPathByContentPath(EditorApplication.applicationContentsPath);
public void InstallDefaultHybridCLR()
{
InstallFromLocal(PrepareLibil2cppWithHybridclrFromGitRepo());
}
public bool HasInstalledHybridCLR()
{
return Directory.Exists($"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr");
}
private string GetUnityIl2CppDllInstallLocation()
{
#if UNITY_EDITOR_WIN
return $"{SettingsUtil.LocalIl2CppDir}/build/deploy/net471/Unity.IL2CPP.dll";
#else
return $"{SettingsUtil.LocalIl2CppDir}/build/deploy/il2cppcore/Unity.IL2CPP.dll";
#endif
}
private string GetUnityIl2CppDllModifiedPath(string curVersionStr)
{
#if UNITY_EDITOR_WIN
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Win.dll.bytes";
#else
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Mac.dll.bytes";
#endif
}
void CloneBranch(string workDir, string repoUrl, string branch, string repoDir)
{
BashUtil.RemoveDir(repoDir);
BashUtil.RunCommand(workDir, "git", new string[] {"clone", "-b", branch, "--depth", "1", repoUrl, repoDir});
}
private string PrepareLibil2cppWithHybridclrFromGitRepo()
{
string workDir = SettingsUtil.HybridCLRDataDir;
Directory.CreateDirectory(workDir);
//BashUtil.RecreateDir(workDir);
// clone hybridclr
string hybridclrRepoURL = HybridCLRSettings.Instance.hybridclrRepoURL;
string hybridclrRepoDir = $"{workDir}/{hybridclr_repo_path}";
CloneBranch(workDir, hybridclrRepoURL, _curDefaultVersion.hybridclr.branch, hybridclrRepoDir);
if (!Directory.Exists(hybridclrRepoDir))
{
throw new Exception($"clone hybridclr fail. url: {hybridclrRepoURL}");
}
// clone il2cpp_plus
string il2cppPlusRepoURL = HybridCLRSettings.Instance.il2cppPlusRepoURL;
string il2cppPlusRepoDir = $"{workDir}/{il2cpp_plus_repo_path}";
CloneBranch(workDir, il2cppPlusRepoURL, _curDefaultVersion.il2cpp_plus.branch, il2cppPlusRepoDir);
if (!Directory.Exists(il2cppPlusRepoDir))
{
throw new Exception($"clone il2cpp_plus fail. url: {il2cppPlusRepoDir}");
}
Directory.Move($"{hybridclrRepoDir}/hybridclr", $"{il2cppPlusRepoDir}/libil2cpp/hybridclr");
return $"{il2cppPlusRepoDir}/libil2cpp";
}
public void InstallFromLocal(string libil2cppWithHybridclrSourceDir)
{
RunInitLocalIl2CppData(ApplicationIl2cppPath, libil2cppWithHybridclrSourceDir, _curVersion);
}
private void RunInitLocalIl2CppData(string editorIl2cppPath, string libil2cppWithHybridclrSourceDir, UnityVersion version)
{
if (!IsComaptibleVersion())
{
Debug.LogError($"il2cpp 版本不兼容,最小版本为 {GetCurrentUnityVersionMinCompatibleVersionStr()}");
return;
}
string workDir = SettingsUtil.HybridCLRDataDir;
Directory.CreateDirectory(workDir);
//BashUtil.RecreateDir(workDir);
string buildiOSDir = $"{workDir}/iOSBuild";
BashUtil.RemoveDir(buildiOSDir);
BashUtil.CopyDir($"{SettingsUtil.HybridCLRDataPathInPackage}/iOSBuild", buildiOSDir, true);
// create LocalIl2Cpp
string localUnityDataDir = SettingsUtil.LocalUnityDataDir;
BashUtil.RecreateDir(localUnityDataDir);
// copy MonoBleedingEdge
BashUtil.CopyDir($"{Directory.GetParent(editorIl2cppPath)}/MonoBleedingEdge", $"{localUnityDataDir}/MonoBleedingEdge", true);
// copy il2cpp
BashUtil.CopyDir(editorIl2cppPath, SettingsUtil.LocalIl2CppDir, true);
// replace libil2cpp
string dstLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
BashUtil.CopyDir($"{libil2cppWithHybridclrSourceDir}", dstLibil2cppDir, true);
// clean Il2cppBuildCache
BashUtil.RemoveDir($"{SettingsUtil.ProjectDir}/Library/Il2cppBuildCache", true);
if (HasInstalledHybridCLR())
{
Debug.Log("安装成功");
}
else
{
Debug.LogError("安装失败");
}
}
}
}