InstallerController.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Text;
  5. using UnityEditor;
  6. using UnityEngine;
  7. using Debug = UnityEngine.Debug;
  8. using System.Text.RegularExpressions;
  9. using System.Linq;
  10. using HybridCLR.Editor.Settings;
  11. namespace HybridCLR.Editor.Installer
  12. {
  13. public class InstallerController
  14. {
  15. private const string hybridclr_repo_path = "hybridclr_repo";
  16. private const string il2cpp_plus_repo_path = "il2cpp_plus_repo";
  17. public int MajorVersion => _curVersion.major;
  18. private readonly UnityVersion _curVersion;
  19. private readonly HybridclrVersionManifest _versionManifest;
  20. private readonly HybridclrVersionInfo _curDefaultVersion;
  21. public string PackageVersion { get; private set; }
  22. public string InstalledLibil2cppVersion { get; private set; }
  23. public InstallerController()
  24. {
  25. _curVersion = ParseUnityVersion(Application.unityVersion);
  26. _versionManifest = GetHybridCLRVersionManifest();
  27. _curDefaultVersion = _versionManifest.versions.FirstOrDefault(v => v.unity_version == _curVersion.major.ToString());
  28. PackageVersion = LoadPackageInfo().version;
  29. InstalledLibil2cppVersion = ReadLocalVersion();
  30. }
  31. private HybridclrVersionManifest GetHybridCLRVersionManifest()
  32. {
  33. string versionFile = $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/hybridclr_version.json";
  34. return JsonUtility.FromJson<HybridclrVersionManifest>(File.ReadAllText(versionFile, Encoding.UTF8));
  35. }
  36. private PackageInfo LoadPackageInfo()
  37. {
  38. string packageJson = $"{SettingsUtil.ProjectDir}/Packages/{SettingsUtil.PackageName}/package.json";
  39. return JsonUtility.FromJson<PackageInfo>(File.ReadAllText(packageJson, Encoding.UTF8));
  40. }
  41. [Serializable]
  42. class PackageInfo
  43. {
  44. public string name;
  45. public string version;
  46. }
  47. [Serializable]
  48. class VersionDesc
  49. {
  50. public string branch;
  51. //public string hash;
  52. }
  53. [Serializable]
  54. class HybridclrVersionInfo
  55. {
  56. public string unity_version;
  57. public VersionDesc hybridclr;
  58. public VersionDesc il2cpp_plus;
  59. }
  60. [Serializable]
  61. class HybridclrVersionManifest
  62. {
  63. public List<HybridclrVersionInfo> versions;
  64. }
  65. private class UnityVersion
  66. {
  67. public int major;
  68. public int minor1;
  69. public int minor2;
  70. public override string ToString()
  71. {
  72. return $"{major}.{minor1}.{minor2}";
  73. }
  74. }
  75. private static readonly Regex s_unityVersionPat = new Regex(@"(\d+)\.(\d+)\.(\d+)");
  76. private UnityVersion ParseUnityVersion(string versionStr)
  77. {
  78. var matches = s_unityVersionPat.Matches(versionStr);
  79. if (matches.Count == 0)
  80. {
  81. return null;
  82. }
  83. Match match = matches[matches.Count - 1];
  84. int major = int.Parse(match.Groups[1].Value);
  85. int minor1 = int.Parse(match.Groups[2].Value);
  86. int minor2 = int.Parse(match.Groups[3].Value);
  87. return new UnityVersion { major = major, minor1 = minor1, minor2 = minor2 };
  88. }
  89. public string GetCurrentUnityVersionMinCompatibleVersionStr()
  90. {
  91. return GetMinCompatibleVersion(MajorVersion);
  92. }
  93. public string GetMinCompatibleVersion(int majorVersion)
  94. {
  95. switch(majorVersion)
  96. {
  97. case 2020: return $"2020.3.0";
  98. case 2021: return $"2021.3.0";
  99. case 2022: return $"2022.3.0";
  100. default: return $"2020.3.0";
  101. }
  102. }
  103. public enum CompatibleType
  104. {
  105. Compatible,
  106. MaybeIncompatible,
  107. Incompatible,
  108. }
  109. public CompatibleType GetCompatibleType()
  110. {
  111. UnityVersion version = _curVersion;
  112. if (version == null)
  113. {
  114. return CompatibleType.Incompatible;
  115. }
  116. if (version.minor1 != 3)
  117. {
  118. return CompatibleType.MaybeIncompatible;
  119. }
  120. return CompatibleType.Compatible;
  121. }
  122. public string HybridclrLocalVersion => _curDefaultVersion?.hybridclr?.branch;
  123. public string Il2cppPlusLocalVersion => _curDefaultVersion?.il2cpp_plus?.branch;
  124. private string GetIl2CppPathByContentPath(string contentPath)
  125. {
  126. return $"{contentPath}/il2cpp";
  127. }
  128. public string ApplicationIl2cppPath => GetIl2CppPathByContentPath(EditorApplication.applicationContentsPath);
  129. public string LocalVersionFile => $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/libil2cpp-version.txt";
  130. private string ReadLocalVersion()
  131. {
  132. if (!File.Exists(LocalVersionFile))
  133. {
  134. return null;
  135. }
  136. return File.ReadAllText(LocalVersionFile, Encoding.UTF8);
  137. }
  138. public void WriteLocalVersion()
  139. {
  140. InstalledLibil2cppVersion = PackageVersion;
  141. File.WriteAllText(LocalVersionFile, PackageVersion, Encoding.UTF8);
  142. }
  143. public void InstallDefaultHybridCLR()
  144. {
  145. InstallFromLocal(PrepareLibil2cppWithHybridclrFromGitRepo());
  146. }
  147. public bool HasInstalledHybridCLR()
  148. {
  149. return Directory.Exists($"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr");
  150. }
  151. void CloneBranch(string workDir, string repoUrl, string branch, string repoDir)
  152. {
  153. BashUtil.RemoveDir(repoDir);
  154. BashUtil.RunCommand(workDir, "git", new string[] {"clone", "-b", branch, "--depth", "1", repoUrl, repoDir});
  155. }
  156. private string PrepareLibil2cppWithHybridclrFromGitRepo()
  157. {
  158. string workDir = SettingsUtil.HybridCLRDataDir;
  159. Directory.CreateDirectory(workDir);
  160. //BashUtil.RecreateDir(workDir);
  161. // clone hybridclr
  162. string hybridclrRepoURL = HybridCLRSettings.Instance.hybridclrRepoURL;
  163. string hybridclrRepoDir = $"{workDir}/{hybridclr_repo_path}";
  164. CloneBranch(workDir, hybridclrRepoURL, _curDefaultVersion.hybridclr.branch, hybridclrRepoDir);
  165. if (!Directory.Exists(hybridclrRepoDir))
  166. {
  167. throw new Exception($"clone hybridclr fail. url: {hybridclrRepoURL}");
  168. }
  169. // clone il2cpp_plus
  170. string il2cppPlusRepoURL = HybridCLRSettings.Instance.il2cppPlusRepoURL;
  171. string il2cppPlusRepoDir = $"{workDir}/{il2cpp_plus_repo_path}";
  172. CloneBranch(workDir, il2cppPlusRepoURL, _curDefaultVersion.il2cpp_plus.branch, il2cppPlusRepoDir);
  173. if (!Directory.Exists(il2cppPlusRepoDir))
  174. {
  175. throw new Exception($"clone il2cpp_plus fail. url: {il2cppPlusRepoDir}");
  176. }
  177. Directory.Move($"{hybridclrRepoDir}/hybridclr", $"{il2cppPlusRepoDir}/libil2cpp/hybridclr");
  178. return $"{il2cppPlusRepoDir}/libil2cpp";
  179. }
  180. public void InstallFromLocal(string libil2cppWithHybridclrSourceDir)
  181. {
  182. RunInitLocalIl2CppData(ApplicationIl2cppPath, libil2cppWithHybridclrSourceDir, _curVersion);
  183. }
  184. private void RunInitLocalIl2CppData(string editorIl2cppPath, string libil2cppWithHybridclrSourceDir, UnityVersion version)
  185. {
  186. if (GetCompatibleType() == CompatibleType.Incompatible)
  187. {
  188. Debug.LogError($"Incompatible with current version, minimum compatible version: {GetCurrentUnityVersionMinCompatibleVersionStr()}");
  189. return;
  190. }
  191. string workDir = SettingsUtil.HybridCLRDataDir;
  192. Directory.CreateDirectory(workDir);
  193. // create LocalIl2Cpp
  194. string localUnityDataDir = SettingsUtil.LocalUnityDataDir;
  195. BashUtil.RecreateDir(localUnityDataDir);
  196. // copy MonoBleedingEdge
  197. BashUtil.CopyDir($"{Directory.GetParent(editorIl2cppPath)}/MonoBleedingEdge", $"{localUnityDataDir}/MonoBleedingEdge", true);
  198. // copy il2cpp
  199. BashUtil.CopyDir(editorIl2cppPath, SettingsUtil.LocalIl2CppDir, true);
  200. // replace libil2cpp
  201. string dstLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
  202. BashUtil.CopyDir($"{libil2cppWithHybridclrSourceDir}", dstLibil2cppDir, true);
  203. // clean Il2cppBuildCache
  204. BashUtil.RemoveDir($"{SettingsUtil.ProjectDir}/Library/Il2cppBuildCache", true);
  205. if (HasInstalledHybridCLR())
  206. {
  207. WriteLocalVersion();
  208. Debug.Log("Install Sucessfully");
  209. }
  210. else
  211. {
  212. Debug.LogError("Installation failed!");
  213. }
  214. }
  215. }
  216. }