2022-09-22 08:56:07 +08:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Text ;
using UnityEditor ;
using UnityEngine ;
using Debug = UnityEngine . Debug ;
using System.Text.RegularExpressions ;
2023-06-12 13:30:32 +08:00
using System.Linq ;
2023-10-09 15:39:32 +08:00
using HybridCLR.Editor.Settings ;
2022-09-22 08:56:07 +08:00
namespace HybridCLR.Editor.Installer
{
2023-01-26 13:11:38 +08:00
public class InstallerController
2022-09-22 08:56:07 +08:00
{
2022-10-25 17:26:21 +08:00
private const string hybridclr_repo_path = "hybridclr_repo" ;
2022-12-06 11:52:47 +08:00
2022-10-25 17:26:21 +08:00
private const string il2cpp_plus_repo_path = "il2cpp_plus_repo" ;
2022-09-22 08:56:07 +08:00
2022-12-06 11:52:47 +08:00
public int MajorVersion = > _curVersion . major ;
2022-09-22 08:56:07 +08:00
2023-01-26 13:11:38 +08:00
private readonly UnityVersion _curVersion ;
private readonly HybridclrVersionManifest _versionManifest ;
private readonly HybridclrVersionInfo _curDefaultVersion ;
2022-09-22 08:56:07 +08:00
2023-06-16 18:18:41 +08:00
public string PackageVersion { get ; private set ; }
2023-10-15 12:44:22 +08:00
public string InstalledLibil2cppVersion { get ; private set ; }
2022-09-22 08:56:07 +08:00
public InstallerController ( )
{
2022-12-06 11:52:47 +08:00
_curVersion = ParseUnityVersion ( Application . unityVersion ) ;
2023-01-26 13:11:38 +08:00
_versionManifest = GetHybridCLRVersionManifest ( ) ;
2024-02-28 14:20:39 +08:00
_curDefaultVersion = _versionManifest . versions . FirstOrDefault ( v = > _curVersion . isTuanjieEngine ? v . unity_version = = $"{_curVersion.major}-tuanjie" : v . unity_version = = _curVersion . major . ToString ( ) ) ;
2023-06-16 18:18:41 +08:00
PackageVersion = LoadPackageInfo ( ) . version ;
2023-10-15 12:44:22 +08:00
InstalledLibil2cppVersion = ReadLocalVersion ( ) ;
2023-01-26 13:11:38 +08:00
}
private HybridclrVersionManifest GetHybridCLRVersionManifest ( )
{
string versionFile = $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/hybridclr_version.json" ;
return JsonUtility . FromJson < HybridclrVersionManifest > ( File . ReadAllText ( versionFile , Encoding . UTF8 ) ) ;
}
2023-06-16 18:18:41 +08:00
private PackageInfo LoadPackageInfo ( )
{
string packageJson = $"{SettingsUtil.ProjectDir}/Packages/{SettingsUtil.PackageName}/package.json" ;
return JsonUtility . FromJson < PackageInfo > ( File . ReadAllText ( packageJson , Encoding . UTF8 ) ) ;
}
[Serializable]
class PackageInfo
{
public string name ;
public string version ;
}
2023-01-26 13:11:38 +08:00
[Serializable]
class VersionDesc
{
public string branch ;
2023-02-22 10:43:30 +08:00
//public string hash;
2023-01-26 13:11:38 +08:00
}
[Serializable]
class HybridclrVersionInfo
{
public string unity_version ;
public VersionDesc hybridclr ;
public VersionDesc il2cpp_plus ;
2022-12-06 11:52:47 +08:00
}
2023-01-26 13:11:38 +08:00
[Serializable]
class HybridclrVersionManifest
{
public List < HybridclrVersionInfo > versions ;
}
private class UnityVersion
2022-12-06 11:52:47 +08:00
{
public int major ;
public int minor1 ;
public int minor2 ;
2024-02-28 14:20:39 +08:00
public bool isTuanjieEngine ;
2022-12-06 11:52:47 +08:00
public override string ToString ( )
{
return $"{major}.{minor1}.{minor2}" ;
}
2022-09-22 08:56:07 +08:00
}
private static readonly Regex s_unityVersionPat = new Regex ( @"(\d+)\.(\d+)\.(\d+)" ) ;
2022-12-06 11:52:47 +08:00
private UnityVersion ParseUnityVersion ( string versionStr )
2022-09-22 08:56:07 +08:00
{
2022-12-06 11:52:47 +08:00
var matches = s_unityVersionPat . Matches ( versionStr ) ;
2022-09-22 08:56:07 +08:00
if ( matches . Count = = 0 )
{
2022-12-06 11:52:47 +08:00
return null ;
2022-09-22 08:56:07 +08:00
}
Match match = matches [ matches . Count - 1 ] ;
int major = int . Parse ( match . Groups [ 1 ] . Value ) ;
int minor1 = int . Parse ( match . Groups [ 2 ] . Value ) ;
int minor2 = int . Parse ( match . Groups [ 3 ] . Value ) ;
2024-02-28 14:20:39 +08:00
bool isTuanjieEngine = versionStr . Contains ( "t" ) ;
return new UnityVersion { major = major , minor1 = minor1 , minor2 = minor2 , isTuanjieEngine = isTuanjieEngine } ;
2022-09-22 08:56:07 +08:00
}
2022-12-06 11:52:47 +08:00
public string GetCurrentUnityVersionMinCompatibleVersionStr ( )
2022-09-22 08:56:07 +08:00
{
2022-12-06 11:52:47 +08:00
return GetMinCompatibleVersion ( MajorVersion ) ;
2022-09-22 08:56:07 +08:00
}
2022-12-06 11:52:47 +08:00
public string GetMinCompatibleVersion ( int majorVersion )
2022-09-22 08:56:07 +08:00
{
2022-12-06 11:52:47 +08:00
switch ( majorVersion )
2022-09-22 08:56:07 +08:00
{
2023-11-28 11:27:58 +08:00
case 2019 : return $"2019.4.0" ;
2023-07-11 12:27:11 +08:00
case 2020 : return $"2020.3.0" ;
case 2021 : return $"2021.3.0" ;
case 2022 : return $"2022.3.0" ;
default : return $"2020.3.0" ;
2022-09-22 08:56:07 +08:00
}
}
2023-09-17 23:30:09 +08:00
public enum CompatibleType
{
Compatible ,
MaybeIncompatible ,
Incompatible ,
}
public CompatibleType GetCompatibleType ( )
2022-09-22 08:56:07 +08:00
{
2022-12-06 11:52:47 +08:00
UnityVersion version = _curVersion ;
2023-06-12 13:30:32 +08:00
if ( version = = null )
{
2023-09-17 23:30:09 +08:00
return CompatibleType . Incompatible ;
2023-06-12 13:30:32 +08:00
}
2023-11-28 11:27:58 +08:00
if ( ( version . major = = 2019 & & version . minor1 < 4 ) | | ( version . major > = 2020 & & version . minor1 < 3 ) )
2023-06-03 19:42:56 +08:00
{
2023-09-17 23:30:09 +08:00
return CompatibleType . MaybeIncompatible ;
2023-06-03 19:42:56 +08:00
}
2023-09-17 23:30:09 +08:00
return CompatibleType . Compatible ;
2022-09-22 08:56:07 +08:00
}
2023-06-30 12:20:56 +08:00
public string HybridclrLocalVersion = > _curDefaultVersion ? . hybridclr ? . branch ;
2022-12-06 18:57:48 +08:00
2023-06-30 12:20:56 +08:00
public string Il2cppPlusLocalVersion = > _curDefaultVersion ? . il2cpp_plus ? . branch ;
2022-12-06 18:57:48 +08:00
2023-01-26 13:11:38 +08:00
private string GetIl2CppPathByContentPath ( string contentPath )
2022-12-06 11:52:47 +08:00
{
2023-01-26 13:11:38 +08:00
return $"{contentPath}/il2cpp" ;
2022-09-22 08:56:07 +08:00
}
2023-04-29 12:41:47 +08:00
public string ApplicationIl2cppPath = > GetIl2CppPathByContentPath ( EditorApplication . applicationContentsPath ) ;
2022-12-06 11:52:47 +08:00
2023-10-15 12:44:22 +08:00
public string LocalVersionFile = > $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/libil2cpp-version.txt" ;
private string ReadLocalVersion ( )
{
if ( ! File . Exists ( LocalVersionFile ) )
{
return null ;
}
return File . ReadAllText ( LocalVersionFile , Encoding . UTF8 ) ;
}
public void WriteLocalVersion ( )
{
InstalledLibil2cppVersion = PackageVersion ;
File . WriteAllText ( LocalVersionFile , PackageVersion , Encoding . UTF8 ) ;
2023-11-28 21:01:33 +08:00
Debug . Log ( $"Write installed version:'{PackageVersion}' to {LocalVersionFile}" ) ;
2023-10-15 12:44:22 +08:00
}
2023-01-26 13:11:38 +08:00
public void InstallDefaultHybridCLR ( )
2022-09-22 08:56:07 +08:00
{
2023-04-29 12:41:47 +08:00
InstallFromLocal ( PrepareLibil2cppWithHybridclrFromGitRepo ( ) ) ;
2022-09-22 08:56:07 +08:00
}
2022-12-06 11:52:47 +08:00
public bool HasInstalledHybridCLR ( )
2022-09-22 08:56:07 +08:00
{
2022-12-06 11:52:47 +08:00
return Directory . Exists ( $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr" ) ;
2022-09-22 08:56:07 +08:00
}
2023-11-28 11:27:58 +08:00
private string GetUnityIl2CppDllInstallLocation ( )
{
2023-11-29 16:08:22 +08:00
#if UNITY_EDITOR_WIN
return $"{SettingsUtil.LocalIl2CppDir}/build/deploy/net471/Unity.IL2CPP.dll" ;
# else
return $"{SettingsUtil.LocalIl2CppDir}/build/deploy/il2cppcore/Unity.IL2CPP.dll" ;
# endif
2023-11-28 11:27:58 +08:00
}
private string GetUnityIl2CppDllModifiedPath ( string curVersionStr )
{
#if UNITY_EDITOR_WIN
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Win.dll" ;
# else
return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Mac.dll" ;
# endif
}
2023-02-22 10:43:30 +08:00
void CloneBranch ( string workDir , string repoUrl , string branch , string repoDir )
2023-01-26 13:11:38 +08:00
{
BashUtil . RemoveDir ( repoDir ) ;
2023-02-22 10:43:30 +08:00
BashUtil . RunCommand ( workDir , "git" , new string [ ] { "clone" , "-b" , branch , "--depth" , "1" , repoUrl , repoDir } ) ;
2023-01-26 13:11:38 +08:00
}
2023-04-29 12:11:16 +08:00
private string PrepareLibil2cppWithHybridclrFromGitRepo ( )
2022-09-22 08:56:07 +08:00
{
string workDir = SettingsUtil . HybridCLRDataDir ;
Directory . CreateDirectory ( workDir ) ;
//BashUtil.RecreateDir(workDir);
// clone hybridclr
2022-11-28 12:20:52 +08:00
string hybridclrRepoURL = HybridCLRSettings . Instance . hybridclrRepoURL ;
2022-10-25 17:26:21 +08:00
string hybridclrRepoDir = $"{workDir}/{hybridclr_repo_path}" ;
2023-02-22 10:43:30 +08:00
CloneBranch ( workDir , hybridclrRepoURL , _curDefaultVersion . hybridclr . branch , hybridclrRepoDir ) ;
2022-09-22 08:56:07 +08:00
2023-04-29 12:11:16 +08:00
if ( ! Directory . Exists ( hybridclrRepoDir ) )
{
throw new Exception ( $"clone hybridclr fail. url: {hybridclrRepoURL}" ) ;
}
2022-09-22 08:56:07 +08:00
// clone il2cpp_plus
2022-11-28 12:20:52 +08:00
string il2cppPlusRepoURL = HybridCLRSettings . Instance . il2cppPlusRepoURL ;
2022-10-25 17:26:21 +08:00
string il2cppPlusRepoDir = $"{workDir}/{il2cpp_plus_repo_path}" ;
2023-02-22 10:43:30 +08:00
CloneBranch ( workDir , il2cppPlusRepoURL , _curDefaultVersion . il2cpp_plus . branch , il2cppPlusRepoDir ) ;
2022-09-22 08:56:07 +08:00
2023-04-29 12:11:16 +08:00
if ( ! Directory . Exists ( il2cppPlusRepoDir ) )
{
throw new Exception ( $"clone il2cpp_plus fail. url: {il2cppPlusRepoDir}" ) ;
}
Directory . Move ( $"{hybridclrRepoDir}/hybridclr" , $"{il2cppPlusRepoDir}/libil2cpp/hybridclr" ) ;
return $"{il2cppPlusRepoDir}/libil2cpp" ;
}
2023-04-29 12:41:47 +08:00
public void InstallFromLocal ( string libil2cppWithHybridclrSourceDir )
{
RunInitLocalIl2CppData ( ApplicationIl2cppPath , libil2cppWithHybridclrSourceDir , _curVersion ) ;
}
2023-04-29 12:11:16 +08:00
private void RunInitLocalIl2CppData ( string editorIl2cppPath , string libil2cppWithHybridclrSourceDir , UnityVersion version )
{
2023-09-17 23:30:09 +08:00
if ( GetCompatibleType ( ) = = CompatibleType . Incompatible )
2023-04-29 12:11:16 +08:00
{
2023-07-11 12:27:11 +08:00
Debug . LogError ( $"Incompatible with current version, minimum compatible version: {GetCurrentUnityVersionMinCompatibleVersionStr()}" ) ;
2023-04-29 12:11:16 +08:00
return ;
}
string workDir = SettingsUtil . HybridCLRDataDir ;
Directory . CreateDirectory ( workDir ) ;
2022-09-22 08:56:07 +08:00
// create LocalIl2Cpp
string localUnityDataDir = SettingsUtil . LocalUnityDataDir ;
BashUtil . RecreateDir ( localUnityDataDir ) ;
// copy MonoBleedingEdge
2022-12-06 11:52:47 +08:00
BashUtil . CopyDir ( $"{Directory.GetParent(editorIl2cppPath)}/MonoBleedingEdge" , $"{localUnityDataDir}/MonoBleedingEdge" , true ) ;
2022-09-22 08:56:07 +08:00
// copy il2cpp
2022-12-06 11:52:47 +08:00
BashUtil . CopyDir ( editorIl2cppPath , SettingsUtil . LocalIl2CppDir , true ) ;
2022-09-22 08:56:07 +08:00
// replace libil2cpp
string dstLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp" ;
2023-04-29 12:11:16 +08:00
BashUtil . CopyDir ( $"{libil2cppWithHybridclrSourceDir}" , dstLibil2cppDir , true ) ;
2022-09-22 08:56:07 +08:00
// clean Il2cppBuildCache
BashUtil . RemoveDir ( $"{SettingsUtil.ProjectDir}/Library/Il2cppBuildCache" , true ) ;
2023-11-28 11:27:58 +08:00
if ( version . major = = 2019 )
{
string curVersionStr = version . ToString ( ) ;
string srcIl2CppDll = GetUnityIl2CppDllModifiedPath ( curVersionStr ) ;
if ( File . Exists ( srcIl2CppDll ) )
{
string dstIl2CppDll = GetUnityIl2CppDllInstallLocation ( ) ;
File . Copy ( srcIl2CppDll , dstIl2CppDll , true ) ;
Debug . Log ( $"copy {srcIl2CppDll} => {dstIl2CppDll}" ) ;
}
else
{
throw new Exception ( $"the modified Unity.IL2CPP.dll of {curVersionStr} isn't found. please install hybridclr in 2019.4.40 first, then switch to your unity version" ) ;
}
}
2022-09-22 08:56:07 +08:00
if ( HasInstalledHybridCLR ( ) )
{
2023-10-15 12:44:22 +08:00
WriteLocalVersion ( ) ;
2023-07-11 12:27:11 +08:00
Debug . Log ( "Install Sucessfully" ) ;
2022-09-22 08:56:07 +08:00
}
else
{
2023-07-11 12:27:11 +08:00
Debug . LogError ( "Installation failed!" ) ;
2022-09-22 08:56:07 +08:00
}
}
}
}