2022-09-22 08:56:07 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using UnityEditor;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
|
|
|
|
using Debug = UnityEngine.Debug;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
|
|
|
|
namespace HybridCLR.Editor.Installer
|
|
|
|
|
{
|
|
|
|
|
public enum InstallErrorCode
|
|
|
|
|
{
|
|
|
|
|
Ok,
|
2022-09-28 21:48:09 +08:00
|
|
|
|
InvalidUnityInstallPath,
|
2022-09-22 08:56:07 +08:00
|
|
|
|
Il2CppInstallPathNotMatchIl2CppBranch,
|
|
|
|
|
Il2CppInstallPathNotExists,
|
|
|
|
|
NotIl2CppPath,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public partial class InstallerController
|
|
|
|
|
{
|
2022-10-25 17:26:21 +08:00
|
|
|
|
private const string hybridclr_repo_path = "hybridclr_repo";
|
|
|
|
|
private const string hybridclr_url = "hybridclr";
|
|
|
|
|
private const string il2cpp_plus_repo_path = "il2cpp_plus_repo";
|
|
|
|
|
private const string il2cpp_plus_url = "il2cpp_plus";
|
|
|
|
|
|
2022-09-22 08:56:07 +08:00
|
|
|
|
private string m_Il2CppInstallDirectory;
|
|
|
|
|
|
|
|
|
|
public string Il2CppInstallDirectory
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return m_Il2CppInstallDirectory;
|
|
|
|
|
}
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
m_Il2CppInstallDirectory = value?.Replace('\\', '/');
|
|
|
|
|
if (!string.IsNullOrEmpty(m_Il2CppInstallDirectory))
|
|
|
|
|
{
|
|
|
|
|
EditorPrefs.SetString("UnityInstallDirectory", m_Il2CppInstallDirectory);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetIl2CppPlusBranchByUnityVersion(string unityVersion)
|
|
|
|
|
{
|
|
|
|
|
if (unityVersion.Contains("2019."))
|
|
|
|
|
{
|
|
|
|
|
return "2019.4.40";
|
|
|
|
|
}
|
|
|
|
|
if (unityVersion.Contains("2020."))
|
|
|
|
|
{
|
|
|
|
|
return "2020.3.33";
|
|
|
|
|
}
|
|
|
|
|
if (unityVersion.Contains("2021."))
|
|
|
|
|
{
|
|
|
|
|
return "2021.3.1";
|
|
|
|
|
}
|
|
|
|
|
return "not support";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string Il2CppBranch => GetIl2CppPlusBranchByUnityVersion(Application.unityVersion);
|
|
|
|
|
|
|
|
|
|
public InstallerController()
|
|
|
|
|
{
|
|
|
|
|
PrepareIl2CppInstallPath();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static readonly Regex s_unityVersionPat = new Regex(@"(\d+)\.(\d+)\.(\d+)");
|
|
|
|
|
|
|
|
|
|
public const int min2019_4_CompatibleMinorVersion = 40;
|
|
|
|
|
public const int min2020_3_CompatibleMinorVersion = 21;
|
|
|
|
|
public const int min2021_3_CompatibleMinorVersion = 0;
|
|
|
|
|
|
|
|
|
|
private bool TryParseMinorVersion(string installDir, out (int Major, int Minor1, int Minor2) unityVersion)
|
|
|
|
|
{
|
|
|
|
|
var matches = s_unityVersionPat.Matches(installDir);
|
|
|
|
|
if (matches.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
unityVersion = default;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 找最后一个匹配的,有的人居然会把Unity安装目录放到其他安装版本下。无语!
|
|
|
|
|
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);
|
|
|
|
|
unityVersion = (major, minor1, minor2);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetCurVersionStr(string installDir)
|
|
|
|
|
{
|
|
|
|
|
if (TryParseMinorVersion(installDir, out var version))
|
|
|
|
|
{
|
|
|
|
|
return $"{version.Major}.{version.Minor1}.{version.Minor2}";
|
|
|
|
|
}
|
|
|
|
|
throw new Exception($"not support version:{installDir}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetMinCompatibleVersion(string branch)
|
|
|
|
|
{
|
|
|
|
|
switch(branch)
|
|
|
|
|
{
|
|
|
|
|
case "2019.4.40": return $"2019.4.{min2019_4_CompatibleMinorVersion}";
|
|
|
|
|
case "2020.3.33": return $"2020.3.{min2020_3_CompatibleMinorVersion}";
|
|
|
|
|
case "2021.3.1": return $"2021.3.{min2021_3_CompatibleMinorVersion}";
|
|
|
|
|
default: throw new Exception($"not support version:{branch}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool IsComaptibleWithIl2CppPlusBranch(string branch, string installDir)
|
|
|
|
|
{
|
|
|
|
|
if (!TryParseMinorVersion(installDir, out var unityVersion))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
switch(branch)
|
|
|
|
|
{
|
|
|
|
|
case "2019.4.40":
|
|
|
|
|
{
|
|
|
|
|
if (unityVersion.Major != 2019 || unityVersion.Minor1 != 4)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return unityVersion.Minor2 >= min2019_4_CompatibleMinorVersion;
|
|
|
|
|
}
|
|
|
|
|
case "2020.3.33":
|
|
|
|
|
{
|
|
|
|
|
if (unityVersion.Major != 2020 || unityVersion.Minor1 != 3)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return unityVersion.Minor2 >= min2020_3_CompatibleMinorVersion;
|
|
|
|
|
}
|
|
|
|
|
case "2021.3.1":
|
|
|
|
|
{
|
|
|
|
|
if (unityVersion.Major != 2021 || unityVersion.Minor1 != 3)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return unityVersion.Minor2 >= min2021_3_CompatibleMinorVersion;
|
|
|
|
|
}
|
|
|
|
|
default: throw new Exception($"not support il2cpp_plus branch:{branch}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrepareIl2CppInstallPath()
|
|
|
|
|
{
|
|
|
|
|
#if UNITY_EDITOR_WIN
|
|
|
|
|
|
|
|
|
|
m_Il2CppInstallDirectory = EditorPrefs.GetString("Il2CppInstallDirectory");
|
|
|
|
|
if (CheckValidIl2CppInstallDirectory(Il2CppBranch, m_Il2CppInstallDirectory) == InstallErrorCode.Ok)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var il2cppBranch = Il2CppBranch;
|
|
|
|
|
var curAppInstallPath = EditorApplication.applicationPath;
|
|
|
|
|
if (IsComaptibleWithIl2CppPlusBranch(il2cppBranch, curAppInstallPath))
|
|
|
|
|
{
|
|
|
|
|
Il2CppInstallDirectory = $"{Directory.GetParent(curAppInstallPath)}/Data/il2cpp";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
string unityHubRootDir = Directory.GetParent(curAppInstallPath).Parent.Parent.ToString();
|
|
|
|
|
// Debug.Log("unity hub root dir:" + unityHubRootDir);
|
|
|
|
|
foreach (var unityInstallDir in Directory.GetDirectories(unityHubRootDir, "*", SearchOption.TopDirectoryOnly))
|
|
|
|
|
{
|
|
|
|
|
// Debug.Log("Unity install dir:" + unityInstallDir);
|
|
|
|
|
if (IsComaptibleWithIl2CppPlusBranch(il2cppBranch, unityInstallDir))
|
|
|
|
|
{
|
|
|
|
|
Il2CppInstallDirectory = $"{unityInstallDir}/Editor/Data/il2cpp";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Il2CppInstallDirectory = $"{Directory.GetParent(curAppInstallPath)}/Data/il2cpp";
|
|
|
|
|
#else
|
|
|
|
|
m_Il2CppInstallDirectory = EditorPrefs.GetString("Il2CppInstallDirectory");
|
|
|
|
|
if (CheckValidIl2CppInstallDirectory(Il2CppBranch, m_Il2CppInstallDirectory) == InstallErrorCode.Ok)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var il2cppBranch = Il2CppBranch;
|
|
|
|
|
var curAppInstallPath = EditorApplication.applicationPath;
|
|
|
|
|
if (IsComaptibleWithIl2CppPlusBranch(il2cppBranch, curAppInstallPath))
|
|
|
|
|
{
|
|
|
|
|
Il2CppInstallDirectory = $"{curAppInstallPath}/Contents/il2cpp";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
string unityHubRootDir = Directory.GetParent(curAppInstallPath).Parent.Parent.ToString();
|
|
|
|
|
foreach (var unityInstallDir in Directory.GetDirectories(unityHubRootDir, "*", SearchOption.TopDirectoryOnly))
|
|
|
|
|
{
|
|
|
|
|
Debug.Log("nity install dir:" + unityInstallDir);
|
|
|
|
|
if (IsComaptibleWithIl2CppPlusBranch(il2cppBranch, unityInstallDir))
|
|
|
|
|
{
|
|
|
|
|
Il2CppInstallDirectory = $"{unityInstallDir}/Unity.app/Contents/il2cpp";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Il2CppInstallDirectory = $"{curAppInstallPath}/Contents/il2cpp";
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void InitHybridCLR(string il2cppBranch, string il2cppInstallPath)
|
|
|
|
|
{
|
|
|
|
|
if (CheckValidIl2CppInstallDirectory(il2cppBranch, il2cppInstallPath) != InstallErrorCode.Ok)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"请正确设置 il2cpp 安装目录");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
RunInitLocalIl2CppData(il2cppBranch, il2cppInstallPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool HasInstalledHybridCLR()
|
|
|
|
|
{
|
|
|
|
|
return Directory.Exists($"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public InstallErrorCode CheckValidIl2CppInstallDirectory(string il2cppBranch, string installDir)
|
|
|
|
|
{
|
|
|
|
|
installDir = installDir.Replace('\\', '/');
|
|
|
|
|
if (!Directory.Exists(installDir))
|
|
|
|
|
{
|
|
|
|
|
return InstallErrorCode.Il2CppInstallPathNotExists;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!IsComaptibleWithIl2CppPlusBranch(il2cppBranch, installDir))
|
|
|
|
|
{
|
2022-09-28 21:48:09 +08:00
|
|
|
|
return TryParseMinorVersion(installDir, out _) ?
|
|
|
|
|
InstallErrorCode.Il2CppInstallPathNotMatchIl2CppBranch
|
|
|
|
|
: InstallErrorCode.InvalidUnityInstallPath;
|
2022-09-22 08:56:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!installDir.EndsWith("/il2cpp"))
|
|
|
|
|
{
|
|
|
|
|
return InstallErrorCode.NotIl2CppPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return InstallErrorCode.Ok;
|
|
|
|
|
}
|
2022-10-25 17:26:21 +08:00
|
|
|
|
|
2022-09-22 08:56:07 +08:00
|
|
|
|
public bool IsUnity2019(string branch)
|
|
|
|
|
{
|
|
|
|
|
return branch.Contains("2019.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string GetRepoUrl(string repoName)
|
|
|
|
|
{
|
2022-10-09 20:53:13 +08:00
|
|
|
|
string repoProvider = SettingsUtil.HybridCLRSettings.cloneFromGitee ? "gitee" : "github";
|
2022-09-22 08:56:07 +08:00
|
|
|
|
return $"https://{repoProvider}.com/focus-creative-games/{repoName}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RunInitLocalIl2CppData(string il2cppBranch, string il2cppInstallPath)
|
|
|
|
|
{
|
|
|
|
|
#if UNITY_EDITOR_WIN
|
|
|
|
|
if (!BashUtil.ExistProgram("git"))
|
|
|
|
|
{
|
|
|
|
|
throw new Exception($"安装本地il2cpp需要使用git从远程拉取仓库,请先安装git");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
string workDir = SettingsUtil.HybridCLRDataDir;
|
|
|
|
|
Directory.CreateDirectory(workDir);
|
|
|
|
|
//BashUtil.RecreateDir(workDir);
|
|
|
|
|
|
|
|
|
|
string buildiOSDir = $"{workDir}/iOSBuild";
|
|
|
|
|
BashUtil.RemoveDir(buildiOSDir);
|
|
|
|
|
BashUtil.CopyDir($"{SettingsUtil.HybridCLRDataPathInPackage}/iOSBuild", buildiOSDir, true);
|
|
|
|
|
|
|
|
|
|
// clone hybridclr
|
2022-10-25 17:26:21 +08:00
|
|
|
|
string hybridclrRepoDir = $"{workDir}/{hybridclr_repo_path}";
|
2022-09-22 08:56:07 +08:00
|
|
|
|
{
|
|
|
|
|
BashUtil.RemoveDir(hybridclrRepoDir);
|
|
|
|
|
var ret = BashUtil.RunCommand(workDir, "git", new string[]
|
|
|
|
|
{
|
|
|
|
|
"clone",
|
|
|
|
|
"--depth=1",
|
2022-10-25 17:26:21 +08:00
|
|
|
|
GetRepoUrl(hybridclr_url),
|
2022-09-22 08:56:07 +08:00
|
|
|
|
hybridclrRepoDir,
|
|
|
|
|
});
|
|
|
|
|
//if (ret != 0)
|
|
|
|
|
//{
|
|
|
|
|
// throw new Exception($"git clone 失败");
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clone il2cpp_plus
|
2022-10-25 17:26:21 +08:00
|
|
|
|
string il2cppPlusRepoDir = $"{workDir}/{il2cpp_plus_repo_path}";
|
2022-09-22 08:56:07 +08:00
|
|
|
|
{
|
|
|
|
|
BashUtil.RemoveDir(il2cppPlusRepoDir);
|
|
|
|
|
var ret = BashUtil.RunCommand(workDir, "git", new string[]
|
|
|
|
|
{
|
|
|
|
|
"clone",
|
|
|
|
|
"--depth=1",
|
|
|
|
|
"-b",
|
|
|
|
|
il2cppBranch,
|
2022-10-25 17:26:21 +08:00
|
|
|
|
GetRepoUrl(il2cpp_plus_url),
|
2022-09-22 08:56:07 +08:00
|
|
|
|
il2cppPlusRepoDir,
|
|
|
|
|
});
|
|
|
|
|
//if (ret != 0)
|
|
|
|
|
//{
|
|
|
|
|
// throw new Exception($"git clone 失败");
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// create LocalIl2Cpp
|
|
|
|
|
string localUnityDataDir = SettingsUtil.LocalUnityDataDir;
|
|
|
|
|
BashUtil.RecreateDir(localUnityDataDir);
|
|
|
|
|
|
|
|
|
|
// copy MonoBleedingEdge
|
|
|
|
|
BashUtil.CopyDir($"{Directory.GetParent(il2cppInstallPath)}/MonoBleedingEdge", $"{localUnityDataDir}/MonoBleedingEdge", true);
|
|
|
|
|
|
|
|
|
|
// copy il2cpp
|
|
|
|
|
BashUtil.CopyDir(Il2CppInstallDirectory, SettingsUtil.LocalIl2CppDir, true);
|
|
|
|
|
|
|
|
|
|
// replace libil2cpp
|
|
|
|
|
string dstLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
|
|
|
|
|
BashUtil.CopyDir($"{il2cppPlusRepoDir}/libil2cpp", dstLibil2cppDir, true);
|
|
|
|
|
BashUtil.CopyDir($"{hybridclrRepoDir}/hybridclr", $"{dstLibil2cppDir}/hybridclr", true);
|
|
|
|
|
|
|
|
|
|
// clean Il2cppBuildCache
|
|
|
|
|
BashUtil.RemoveDir($"{SettingsUtil.ProjectDir}/Library/Il2cppBuildCache", true);
|
|
|
|
|
|
|
|
|
|
if (IsUnity2019(il2cppBranch))
|
|
|
|
|
{
|
|
|
|
|
string curVersionStr = GetCurVersionStr(il2cppInstallPath);
|
|
|
|
|
string srcIl2CppDll = GetUnityIl2CppDllModifiedPath(curVersionStr);
|
|
|
|
|
if (File.Exists(srcIl2CppDll))
|
|
|
|
|
{
|
|
|
|
|
string dstIl2CppDll = GetUnityIl2CppDllInstallLocation();
|
|
|
|
|
File.Copy(srcIl2CppDll, dstIl2CppDll, true);
|
|
|
|
|
Debug.Log($"copy {srcIl2CppDll} => {dstIl2CppDll}");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"未找到当前版本:{curVersionStr} 对应的改造过的 Unity.IL2CPP.dll,打包出的程序将会崩溃");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (HasInstalledHybridCLR())
|
|
|
|
|
{
|
|
|
|
|
Debug.Log("安装成功!");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError("安装失败!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|