InstallerController.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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. Debug.Log($"Write installed version:'{PackageVersion}' to {LocalVersionFile}");
  143. }
  144. public void InstallDefaultHybridCLR()
  145. {
  146. InstallFromLocal(PrepareLibil2cppWithHybridclrFromGitRepo());
  147. }
  148. public bool HasInstalledHybridCLR()
  149. {
  150. return Directory.Exists($"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr");
  151. }
  152. void CloneBranch(string workDir, string repoUrl, string branch, string repoDir)
  153. {
  154. BashUtil.RemoveDir(repoDir);
  155. BashUtil.RunCommand(workDir, "git", new string[] {"clone", "-b", branch, "--depth", "1", repoUrl, repoDir});
  156. }
  157. private string PrepareLibil2cppWithHybridclrFromGitRepo()
  158. {
  159. string workDir = SettingsUtil.HybridCLRDataDir;
  160. Directory.CreateDirectory(workDir);
  161. //BashUtil.RecreateDir(workDir);
  162. // clone hybridclr
  163. string hybridclrRepoURL = HybridCLRSettings.Instance.hybridclrRepoURL;
  164. string hybridclrRepoDir = $"{workDir}/{hybridclr_repo_path}";
  165. CloneBranch(workDir, hybridclrRepoURL, _curDefaultVersion.hybridclr.branch, hybridclrRepoDir);
  166. if (!Directory.Exists(hybridclrRepoDir))
  167. {
  168. throw new Exception($"clone hybridclr fail. url: {hybridclrRepoURL}");
  169. }
  170. // clone il2cpp_plus
  171. string il2cppPlusRepoURL = HybridCLRSettings.Instance.il2cppPlusRepoURL;
  172. string il2cppPlusRepoDir = $"{workDir}/{il2cpp_plus_repo_path}";
  173. CloneBranch(workDir, il2cppPlusRepoURL, _curDefaultVersion.il2cpp_plus.branch, il2cppPlusRepoDir);
  174. if (!Directory.Exists(il2cppPlusRepoDir))
  175. {
  176. throw new Exception($"clone il2cpp_plus fail. url: {il2cppPlusRepoDir}");
  177. }
  178. Directory.Move($"{hybridclrRepoDir}/hybridclr", $"{il2cppPlusRepoDir}/libil2cpp/hybridclr");
  179. return $"{il2cppPlusRepoDir}/libil2cpp";
  180. }
  181. public void InstallFromLocal(string libil2cppWithHybridclrSourceDir)
  182. {
  183. RunInitLocalIl2CppData(ApplicationIl2cppPath, libil2cppWithHybridclrSourceDir, _curVersion);
  184. }
  185. private void RunInitLocalIl2CppData(string editorIl2cppPath, string libil2cppWithHybridclrSourceDir, UnityVersion version)
  186. {
  187. if (GetCompatibleType() == CompatibleType.Incompatible)
  188. {
  189. Debug.LogError($"Incompatible with current version, minimum compatible version: {GetCurrentUnityVersionMinCompatibleVersionStr()}");
  190. return;
  191. }
  192. string workDir = SettingsUtil.HybridCLRDataDir;
  193. Directory.CreateDirectory(workDir);
  194. // create LocalIl2Cpp
  195. string localUnityDataDir = SettingsUtil.LocalUnityDataDir;
  196. BashUtil.RecreateDir(localUnityDataDir);
  197. // copy MonoBleedingEdge
  198. BashUtil.CopyDir($"{Directory.GetParent(editorIl2cppPath)}/MonoBleedingEdge", $"{localUnityDataDir}/MonoBleedingEdge", true);
  199. // copy il2cpp
  200. BashUtil.CopyDir(editorIl2cppPath, SettingsUtil.LocalIl2CppDir, true);
  201. // replace libil2cpp
  202. string dstLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
  203. BashUtil.CopyDir($"{libil2cppWithHybridclrSourceDir}", dstLibil2cppDir, true);
  204. // clean Il2cppBuildCache
  205. BashUtil.RemoveDir($"{SettingsUtil.ProjectDir}/Library/Il2cppBuildCache", true);
  206. if (HasInstalledHybridCLR())
  207. {
  208. WriteLocalVersion();
  209. Debug.Log("Install Sucessfully");
  210. }
  211. else
  212. {
  213. Debug.LogError("Installation failed!");
  214. }
  215. }
  216. }
  217. }