AddLil2cppSourceCodeToXcodeproj2019.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. using System;
  2. using HybridCLR.Editor.Installer;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using UnityEditor;
  8. using System.Reflection;
  9. using HybridCLR.Editor.Settings;
  10. #if UNITY_2019 && (UNITY_IOS || UNITY_TVOS)
  11. using UnityEditor.Build;
  12. using UnityEditor.Callbacks;
  13. using UnityEditor.iOS.Xcode;
  14. using UnityEngine;
  15. namespace HybridCLR.Editor.BuildProcessors
  16. {
  17. public static class AddLil2cppSourceCodeToXcodeproj2019
  18. {
  19. [PostProcessBuild]
  20. public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject)
  21. {
  22. if (!HybridCLRSettings.Instance.enable)
  23. return;
  24. /*
  25. * 1. 生成lump,并且添加到工程
  26. 3. 将libil2cpp目录复制到 Library/. 删除旧的. search paths里修改 libil2cpp/include为libil2cpp
  27. 3. Libraries/bdwgc/include -> Libraries/external/bdwgc/include
  28. 4. 将external目录复制到 Library/external。删除旧目录
  29. 5. 将Library/external/baselib/Platforms/OSX改名为 IOS 全大写
  30. 6. 将 external/zlib下c 文件添加到工程
  31. 7. 移除libil2cpp.a
  32. 8. Include path add libil2cpp/os/ClassLibraryPAL/brotli/include
  33. 9. add external/xxHash
  34. 10. add "#include <stdio.h>" to Classes/Prefix.pch
  35. */
  36. string pbxprojFile = BuildProcessorUtil.GetXcodeProjectFile(pathToBuiltProject);
  37. string srcLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp";
  38. string dstLibil2cppDir = $"{pathToBuiltProject}/Libraries/libil2cpp";
  39. string lumpDir = $"{pathToBuiltProject}/Libraries/lumps";
  40. string srcExternalDir = $"{SettingsUtil.LocalIl2CppDir}/external";
  41. string dstExternalDir = $"{pathToBuiltProject}/Libraries/external";
  42. //RemoveExternalLibil2cppOption(srcExternalDir, dstExternalDir);
  43. CopyLibil2cppToXcodeProj(srcLibil2cppDir, dstLibil2cppDir);
  44. CopyExternalToXcodeProj(srcExternalDir, dstExternalDir);
  45. var lumpFiles = CreateLumps(dstLibil2cppDir, lumpDir);
  46. var extraSources = GetExtraSourceFiles(dstExternalDir, dstLibil2cppDir);
  47. var cflags = new List<string>()
  48. {
  49. "-DIL2CPP_MONO_DEBUGGER_DISABLED",
  50. };
  51. ModifyPBXProject(pathToBuiltProject, pbxprojFile, lumpFiles, extraSources, cflags);
  52. AddSystemHeaderToPrefixPch(pathToBuiltProject);
  53. }
  54. private static void AddSystemHeaderToPrefixPch(string pathToBuiltProject)
  55. {
  56. // 如果不将 stdio.h 添加到 Prefix.pch, zutil.c会有编译错误
  57. string prefixPchFile = $"{pathToBuiltProject}/Classes/Prefix.pch";
  58. string fileContent = File.ReadAllText(prefixPchFile, Encoding.UTF8);
  59. if (!fileContent.Contains("stdio.h"))
  60. {
  61. string newFileContent = fileContent + "\n#include <stdio.h>\n";
  62. File.WriteAllText(prefixPchFile, newFileContent, Encoding.UTF8);
  63. UnityEngine.Debug.Log($"append header to {prefixPchFile}");
  64. }
  65. }
  66. private static string GetRelativePathFromProj(string path)
  67. {
  68. return path.Substring(path.IndexOf("Libraries", StringComparison.Ordinal)).Replace('\\', '/');
  69. }
  70. private static void ModifyPBXProject(string pathToBuiltProject, string pbxprojFile, List<LumpFile> lumpFiles, List<string> extraFiles, List<string> cflags)
  71. {
  72. var proj = new PBXProject();
  73. proj.ReadFromFile(pbxprojFile);
  74. string targetGUID = proj.GetUnityFrameworkTargetGuid();
  75. // 移除旧的libil2cpp.a
  76. var libil2cppGUID = proj.FindFileGuidByProjectPath("Libraries/libil2cpp.a");
  77. if (!string.IsNullOrEmpty(libil2cppGUID))
  78. {
  79. proj.RemoveFileFromBuild(targetGUID, libil2cppGUID);
  80. proj.RemoveFile(libil2cppGUID);
  81. File.Delete(Path.Combine(pathToBuiltProject, "Libraries", "libil2cpp.a"));
  82. }
  83. //var lumpGroupGuid = proj.AddFile("Lumps", $"Classes/Lumps", PBXSourceTree.Group);
  84. foreach (var lumpFile in lumpFiles)
  85. {
  86. string lumpFileName = Path.GetFileName(lumpFile.lumpFile);
  87. string projPathOfFile = $"Classes/Lumps/{lumpFileName}";
  88. string relativePathOfFile = GetRelativePathFromProj(lumpFile.lumpFile);
  89. string lumpGuid = proj.FindFileGuidByProjectPath(projPathOfFile);
  90. if (!string.IsNullOrEmpty(lumpGuid))
  91. {
  92. proj.RemoveFileFromBuild(targetGUID, lumpGuid);
  93. proj.RemoveFile(lumpGuid);
  94. }
  95. lumpGuid = proj.AddFile(relativePathOfFile, projPathOfFile, PBXSourceTree.Source);
  96. proj.AddFileToBuild(targetGUID, lumpGuid);
  97. }
  98. foreach (var extraFile in extraFiles)
  99. {
  100. string projPathOfFile = $"Classes/Extrals/{Path.GetFileName(extraFile)}";
  101. string extraFileGuid = proj.FindFileGuidByProjectPath(projPathOfFile);
  102. if (!string.IsNullOrEmpty(extraFileGuid))
  103. {
  104. proj.RemoveFileFromBuild(targetGUID, extraFileGuid);
  105. proj.RemoveFile(extraFileGuid);
  106. //Debug.LogWarning($"remove exist extra file:{projPathOfFile} guid:{extraFileGuid}");
  107. }
  108. var lumpGuid = proj.AddFile(GetRelativePathFromProj(extraFile), projPathOfFile, PBXSourceTree.Source);
  109. proj.AddFileToBuild(targetGUID, lumpGuid);
  110. }
  111. foreach(var configName in proj.BuildConfigNames())
  112. {
  113. //Debug.Log($"build config:{bcn}");
  114. string configGuid = proj.BuildConfigByName(targetGUID, configName);
  115. string headerSearchPaths = "HEADER_SEARCH_PATHS";
  116. string hspProp = proj.GetBuildPropertyForConfig(configGuid, headerSearchPaths);
  117. //Debug.Log($"config guid:{configGuid} prop:{hspProp}");
  118. string newPro = hspProp.Replace("libil2cpp/include", "libil2cpp")
  119. .Replace("Libraries/bdwgc", "Libraries/external/bdwgc");
  120. //if (!newPro.Contains("Libraries/libil2cpp/os/ClassLibraryPAL/brotli/include"))
  121. //{
  122. // newPro += " $(SRCROOT)/Libraries/libil2cpp/os/ClassLibraryPAL/brotli/include";
  123. //}
  124. if (!newPro.Contains("Libraries/external/xxHash"))
  125. {
  126. newPro += " $(SRCROOT)/Libraries/external/xxHash";
  127. }
  128. newPro += " $(SRCR00T)/Libraries/external/mono";
  129. //Debug.Log($"config:{bcn} new prop:{newPro}");
  130. proj.SetBuildPropertyForConfig(configGuid, headerSearchPaths, newPro);
  131. string cflagKey = "OTHER_CFLAGS";
  132. string cfProp = proj.GetBuildPropertyForConfig(configGuid, cflagKey);
  133. foreach (var flag in cflags)
  134. {
  135. if (!cfProp.Contains(flag))
  136. {
  137. cfProp += " " + flag;
  138. }
  139. }
  140. if (configName.Contains("Debug") && !cfProp.Contains("-DIL2CPP_DEBUG="))
  141. {
  142. cfProp += " -DIL2CPP_DEBUG=1 -DDEBUG=1";
  143. }
  144. proj.SetBuildPropertyForConfig(configGuid, cflagKey, cfProp);
  145. }
  146. proj.WriteToFile(pbxprojFile);
  147. }
  148. private static void CopyLibil2cppToXcodeProj(string srcLibil2cppDir, string dstLibil2cppDir)
  149. {
  150. BashUtil.RemoveDir(dstLibil2cppDir);
  151. BashUtil.CopyDir(srcLibil2cppDir, dstLibil2cppDir, true);
  152. }
  153. private static void CopyExternalToXcodeProj(string srcExternalDir, string dstExternalDir)
  154. {
  155. BashUtil.RemoveDir(dstExternalDir);
  156. BashUtil.CopyDir(srcExternalDir, dstExternalDir, true);
  157. //string baselibPlatfromsDir = $"{dstExternalDir}/baselib/Platforms";
  158. //BashUtil.RemoveDir($"{baselibPlatfromsDir}/IOS");
  159. //BashUtil.CopyDir($"{baselibPlatfromsDir}/OSX", $"{baselibPlatfromsDir}/IOS", true);
  160. }
  161. class LumpFile
  162. {
  163. public List<string> cppFiles = new List<string>();
  164. public readonly string lumpFile;
  165. public readonly string il2cppConfigFile;
  166. public LumpFile(string lumpFile, string il2cppConfigFile)
  167. {
  168. this.lumpFile = lumpFile;
  169. this.il2cppConfigFile = il2cppConfigFile;
  170. this.cppFiles.Add(il2cppConfigFile);
  171. }
  172. public void SaveFile()
  173. {
  174. var lumpFileContent = new List<string>();
  175. foreach (var file in cppFiles)
  176. {
  177. lumpFileContent.Add($"#include \"{GetRelativePathFromProj(file)}\"");
  178. }
  179. File.WriteAllLines(lumpFile, lumpFileContent, Encoding.UTF8);
  180. Debug.Log($"create lump file:{lumpFile}");
  181. }
  182. }
  183. private static List<LumpFile> CreateLumps(string libil2cppDir, string outputDir)
  184. {
  185. BashUtil.RecreateDir(outputDir);
  186. string il2cppConfigFile = $"{libil2cppDir}/il2cpp-config.h";
  187. var lumpFiles = new List<LumpFile>();
  188. int lumpFileIndex = 0;
  189. foreach (var cppDir in Directory.GetDirectories(libil2cppDir, "*", SearchOption.AllDirectories).Concat(new string[] {libil2cppDir}))
  190. {
  191. var lumpFile = new LumpFile($"{outputDir}/lump_{Path.GetFileName(cppDir)}_{lumpFileIndex}.cpp", il2cppConfigFile);
  192. foreach (var file in Directory.GetFiles(cppDir, "*.cpp", SearchOption.TopDirectoryOnly))
  193. {
  194. lumpFile.cppFiles.Add(file);
  195. }
  196. lumpFile.SaveFile();
  197. lumpFiles.Add(lumpFile);
  198. ++lumpFileIndex;
  199. }
  200. var mmFiles = Directory.GetFiles(libil2cppDir, "*.mm", SearchOption.AllDirectories);
  201. if (mmFiles.Length > 0)
  202. {
  203. var lumpFile = new LumpFile($"{outputDir}/lump_mm.mm", il2cppConfigFile);
  204. foreach (var file in mmFiles)
  205. {
  206. lumpFile.cppFiles.Add(file);
  207. }
  208. lumpFile.SaveFile();
  209. lumpFiles.Add(lumpFile);
  210. }
  211. return lumpFiles;
  212. }
  213. private static List<string> GetExtraSourceFiles(string externalDir, string libil2cppDir)
  214. {
  215. var files = new List<string>();
  216. foreach (string extraDir in new string[]
  217. {
  218. $"{externalDir}/zlib",
  219. $"{externalDir}/xxHash",
  220. $"{libil2cppDir}/os/ClassLibraryPAL/brotli",
  221. })
  222. {
  223. if (!Directory.Exists(extraDir))
  224. {
  225. continue;
  226. }
  227. files.AddRange(Directory.GetFiles(extraDir, "*.c", SearchOption.AllDirectories));
  228. }
  229. return files;
  230. }
  231. }
  232. }
  233. #endif