OpenCVForUnityIOSBuildPostprocessor.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #if (UNITY_5 || UNITY_5_3_OR_NEWER) && UNITY_IOS
  2. using UnityEngine;
  3. using UnityEditor;
  4. using UnityEditor.Callbacks;
  5. using UnityEditor.iOS.Xcode;
  6. using System.Diagnostics;
  7. #if UNITY_2017_2_OR_NEWER
  8. using UnityEditor.iOS.Xcode.Extensions;
  9. #endif
  10. using System;
  11. using System.Linq;
  12. using System.Collections;
  13. using System.IO;
  14. using System.Collections.Generic;
  15. namespace OpenCVForUnity.Editor
  16. {
  17. public class OpenCVForUnityIOSBuildPostprocessor : MonoBehaviour
  18. {
  19. [PostProcessBuild]
  20. public static void OnPostprocessBuild(BuildTarget buildTarget, string path)
  21. {
  22. if (buildTarget == BuildTarget.iOS)
  23. {
  24. string opencvFrameworkPath = Directory.GetDirectories(path, "opencv2.framework", SearchOption.AllDirectories).FirstOrDefault();
  25. if (string.IsNullOrEmpty(opencvFrameworkPath))
  26. throw new System.Exception("Can't find opencv2.framework");
  27. string opencvLibraryPath = Directory.GetFiles(path, "libopencvforunity.a", SearchOption.AllDirectories).FirstOrDefault();
  28. if (string.IsNullOrEmpty(opencvLibraryPath))
  29. throw new System.Exception("Can't find libopencvforunity.a");
  30. //Remove the architecture for the simulator.
  31. if (PlayerSettings.iOS.sdkVersion == iOSSdkVersion.DeviceSDK)
  32. {
  33. #if UNITY_EDITOR_OSX
  34. RemoveSimulatorArchitectures(Path.GetDirectoryName(opencvFrameworkPath), "opencv2.framework/opencv2");
  35. RemoveSimulatorArchitectures(Path.GetDirectoryName(opencvLibraryPath), "libopencvforunity.a");
  36. #else
  37. UnityEngine.Debug.LogError("The RemoveSimulatorArchitectures() method fails when outputting an Xcode project in UnityEditor on non-macOS.\nBefore outputting the Xcode project, please execute the following command on macOS.\n\n//remove i386 architectures.\nlipo - remove i386 opencv2.framework / opencv2 - o opencv2.framework / opencv2\n//remove x86_64 architectures.\nlipo - remove x86_64 opencv2.framework / opencv2 - o opencv2.framework / opencv2\n//check the architectures.\nlipo - info opencv2.framework / opencv2\n\n//remove i386 architectures.\nlipo - remove i386 libopencvforunity.a - o libopencvforunity.a\n//remove x86_64 architectures.\nlipo - remove x86_64 libopencvforunity.a - o libopencvforunity.a\n//check the architectures.\nlipo - info libopencvforunity.a\n");
  38. #endif
  39. }
  40. //Set opencv2.framework to Embedded Binaries.
  41. #if UNITY_5_0 || UNITY_5_1 || UNITY5_2
  42. string projPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj";
  43. #else
  44. string projPath = PBXProject.GetPBXProjectPath(path);
  45. #endif
  46. PBXProject proj = new PBXProject();
  47. proj.ReadFromString(System.IO.File.ReadAllText(projPath));
  48. #if UNITY_2019_3_OR_NEWER
  49. string target = proj.GetUnityFrameworkTargetGuid();
  50. #elif UNITY_5_0 || UNITY_5_1 || UNITY5_2
  51. string target = proj.TargetGuidByName("Unity-iPhone");
  52. #else
  53. string target = proj.TargetGuidByName(PBXProject.GetUnityTargetName());
  54. #endif
  55. #if !UNITY_2018_1_OR_NEWER && UNITY_2017_2_OR_NEWER
  56. string fileGuid = proj.FindFileGuidByProjectPath(opencvFrameworkPath.Substring(path.Length + 1));
  57. proj.AddFileToBuild(target, fileGuid);
  58. proj.AddFileToEmbedFrameworks(target, fileGuid);
  59. foreach (var configName in proj.BuildConfigNames())
  60. {
  61. var configGuid = proj.BuildConfigByName(target, configName);
  62. proj.SetBuildPropertyForConfig(configGuid, "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks");
  63. }
  64. #endif
  65. #if UNITY_2018_3_0 || UNITY_2018_3_1 || UNITY_2018_3_2 || UNITY_2018_3_3
  66. proj.SetBuildProperty(target, "ENABLE_BITCODE", "NO");
  67. #endif
  68. File.WriteAllText(projPath, proj.WriteToString());
  69. //Check if the Target minimum iOS Version is set to 9.0 or higher.
  70. #if UNITY_5_5_OR_NEWER
  71. if ((int)Convert.ToDecimal(PlayerSettings.iOS.targetOSVersionString) < 9)
  72. {
  73. #else
  74. if ((int)PlayerSettings.iOS.targetOSVersion < (int)iOSTargetOSVersion.iOS_9_0) {
  75. #endif
  76. UnityEngine.Debug.LogError("Please set Target minimum iOS Version to 9.0 or higher.");
  77. }
  78. }
  79. }
  80. /// <summary>
  81. /// Removes the simulator architectures.
  82. /// </summary>
  83. /// <param name="workingDirectory">Working directory.</param>
  84. /// <param name="filePath">File path.</param>
  85. private static void RemoveSimulatorArchitectures(string workingDirectory, string filePath)
  86. {
  87. if (!IsSimulatorArchitectures(workingDirectory, filePath)) return;
  88. Process process = new Process();
  89. process.StartInfo.FileName = "/bin/bash";
  90. process.StartInfo.WorkingDirectory = workingDirectory;
  91. process.StartInfo.Arguments = "-c \" ";
  92. process.StartInfo.Arguments += "lipo -remove i386 " + filePath + " -o " + filePath + ";";
  93. process.StartInfo.Arguments += "lipo -remove x86_64 " + filePath + " -o " + filePath + ";";
  94. process.StartInfo.Arguments += "lipo -info " + filePath + ";";
  95. process.StartInfo.Arguments += " \"";
  96. process.StartInfo.UseShellExecute = false;
  97. process.StartInfo.RedirectStandardOutput = true;
  98. process.StartInfo.RedirectStandardError = true;
  99. process.Start();
  100. string output = process.StandardOutput.ReadToEnd();
  101. string error = process.StandardError.ReadToEnd();
  102. process.WaitForExit();
  103. process.Close();
  104. if (string.IsNullOrEmpty(error))
  105. {
  106. UnityEngine.Debug.Log("Success RemoveSimulatorArchitectures() : " + output);
  107. }
  108. else
  109. {
  110. UnityEngine.Debug.LogError("Error RemoveSimulatorArchitectures() : " + error);
  111. }
  112. }
  113. /// <summary>
  114. /// Whether the file contains the simulator architectures?
  115. /// </summary>
  116. /// <param name="workingDirectory">Working directory.</param>
  117. /// <param name="filePath">File path.</param>
  118. private static bool IsSimulatorArchitectures(string workingDirectory, string filePath)
  119. {
  120. Process process = new Process();
  121. process.StartInfo.FileName = "/bin/bash";
  122. process.StartInfo.WorkingDirectory = workingDirectory;
  123. process.StartInfo.Arguments = "-c \" ";
  124. process.StartInfo.Arguments += "lipo -archs " + filePath + ";";
  125. process.StartInfo.Arguments += " \"";
  126. process.StartInfo.UseShellExecute = false;
  127. process.StartInfo.RedirectStandardOutput = true;
  128. process.StartInfo.RedirectStandardError = true;
  129. process.Start();
  130. string output = process.StandardOutput.ReadToEnd();
  131. string error = process.StandardError.ReadToEnd();
  132. process.WaitForExit();
  133. process.Close();
  134. //if (string.IsNullOrEmpty(error))
  135. //{
  136. // UnityEngine.Debug.Log("Success IsSimulatorArchitectures() : " + output);
  137. //}
  138. //else
  139. //{
  140. // UnityEngine.Debug.LogError("Error IsSimulatorArchitectures() : " + error);
  141. // return false;
  142. //}
  143. return output.Contains("i386") || output.Contains("x86_64");
  144. }
  145. }
  146. }
  147. #endif