From 42566a7973fd829f67186628d169f46fd9e7438b Mon Sep 17 00:00:00 2001 From: Kris Pypen Date: Thu, 1 Aug 2019 13:44:16 +0200 Subject: [PATCH] add new xcodebuild script --- scripts/Editor/XCodePostBuild.cs | 277 +++++-------------------------- 1 file changed, 37 insertions(+), 240 deletions(-) diff --git a/scripts/Editor/XCodePostBuild.cs b/scripts/Editor/XCodePostBuild.cs index 1100234..5e971b2 100644 --- a/scripts/Editor/XCodePostBuild.cs +++ b/scripts/Editor/XCodePostBuild.cs @@ -21,53 +21,19 @@ SOFTWARE. #if UNITY_IOS using System; -using System.Linq; + using System.Collections.Generic; using System.IO; -using System.Text; -using UnityEngine; using UnityEditor; using UnityEditor.Callbacks; -using UnityEditor.iOS.Xcode; -using Application = UnityEngine.Application; + /// /// Adding this post build script to Unity project enables the flutter-unity-widget to access it /// public static class XcodePostBuild { - /// - /// Path to the root directory of Xcode project. - /// This should point to the directory of '${XcodeProjectName}.xcodeproj'. - /// It is recommended to use relative path here. - /// Current directory is the root directory of this Unity project, i.e. the directory of 'Assets' folder. - /// Sample value: "../xcode" - /// - private const string XcodeProjectRoot = "../../ios"; - - /// - /// Name of the Xcode project. - /// This script looks for '${XcodeProjectName} + ".xcodeproj"' under '${XcodeProjectRoot}'. - /// Sample value: "DemoApp" - /// - private static string XcodeProjectName = Application.productName; - - /// - /// Directories, relative to the root directory of the Xcode project, to put generated Unity iOS build output. - /// - private static string ClassesProjectPath = "UnityExport/Classes"; - private static string LibrariesProjectPath = "UnityExport/Libraries"; - private static string DataProjectPath = "UnityExport/Data"; - - /// - /// Path, relative to the root directory of the Xcode project, to put information about generated Unity output. - /// - private static string ExportsConfigProjectPath = "UnityExport/Exports.xcconfig"; - - private static string PbxFilePath = XcodeProjectName + ".xcodeproj/project.pbxproj"; - - private const string BackupExtension = ".bak"; /// /// The identifier added to touched file to avoid double edits when building to existing directory without @@ -84,108 +50,6 @@ public static class XcodePostBuild } PatchUnityNativeCode(pathToBuiltProject); - - } - - /// - /// Update pbx project file by adding src files and removing extra files that - /// exists in dest but not in src any more. - /// - /// This method only updates the pbx project file. It does not copy or delete - /// files in Swift Xcode project. The Swift Xcode project will do copy and delete - /// during build, and it should copy files if contents are different, regardless - /// of the file time. - /// - /// The pbx project. - /// The directory where Unity project is built. - /// The directory of the Swift Xcode project where the - /// Unity project is embedded into. - /// The prefix of project path in Swift Xcode - /// project for Unity code files. E.g. "DempApp/Unity/Classes" for all files - /// under Classes folder from Unity iOS build output. - private static void ProcessUnityDirectory(PBXProject pbx, string src, string dest, string projectPathPrefix) - { - var targetGuid = pbx.TargetGuidByName(XcodeProjectName); - if (string.IsNullOrEmpty(targetGuid)) { - throw new Exception(string.Format("TargetGuid could not be found for '{0}'", XcodeProjectName)); - } - - // newFiles: array of file names in build output that do not exist in project.pbx manifest. - // extraFiles: array of file names in project.pbx manifest that do not exist in build output. - // Build output files that already exist in project.pbx manifest will be skipped to minimize - // changes to project.pbx file. - string[] newFiles, extraFiles; - CompareDirectories(src, dest, out newFiles, out extraFiles); - - foreach (var f in newFiles) - { - if (ShouldExcludeFile(f)) - { - continue; - } - - var projPath = Path.Combine(projectPathPrefix, f); - if (!pbx.ContainsFileByProjectPath(projPath)) - { - var guid = pbx.AddFile(projPath, projPath); - pbx.AddFileToBuild(targetGuid, guid); - - Debug.LogFormat("Added file to pbx: '{0}'", projPath); - } - } - - foreach (var f in extraFiles) - { - var projPath = Path.Combine(projectPathPrefix, f); - if (pbx.ContainsFileByProjectPath(projPath)) - { - var guid = pbx.FindFileGuidByProjectPath(projPath); - pbx.RemoveFile(guid); - - Debug.LogFormat("Removed file from pbx: '{0}'", projPath); - } - } - } - - /// - /// Compares the directories. Returns files that exists in src and - /// extra files that exists in dest but not in src any more. - /// - private static void CompareDirectories(string src, string dest, out string[] srcFiles, out string[] extraFiles) - { - srcFiles = GetFilesRelativePath(src); - - var destFiles = GetFilesRelativePath(dest); - var extraFilesSet = new HashSet(destFiles); - - extraFilesSet.ExceptWith(srcFiles); - extraFiles = extraFilesSet.ToArray(); - } - - private static string[] GetFilesRelativePath(string directory) - { - var results = new List(); - - if (Directory.Exists(directory)) - { - foreach (var path in Directory.GetFiles(directory, "*", SearchOption.AllDirectories)) - { - var relative = path.Substring(directory.Length).TrimStart('/'); - results.Add(relative); - } - } - - return results.ToArray(); - } - - private static bool ShouldExcludeFile(string fileName) - { - if (fileName.EndsWith(".bak", StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - return false; } /// @@ -193,35 +57,41 @@ public static class XcodePostBuild /// private static void PatchUnityNativeCode(string pathToBuiltProject) { - EditMainMM(Path.Combine(pathToBuiltProject, "Classes/main.mm")); + EditUnityFrameworkH(Path.Combine(pathToBuiltProject, "UnityFramework/UnityFramework.h")); EditUnityAppControllerH(Path.Combine(pathToBuiltProject, "Classes/UnityAppController.h")); EditUnityAppControllerMM(Path.Combine(pathToBuiltProject, "Classes/UnityAppController.mm")); - - if (Application.unityVersion == "2017.1.1f1") - { - EditMetalHelperMM(Path.Combine(pathToBuiltProject, "Classes/Unity/MetalHelper.mm")); - } - - // TODO: Parse unity version number and do range comparison. - if (Application.unityVersion.StartsWith("2017.3.0f") || Application.unityVersion.StartsWith("2017.3.1f")) - { - EditSplashScreenMM(Path.Combine(pathToBuiltProject, "Classes/UI/SplashScreen.mm")); - } } + /// - /// Edit 'main.mm': removes 'main' entry that would conflict with the Xcode project it embeds into. + /// Edit 'UnityFramework.h': add 'frameworkWarmup' /// - private static void EditMainMM(string path) + private static void EditUnityFrameworkH(string path) { + var inScope = false; + + // Add frameworkWarmup method EditCodeFile(path, line => { - if (line.TrimStart().StartsWith("int main", StringComparison.Ordinal)) + inScope |= line.Contains("- (void)runUIApplicationMainWithArgc:"); + + if (inScope) { - return line.Replace("int main", "int old_main"); + if (line.Trim() == "") + { + inScope = false; + + return new string[] + { + "", + "// Added by " + TouchedMarker, + "- (void)frameworkWarmup:(int)argc argv:(char*[])argv;", + "" + }; + } } - return line; + return new string[] { line }; }); } @@ -264,11 +134,11 @@ public static class XcodePostBuild // Modify inline GetAppController EditCodeFile(path, line => { - inScope |= line.Contains("inline UnityAppController"); + inScope |= line.Contains("extern UnityAppController* GetAppController"); if (inScope && !markerDetected) { - if (line.Trim() == "}") + if (line.Trim() == "") { inScope = false; markerDetected = true; @@ -284,21 +154,13 @@ public static class XcodePostBuild }; } - if (!markerAdded) - { - markerAdded = true; - return new string[] - { - "// Modified by " + TouchedMarker, - "// " + line, - }; - } - return new string[] { "// " + line }; } return new string[] { line }; }); + + } /// @@ -356,100 +218,35 @@ public static class XcodePostBuild return new string[] { line }; }); - } - /// - /// Edit 'MetalHelper.mm': fixes a bug (only in 2017.1.1f1) that causes crash. - /// - private static void EditMetalHelperMM(string path) - { - var markerDetected = false; + inScope = false; + markerDetected = false; + // Modify inline GetAppController EditCodeFile(path, line => { - markerDetected |= line.Contains(TouchedMarker); - - if (!markerDetected && line.Trim() == "surface->stencilRB = [surface->device newTextureWithDescriptor: stencilTexDesc];") - { - return new string[] - { - "", - " // Modified by " + TouchedMarker, - " // Default stencilTexDesc.usage has flag 1. In runtime it will cause assertion failure:", - " // validateRenderPassDescriptor:589: failed assertion `Texture at stencilAttachment has usage (0x01) which doesn't specify MTLTextureUsageRenderTarget (0x04)'", - " // Adding MTLTextureUsageRenderTarget seems to fix this issue.", - " stencilTexDesc.usage |= MTLTextureUsageRenderTarget;", - line, - }; - } - - return new string[] { line }; - }); - } - - /// - /// Edit 'SplashScreen.mm': Unity introduces its own 'LaunchScreen.storyboard' since 2017.3.0f3. - /// Disable it here and use Swift project's launch screen instead. - /// - private static void EditSplashScreenMM(string path) { - var markerDetected = false; - var markerAdded = false; - var inScope = false; - var level = 0; - - EditCodeFile(path, line => - { - inScope |= line.Trim() == "void ShowSplashScreen(UIWindow* window)"; - markerDetected |= line.Contains(TouchedMarker); + inScope |= line.Contains("UnityAppController* GetAppController()"); if (inScope && !markerDetected) { - if (line.Trim() == "{") - { - level++; - } - else if (line.Trim() == "}") - { - level--; - } - - if (line.Trim() == "}" && level == 0) + if (line.Trim() == "}") { inScope = false; - } + markerDetected = true; - if (level > 0 && line.Trim().StartsWith("bool hasStoryboard")) - { return new string[] { - " // " + line, - " bool hasStoryboard = false;", + "", }; } - if (!markerAdded) - { - markerAdded = true; - return new string[] - { - "// Modified by " + TouchedMarker, - line, - }; - } + return new string[] { "// " + line }; } return new string[] { line }; }); } - private static void EditCodeFile(string path, Func lineHandler) - { - EditCodeFile(path, line => - { - return new string[] { lineHandler(line) }; - }); - } - private static void EditCodeFile(string path, Func> lineHandler) { var bakPath = path + ".bak";