// Majority of this code was thanks to the com.unity.mobile.notifications package private void EnableIOSPushNotifications(IosSettings settings, string buildPath) { #if UNITY_IOS if (settings.iosPushNotificationType == IOSPushNotificationType.None) { return; } // Turning on push notifications (release/development) var projectPath = buildPath + "/Unity-iPhone.xcodeproj/project.pbxproj"; var project = new UnityEditor.iOS.Xcode.PBXProject(); project.ReadFromString(System.IO.File.ReadAllText(projectPath)); var target = project.TargetGuidByName("Unity-iPhone"); var entitlementsFileName = project.GetBuildPropertyForConfig(target, "CODE_SIGN_ENTITLEMENTS"); if (entitlementsFileName == null) { var bundleIdentifier = UnityEditor.PlayerSettings.GetApplicationIdentifier(UnityEditor.BuildTargetGroup.iOS); entitlementsFileName = string.Format("{0}.entitlements", bundleIdentifier.Substring(bundleIdentifier.LastIndexOf(".") + 1)); } var pbxPath = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(buildPath); var capManager = new UnityEditor.iOS.Xcode.ProjectCapabilityManager(pbxPath, entitlementsFileName, "Unity-iPhone"); capManager.AddPushNotifications(settings.iosPushNotificationType == IOSPushNotificationType.Development); capManager.WriteToFile(); // Making sure Uses Remote Notifications is on var preprocessorPath = buildPath + "/Classes/Preprocessor.h"; var preprocessor = System.IO.File.ReadAllText(preprocessorPath); preprocessor = preprocessor.Replace("UNITY_USES_REMOTE_NOTIFICATIONS 0", "UNITY_USES_REMOTE_NOTIFICATIONS 1"); System.IO.File.WriteAllText(preprocessorPath, preprocessor); #endif }
private static void OnPostprocessBuildIOS(string pathToBuiltProject) { // We use UnityEditor.iOS.Xcode API which only exists in iOS editor module #if UNITY_IOS string projPath = pathToBuiltProject + "/Unity-iPhone.xcodeproj/project.pbxproj"; UnityEditor.iOS.Xcode.PBXProject proj = new UnityEditor.iOS.Xcode.PBXProject(); proj.ReadFromString(File.ReadAllText(projPath)); string target = proj.TargetGuidByName("Unity-iPhone"); Directory.CreateDirectory(Path.Combine(pathToBuiltProject, "Libraries/Unity")); string[] filesToCopy = new string[] { "PlatformBase.h", "RenderAPI_Metal.mm", "RenderAPI_OpenGLCoreES.cpp", "RenderAPI.cpp", "RenderAPI.h", "RenderingPlugin.cpp", }; for (int i = 0; i < filesToCopy.Length; ++i) { var srcPath = Path.Combine("../PluginSource/source", filesToCopy[i]); var dstLocalPath = "Libraries/" + filesToCopy[i]; var dstPath = Path.Combine(pathToBuiltProject, dstLocalPath); File.Copy(srcPath, dstPath, true); proj.AddFileToBuild(target, proj.AddFile(dstLocalPath, dstLocalPath)); } File.WriteAllText(projPath, proj.WriteToString()); #endif // #if UNITY_IOS }
public static void OnPostprocessBuild(BuildTarget buildTarget, string path) { if (buildTarget == BuildTarget.iOS || buildTarget == BuildTarget.tvOS) { #if UNITY_IOS || UNITY_TVOS string projPath = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(path); UnityEditor.iOS.Xcode.PBXProject proj = new UnityEditor.iOS.Xcode.PBXProject(); proj.ReadFromString(File.ReadAllText(projPath)); #if UNITY_2019_3_OR_NEWER string target = proj.GetUnityMainTargetGuid(); #else string targetName = UnityEditor.iOS.Xcode.PBXProject.GetUnityTargetName(); string target = proj.TargetGuidByName(targetName); #endif proj.AddFileToBuild(target, proj.AddFile("usr/lib/libsqlite3.dylib", "Frameworks/libsqlite3.dylib", UnityEditor.iOS.Xcode.PBXSourceTree.Sdk)); proj.AddFileToBuild(target, proj.AddFile("usr/lib/libz.dylib", "Frameworks/libz.dylib", UnityEditor.iOS.Xcode.PBXSourceTree.Sdk)); proj.AddFrameworkToProject(target, "AdSupport.framework", false); proj.AddFrameworkToProject(target, "AppTrackingTransparency.framework", true); //proj.SetBuildProperty(target, "ENABLE_BITCODE", "YES"); #if gameanalytics_topon_enabled string toponHelperFilePath = Path.Combine(path, "Libraries/GameAnalytics/Plugins/iOS/GameAnalyticsTopOnHelper.m"); string contents = File.ReadAllText(toponHelperFilePath); contents = contents.Replace("#if gameanalytics_topon_enabled", "").Replace("#endif", ""); File.WriteAllText(toponHelperFilePath, contents); #endif File.WriteAllText(projPath, proj.WriteToString()); #endif } }
// Majority of this code was thanks to the com.unity.mobile.notifications package private static void EnableIOSPushNotifications(IosSettings settings, string buildPath) { #if UNITY_IOS if (settings.iosPushNotificationType == IOSPushNotificationType.None) { return; } // Turning on push notifications (release/development) var projectPath = buildPath + "/Unity-iPhone.xcodeproj/project.pbxproj"; var project = new UnityEditor.iOS.Xcode.PBXProject(); project.ReadFromString(System.IO.File.ReadAllText(projectPath)); // Push Notification Capability var manager = new UnityEditor.iOS.Xcode.ProjectCapabilityManager( projectPath, "Entitlements.entitlements", targetGuid: project.GetUnityMainTargetGuid() ); manager.AddPushNotifications(settings.iosPushNotificationType == IOSPushNotificationType.Development); manager.WriteToFile(); // Making sure Uses Remote Notifications is on var preprocessorPath = buildPath + "/Classes/Preprocessor.h"; var preprocessor = System.IO.File.ReadAllText(preprocessorPath); preprocessor = preprocessor.Replace("UNITY_USES_REMOTE_NOTIFICATIONS 0", "UNITY_USES_REMOTE_NOTIFICATIONS 1"); System.IO.File.WriteAllText(preprocessorPath, preprocessor); #endif }
public static void OnPostprocessBuild(BuildTarget buildTarget, string path) { if (buildTarget == BuildTarget.iOS || buildTarget == BuildTarget.tvOS) { #if UNITY_IOS || UNITY_TVOS string projPath = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(path); UnityEditor.iOS.Xcode.PBXProject proj = new UnityEditor.iOS.Xcode.PBXProject(); proj.ReadFromString(File.ReadAllText(projPath)); #if UNITY_2019_3_OR_NEWER string target = proj.GetUnityMainTargetGuid(); #else string targetName = UnityEditor.iOS.Xcode.PBXProject.GetUnityTargetName(); string target = proj.TargetGuidByName(targetName); #endif proj.AddFileToBuild(target, proj.AddFile("usr/lib/libsqlite3.dylib", "Frameworks/libsqlite3.dylib", UnityEditor.iOS.Xcode.PBXSourceTree.Sdk)); proj.AddFileToBuild(target, proj.AddFile("usr/lib/libz.dylib", "Frameworks/libz.dylib", UnityEditor.iOS.Xcode.PBXSourceTree.Sdk)); proj.AddFrameworkToProject(target, "AdSupport.framework", false); proj.AddFrameworkToProject(target, "AppTrackingTransparency.framework", true); //proj.SetBuildProperty(target, "ENABLE_BITCODE", "YES"); File.WriteAllText(projPath, proj.WriteToString()); #endif } }
private void OnPostprocessBuildiOS(BuildReport report) { #if UNITY_IOS if (!IsBuiltForAppCenter) { return; } Debug.Log("TestAppPostBuildProcessor.OnPostprocessBuild for target " + report.summary.platform + " at path " + report.summary.outputPath); BuildTarget buildTarget = report.summary.platform; string path = report.summary.outputPath; string projectPath = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(path); var proj = new UnityEditor.iOS.Xcode.PBXProject(); proj.ReadFromString(File.ReadAllText(projectPath)); string xcodeTargetGUID = proj.TargetGuidByName("Unity-iPhone"); proj.AddFrameworkToProject(xcodeTargetGUID, "calabash.framework", false); proj.AddFileToBuild(xcodeTargetGUID, proj.AddFile("calabash.framework", "calabash.framework", UnityEditor.iOS.Xcode.PBXSourceTree.Source)); proj.SetBuildProperty(xcodeTargetGUID, "FRAMEWORK_SEARCH_PATHS", "$(inherited)"); proj.AddBuildProperty(xcodeTargetGUID, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)"); proj.AddBuildProperty(xcodeTargetGUID, "OTHER_LDFLAGS", "-ObjC"); proj.AddBuildProperty(xcodeTargetGUID, "OTHER_LDFLAGS", "-force_load"); proj.AddBuildProperty(xcodeTargetGUID, "OTHER_LDFLAGS", "$(SOURCE_ROOT)/calabash.framework/calabash"); proj.AddBuildProperty(xcodeTargetGUID, "OTHER_LDFLAGS", "-framework"); proj.AddBuildProperty(xcodeTargetGUID, "OTHER_LDFLAGS", "CFNetwork"); File.WriteAllText(projectPath, proj.WriteToString()); #endif }
public static void OnPostprocessBuild(BuildTarget buildTarget, string path) { if (buildTarget == BuildTarget.iOS || buildTarget == BuildTarget.tvOS) { #if UNITY_IOS || UNITY_TVOS string projPath = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(path); UnityEditor.iOS.Xcode.PBXProject proj = new UnityEditor.iOS.Xcode.PBXProject(); proj.ReadFromString(File.ReadAllText(projPath)); #if UNITY_2019_3_OR_NEWER string target = proj.GetUnityMainTargetGuid(); #else string targetName = UnityEditor.iOS.Xcode.PBXProject.GetUnityTargetName(); string target = proj.TargetGuidByName(targetName); #endif proj.AddFileToBuild(target, proj.AddFile("usr/lib/libsqlite3.dylib", "Frameworks/libsqlite3.dylib", UnityEditor.iOS.Xcode.PBXSourceTree.Sdk)); proj.AddFileToBuild(target, proj.AddFile("usr/lib/libz.dylib", "Frameworks/libz.dylib", UnityEditor.iOS.Xcode.PBXSourceTree.Sdk)); proj.AddFrameworkToProject(target, "AdSupport.framework", false); proj.AddFrameworkToProject(target, "AppTrackingTransparency.framework", true); //proj.SetBuildProperty(target, "ENABLE_BITCODE", "YES"); #if gameanalytics_topon_enabled string toponSubPath = "Libraries/GameAnalytics/Plugins/iOS/GameAnalyticsTopOnHelper.m"; string[] topOnGuids = AssetDatabase.FindAssets("GameAnalyticsTopOnHelper", null); if (topOnGuids.Length > 0) { string[] p = AssetDatabase.GUIDToAssetPath(topOnGuids[0]).Split(new char[] { '/' }, 2); if (p.Length > 1) { toponSubPath = "Libraries/" + p[1]; } } string toponHelperFilePath = Path.Combine(path, toponSubPath); string topOncontents = File.ReadAllText(toponHelperFilePath); topOncontents = topOncontents.Replace("#if gameanalytics_topon_enabled", "").Replace("#endif", ""); File.WriteAllText(toponHelperFilePath, topOncontents); #endif #if gameanalytics_hyperbid_enabled string hyperbidSubPath = "Libraries/GameAnalytics/Plugins/iOS/GameAnalyticsHyperBidHelper.m"; string[] hyperBidGuids = AssetDatabase.FindAssets("GameAnalyticsHyperBidHelper", null); if (hyperBidGuids.Length > 0) { string[] p = AssetDatabase.GUIDToAssetPath(hyperBidGuids[0]).Split(new char[] { '/' }, 2); if (p.Length > 1) { hyperbidSubPath = "Libraries/" + p[1]; } } string hyperbidHelperFilePath = Path.Combine(path, hyperbidSubPath); string hyperbidContents = File.ReadAllText(hyperbidHelperFilePath); hyperbidContents = hyperbidContents.Replace("#if gameanalytics_hyperbid_enabled", "").Replace("#endif", ""); File.WriteAllText(hyperbidHelperFilePath, hyperbidContents); #endif File.WriteAllText(projPath, proj.WriteToString()); #endif } }
private UnityEditor.iOS.Xcode.PBXProject GetXcodeProject(string path) { xcodeProjectPath = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(path); UnityEditor.iOS.Xcode.PBXProject proj = new UnityEditor.iOS.Xcode.PBXProject(); proj.ReadFromFile(xcodeProjectPath); return(proj); }
public void OnPostprocessBuild(BuildReport report) { var summary = report.summary; if (summary.platform == BuildTarget.iOS) { var appTrackingTransparencySettings = AppTrackingTransparencySettingsManager.LoadSettings(); if (!appTrackingTransparencySettings.AutomaticPostProcessing) { return; } var projectPath = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(summary.outputPath); var pbxProject = new UnityEditor.iOS.Xcode.PBXProject(); pbxProject.ReadFromFile(projectPath); #if UNITY_2019_3_OR_NEWER var frameworkTargetGuid = pbxProject.GetUnityFrameworkTargetGuid(); var mainTargetGuid = pbxProject.GetUnityMainTargetGuid(); #else var frameworkTargetGuid = pbxProject.GetUnityTargetName(); var mainTargetGuid = pbxProject.GetUnityTargetName(); #endif if (appTrackingTransparencySettings.AddAppTransparencyTrackingFramework) { pbxProject.AddFrameworkToProject(frameworkTargetGuid, "AppTrackingTransparency.framework", true); } if (appTrackingTransparencySettings.AddUserTrackingUsageDescription) { string infoPlistPath; if (appTrackingTransparencySettings.AutoDetectInfoPlistFilePath) { infoPlistPath = Path.Combine( summary.outputPath, pbxProject.GetBuildPropertyForAnyConfig(mainTargetGuid, "INFOPLIST_FILE")); } else { infoPlistPath = Path.Combine( summary.outputPath, appTrackingTransparencySettings.MainInfoPlistFilePath); } var infoPlist = new UnityEditor.iOS.Xcode.PlistDocument(); infoPlist.ReadFromFile(infoPlistPath); infoPlist.root.SetString("NSUserTrackingUsageDescription", appTrackingTransparencySettings.UserTrackingUsageDescription); infoPlist.WriteToFile(infoPlistPath); } pbxProject.WriteToFile(projectPath); } }
/// <summary> /// Creates a new instance of ProjectCapabilityManager. The returned /// instance assumes ownership of the referenced pbxproj project file, /// the entitlements file and project Info.plist files until the last /// WriteToFile() call. /// </summary> /// <param name="pbxProjectPath">Path to the pbxproj file.</param> /// <param name="entitlementFilePath">Path to the entitlements file.</param> /// <param name="targetName">The name of the target to add entitlements for.</param> public ProjectCapabilityManager(string pbxProjectPath, string entitlementFilePath, string targetName) { m_BuildPath = Directory.GetParent(Path.GetDirectoryName(pbxProjectPath)).FullName; m_EntitlementFilePath = entitlementFilePath; m_PBXProjectPath = pbxProjectPath; project = new PBXProject(); project.ReadFromString(File.ReadAllText(m_PBXProjectPath)); #if UNITY_2019_3_OR_NEWER var proj = new UnityEditor.iOS.Xcode.PBXProject(); proj.ReadFromString(File.ReadAllText(m_PBXProjectPath)); m_TargetGuid = proj.GetUnityMainTargetGuid(); #else m_TargetGuid = project.TargetGuidByName(targetName); #endif }
public static void DisableBitCode(BuildTarget buildTarget, string path) { #if UNITY_IOS if (buildTarget == BuildTarget.iOS) { string projectPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj"; var pbxProject = new UnityEditor.iOS.Xcode.PBXProject(); pbxProject.ReadFromFile(projectPath); string target = pbxProject.TargetGuidByName("Unity-iPhone"); pbxProject.SetBuildProperty(target, "ENABLE_BITCODE", "NO"); pbxProject.WriteToFile(projectPath); } #endif }
public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject) { if (target == BuildTarget.iOS) { #if UNITY_IOS var projectPath = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(pathToBuiltProject); var project = new UnityEditor.iOS.Xcode.PBXProject(); project.ReadFromFile(projectPath); var targetId = project.GetUnityFrameworkTargetGuid(); project.AddFileToBuildSection( targetId, project.GetResourcesBuildPhaseByTarget(targetId), project.FindFileGuidByRealPath("Data") ); project.WriteToFile(projectPath); #endif } }
private static void DisableBitCode(IosSettings settings, string path) { if (settings.disableIOSBitCode == false) { return; } Debug.Log("Disabling BitCode..."); #if UNITY_IOS string projectPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj"; var pbxProject = new UnityEditor.iOS.Xcode.PBXProject(); pbxProject.ReadFromFile(projectPath); string target = pbxProject.TargetGuidByName("Unity-iPhone"); pbxProject.SetBuildProperty(target, "ENABLE_BITCODE", "NO"); pbxProject.WriteToFile(projectPath); #endif }
public static void OnPostProcessPatchProject(BuildTarget buildTarget, string pathToBuiltProject) { if (!InjectDependencies()) { return; } var podsWithoutBitcode = FindPodsWithBitcodeDisabled(); bool bitcodeDisabled = podsWithoutBitcode.Count > 0; if (bitcodeDisabled) { Log("Bitcode is disabled due to the following Cocoapods (" + String.Join(", ", podsWithoutBitcode.ToArray()) + ")", level: LogLevel.Warning); } // Configure project settings for Cocoapods. string pbxprojPath = GetProjectPath(pathToBuiltProject); var project = new UnityEditor.iOS.Xcode.PBXProject(); project.ReadFromString(File.ReadAllText(pbxprojPath)); string target = project.TargetGuidByName(TARGET_NAME); project.SetBuildProperty(target, "CLANG_ENABLE_MODULES", "YES"); project.AddBuildProperty(target, "OTHER_LDFLAGS", "$(inherited)"); project.AddBuildProperty(target, "OTHER_CFLAGS", "$(inherited)"); project.AddBuildProperty(target, "HEADER_SEARCH_PATHS", "$(inherited)"); project.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(inherited)"); project.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)/Frameworks"); project.AddBuildProperty(target, "OTHER_LDFLAGS", "-ObjC"); if (bitcodeDisabled) { project.AddBuildProperty(target, "ENABLE_BITCODE", "NO"); } File.WriteAllText(pbxprojPath, project.WriteToString()); }
public static void OnPostProcessUpdateProjectDeps( BuildTarget buildTarget, string pathToBuiltProject) { if (!InjectDependencies()) { return; } // If the Pods directory does not exist, the pod download step // failed. var podsDir = Path.Combine(pathToBuiltProject, "Pods"); if (!Directory.Exists(podsDir)) { return; } Directory.CreateDirectory(Path.Combine(pathToBuiltProject, "Frameworks")); Directory.CreateDirectory(Path.Combine(pathToBuiltProject, "Resources")); string pbxprojPath = GetProjectPath(pathToBuiltProject); var project = new UnityEditor.iOS.Xcode.PBXProject(); project.ReadFromString(File.ReadAllText(pbxprojPath)); string target = project.TargetGuidByName(TARGET_NAME); HashSet <string> frameworks = new HashSet <string>(); HashSet <string> linkFlags = new HashSet <string>(); foreach (var frameworkFullPath in Directory.GetDirectories(podsDir, "*.framework", SearchOption.AllDirectories)) { string frameworkName = new DirectoryInfo(frameworkFullPath).Name; string destFrameworkPath = Path.Combine("Frameworks", frameworkName); string destFrameworkFullPath = Path.Combine(pathToBuiltProject, destFrameworkPath); // Only move this framework if it contains a library. // Skip frameworks that consist of just resources, they're handled // in a separate import step. if (!File.Exists(Path.Combine( frameworkFullPath, Path.GetFileName(frameworkFullPath) .Replace(".framework", "")))) { continue; } PlayServicesSupport.DeleteExistingFileOrDirectory( destFrameworkFullPath); Directory.Move(frameworkFullPath, destFrameworkFullPath); project.AddFileToBuild( target, project.AddFile(destFrameworkPath, destFrameworkPath, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); string moduleMapPath = Path.Combine(Path.Combine(destFrameworkFullPath, "Modules"), "module.modulemap"); if (File.Exists(moduleMapPath)) { // Parse the modulemap, format spec here: // http://clang.llvm.org/docs/Modules.html#module-map-language using (StreamReader moduleMapFile = new StreamReader(moduleMapPath)) { string line; char[] delim = { ' ' }; while ((line = moduleMapFile.ReadLine()) != null) { string[] items = line.TrimStart(delim).Split(delim, 2); if (items.Length > 1) { if (items[0] == "link") { if (items[1].StartsWith("framework")) { items = items[1].Split(delim, 2); frameworks.Add(items[1].Trim( new char[] { '\"' }) + ".framework"); } else { linkFlags.Add("-l" + items[1]); } } } } } } string resourcesFolder = Path.Combine(destFrameworkFullPath, "Resources"); if (Directory.Exists(resourcesFolder)) { string[] resFiles = Directory.GetFiles(resourcesFolder); string[] resFolders = Directory.GetDirectories(resourcesFolder); foreach (var resFile in resFiles) { string destFile = Path.Combine("Resources", Path.GetFileName(resFile)); File.Copy(resFile, Path.Combine(pathToBuiltProject, destFile), true); project.AddFileToBuild( target, project.AddFile( destFile, destFile, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); } foreach (var resFolder in resFolders) { string destFolder = Path.Combine("Resources", new DirectoryInfo(resFolder).Name); string destFolderFullPath = Path.Combine(pathToBuiltProject, destFolder); PlayServicesSupport.DeleteExistingFileOrDirectory( destFolderFullPath); Directory.Move(resFolder, destFolderFullPath); project.AddFileToBuild( target, project.AddFile( destFolder, destFolder, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); } } } foreach (var framework in frameworks) { project.AddFrameworkToProject(target, framework, false); } foreach (var linkFlag in linkFlags) { project.AddBuildProperty(target, "OTHER_LDFLAGS", linkFlag); } File.WriteAllText(pbxprojPath, project.WriteToString()); }
public static void OnPostProcessPatchProject(BuildTarget buildTarget, string pathToBuiltProject) { if (!InjectDependencies()) return; var podsWithoutBitcode = FindPodsWithBitcodeDisabled(); bool bitcodeDisabled = podsWithoutBitcode.Count > 0; if (bitcodeDisabled) { Log("Bitcode is disabled due to the following Cocoapods (" + String.Join(", ", podsWithoutBitcode.ToArray()) + ")", level: LogLevel.Warning); } // Configure project settings for Cocoapods. string pbxprojPath = GetProjectPath(pathToBuiltProject); var project = new UnityEditor.iOS.Xcode.PBXProject(); project.ReadFromString(File.ReadAllText(pbxprojPath)); string target = project.TargetGuidByName(TARGET_NAME); project.SetBuildProperty(target, "CLANG_ENABLE_MODULES", "YES"); project.AddBuildProperty(target, "OTHER_LDFLAGS", "$(inherited)"); project.AddBuildProperty(target, "OTHER_CFLAGS", "$(inherited)"); project.AddBuildProperty(target, "HEADER_SEARCH_PATHS", "$(inherited)"); project.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(inherited)"); project.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)/Frameworks"); project.AddBuildProperty(target, "OTHER_LDFLAGS", "-ObjC"); if (bitcodeDisabled) { project.AddBuildProperty(target, "ENABLE_BITCODE", "NO"); } File.WriteAllText(pbxprojPath, project.WriteToString()); }
// Implementation of OnPostProcessUpdateProjectDeps(). // NOTE: This is separate from the post-processing method to prevent the // Mono runtime from loading the Xcode API before calling the post // processing step. public static void UpdateProjectDeps( BuildTarget buildTarget, string pathToBuiltProject) { // If the Pods directory does not exist, the pod download step // failed. var podsDir = Path.Combine(pathToBuiltProject, PODS_DIR); if (!Directory.Exists(podsDir)) { return; } Directory.CreateDirectory(Path.Combine(pathToBuiltProject, "Frameworks")); Directory.CreateDirectory(Path.Combine(pathToBuiltProject, "Resources")); string pbxprojPath = GetProjectPath(pathToBuiltProject); var project = new UnityEditor.iOS.Xcode.PBXProject(); project.ReadFromString(File.ReadAllText(pbxprojPath)); string target = project.TargetGuidByName(TARGET_NAME); HashSet <string> frameworks = new HashSet <string>(); HashSet <string> linkFlags = new HashSet <string>(); foreach (var frameworkFullPath in Directory.GetDirectories(podsDir, "*.framework", SearchOption.AllDirectories)) { string frameworkName = new DirectoryInfo(frameworkFullPath).Name; string destFrameworkPath = Path.Combine("Frameworks", frameworkName); string destFrameworkFullPath = Path.Combine(pathToBuiltProject, destFrameworkPath); // Only move this framework if it contains a library. // Skip frameworks that consist of just resources, they're handled // in a separate import step. if (!File.Exists(Path.Combine( frameworkFullPath, Path.GetFileName(frameworkFullPath) .Replace(".framework", "")))) { continue; } PlayServicesSupport.DeleteExistingFileOrDirectory( destFrameworkFullPath); Directory.Move(frameworkFullPath, destFrameworkFullPath); project.AddFileToBuild( target, project.AddFile(destFrameworkPath, destFrameworkPath, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); string moduleMapPath = Path.Combine(Path.Combine(destFrameworkFullPath, "Modules"), "module.modulemap"); if (File.Exists(moduleMapPath)) { // Parse the modulemap, format spec here: // http://clang.llvm.org/docs/Modules.html#module-map-language using (StreamReader moduleMapFile = new StreamReader(moduleMapPath)) { string line; char[] delim = { ' ' }; while ((line = moduleMapFile.ReadLine()) != null) { string[] items = line.TrimStart(delim).Split(delim, 2); if (items.Length > 1) { if (items[0] == "link") { if (items[1].StartsWith("framework")) { items = items[1].Split(delim, 2); frameworks.Add(items[1].Trim( new char[] { '\"' }) + ".framework"); } else { linkFlags.Add("-l" + items[1]); } } } } } } string resourcesFolder = Path.Combine(destFrameworkFullPath, "Resources"); if (Directory.Exists(resourcesFolder)) { string[] resFiles = Directory.GetFiles(resourcesFolder); string[] resFolders = Directory.GetDirectories(resourcesFolder); foreach (var resFile in resFiles) { string destFile = Path.Combine("Resources", Path.GetFileName(resFile)); File.Copy(resFile, Path.Combine(pathToBuiltProject, destFile), true); project.AddFileToBuild( target, project.AddFile( destFile, destFile, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); } foreach (var resFolder in resFolders) { string destFolder = Path.Combine("Resources", new DirectoryInfo(resFolder).Name); string destFolderFullPath = Path.Combine(pathToBuiltProject, destFolder); PlayServicesSupport.DeleteExistingFileOrDirectory( destFolderFullPath); Directory.Move(resFolder, destFolderFullPath); project.AddFileToBuild( target, project.AddFile( destFolder, destFolder, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); } } } foreach (var framework in frameworks) { project.AddFrameworkToProject(target, framework, false); } foreach (var linkFlag in linkFlags) { project.AddBuildProperty(target, "OTHER_LDFLAGS", linkFlag); } // Add all source files found under the pods directory to the project. // This is a very crude way of partially supporting source pods. var podPathToProjectPaths = new Dictionary <string, string>(); // Find pod source files and map them to paths relative to the target // Xcode project. foreach (var filename in FindFilesWithExtensions(podsDir, SOURCE_FILE_EXTENSIONS)) { // Save the path relative to the target project for each path // relative to the generated pods Xcode project. // +1 in the following expressions to strip the file separator. podPathToProjectPaths[filename.Substring(podsDir.Length + 1)] = filename.Substring(pathToBuiltProject.Length + 1); } // Add a reference to each source file in the target project. foreach (var podPathProjectPath in podPathToProjectPaths) { project.AddFileToBuild( target, project.AddFile(podPathProjectPath.Value, podPathProjectPath.Value, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); } // Attempt to read per-file compile / build settings from the Pods // project. var podsProjectPath = GetProjectPath(podsDir, PODS_PROJECT_NAME); var podsProject = new UnityEditor.iOS.Xcode.PBXProject(); podsProject.ReadFromString(File.ReadAllText(podsProjectPath)); foreach (var directory in Directory.GetDirectories(podsDir)) { // Each pod will have a top level directory under the pods dir // named after the pod. Also, some pods have build targets in the // xcode project where each build target has the same name as the // pod such that pod Foo is in directory Foo with build target Foo. // Since we can't read the build targets from the generated Xcode // project using Unity's API, we scan the Xcode project for targets // to optionally retrieve build settings for each source file // the settings can be applied in the target project. var podTargetName = Path.GetFileName(directory); var podTargetGuid = podsProject.TargetGuidByName(podTargetName); Log(String.Format("Looking for target: {0} guid: {1}", podTargetName, podTargetGuid ?? "null"), verbose: true); if (podTargetGuid == null) { continue; } foreach (var podPathProjectPath in podPathToProjectPaths) { var podSourceFileGuid = podsProject.FindFileGuidByRealPath( podPathProjectPath.Key); if (podSourceFileGuid == null) { continue; } var podSourceFileCompileFlags = podsProject.GetCompileFlagsForFile(podTargetGuid, podSourceFileGuid); if (podSourceFileCompileFlags == null) { continue; } var targetSourceFileGuid = project.FindFileGuidByProjectPath( podPathProjectPath.Value); if (targetSourceFileGuid == null) { Log("Unable to find " + podPathProjectPath.Value + " in generated project", level: LogLevel.Warning); continue; } Log(String.Format( "Setting {0} compile flags to ({1})", podPathProjectPath.Key, String.Join(", ", podSourceFileCompileFlags.ToArray())), verbose: true); project.SetCompileFlagsForFile(target, targetSourceFileGuid, podSourceFileCompileFlags); } } File.WriteAllText(pbxprojPath, project.WriteToString()); }
public static void OnPostProcessBuild(BuildTarget buildTarget, string buildPath) { if (buildTarget != BuildTarget.iOS) { return; } #if UNITY_IOS var proj = new UnityEditor.iOS.Xcode.PBXProject(); string projPath = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(buildPath); proj.ReadFromFile(projPath); string target = proj.TargetGuidByName("Unity-iPhone"); string plistPath = buildPath + "/Info.plist"; var plist = new UnityEditor.iOS.Xcode.PlistDocument(); plist.ReadFromFile(plistPath); //获取所有的配置文件 string CONFIG_PATH = Application.dataPath + "/../SDK/iOS/"; List <Unity_Xcode_Json> jsons = new List <Unity_Xcode_Json>(); string[] files = Directory.GetFiles(CONFIG_PATH, "*.json", SearchOption.TopDirectoryOnly); for (int i = 0; i < files.Length; i++) { jsons.Add(JsonUtility.FromJson <Unity_Xcode_Json>(File.ReadAllText(files[i]))); } //创建资源目录 string frameworkPath = buildPath + "/Frameworks/Plugins/iOS/"; if (!Directory.Exists(frameworkPath)) { Directory.CreateDirectory(frameworkPath); } string aPath = buildPath + "/Libraries/Plugins/iOS/"; if (!Directory.Exists(aPath)) { Directory.CreateDirectory(aPath); } proj.SetBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(SRCROOT)/Frameworks/Plugins/iOS"); proj.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(inherited)"); proj.SetBuildProperty(target, "LIBRARY_SEARCH_PATHS", "$(SRCROOT)/Libraries/Plugins/iOS"); proj.AddBuildProperty(target, "LIBRARY_SEARCH_PATHS", "$(SRCROOT)/Libraries"); proj.AddBuildProperty(target, "LIBRARY_SEARCH_PATHS", "$(SRCROOT)"); proj.AddBuildProperty(target, "LIBRARY_SEARCH_PATHS", "$(inherited)"); for (int i = 0; i < jsons.Count; i++) { Unity_Xcode_Json json = jsons[i]; //系统静态库引用 if (json.internal_frameworks != null) { for (int j = 0; j < json.internal_frameworks.Length; j++) { proj.AddFrameworkToProject(target, json.internal_frameworks[j], false); } } //系统动态库引用 if (json.internal_dynamiclibs != null) { for (int j = 0; j < json.internal_dynamiclibs.Length; j++) { proj.AddFileToBuild(target, proj.AddFile("usr/lib/" + json.internal_dynamiclibs[j], "Frameworks/" + json.internal_dynamiclibs[j], UnityEditor.iOS.Xcode.PBXSourceTree.Sdk)); } } //外部静态库引用 if (json.external_frameworks != null) { for (int j = 0; j < json.external_frameworks.Length; j++) { EditorUtils_Common.copy_files(CONFIG_PATH + json.external_frameworks[j], frameworkPath); string fileName = Path.GetFileName(json.external_frameworks[j]); proj.AddFileToBuild(target, proj.AddFile("Frameworks/Plugins/iOS/" + fileName, "Frameworks/" + fileName, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); } } //外部静态库引用 if (json.external_staticlibs != null) { for (int j = 0; j < json.external_staticlibs.Length; j++) { EditorUtils_Common.copy_files(CONFIG_PATH + json.external_staticlibs[j], aPath); string fileName = Path.GetFileName(json.external_staticlibs[j]); proj.AddFileToBuild(target, proj.AddFile("Libraries/Plugins/iOS/" + fileName, "Libraries/" + fileName, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); } } //外部文件引用 if (json.external_files != null) { for (int j = 0; j < json.external_files.Length; j++) { EditorUtils_Common.copy_files(CONFIG_PATH + json.external_files[j], aPath); string fileName = Path.GetFileName(json.external_files[j]); proj.AddFileToBuild(target, proj.AddFile("Libraries/Plugins/iOS/" + fileName, "Libraries/" + fileName, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); } } if (json.lib_searchpath != null) { for (int j = 0; j < json.lib_searchpath.Length; j++) { proj.AddBuildProperty(target, "LIBRARY_SEARCH_PATHS", "$(SRCROOT)/Libraries/Plugins/iOS/" + json.lib_searchpath[j]); } } if (json.framework_searchpath != null) { for (int j = 0; j < json.framework_searchpath.Length; j++) { proj.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(SRCROOT)/Frameworks/Plugins/iOS/" + json.framework_searchpath[j]); } } //BuildSetting if (json.buildset_set != null) { for (int j = 0; j < json.buildset_set.Length; j++) { proj.SetBuildProperty(target, json.buildset_set[j].key, json.buildset_set[j].value); } } if (json.buildset_add != null) { for (int j = 0; j < json.buildset_add.Length; j++) { proj.UpdateBuildProperty(target, json.buildset_add[j].key, new List <string>() { json.buildset_add[j].value }, new List <string>()); } } //Info.plist if (json.plistset != null) { var dict = plist.root.AsDict(); for (int j = 0; j < json.plistset.Length; j++) { dict.SetString(json.plistset[j].key, json.plistset[j].value); } } if (json.plistarray != null) { var dict = plist.root.AsDict(); for (int j = 0; j < json.plistarray.Length; j++) { var array = dict.CreateArray(json.plistarray[j].key); for (int k = 0; k < json.plistarray[j].value.Length; k++) { array.AddString(json.plistarray[j].value[k]); } } } if (json.plistarraydict != null) { var dict = plist.root.AsDict(); for (int j = 0; j < json.plistarraydict.Length; j++) { var arrayDict = dict.CreateDict(json.plistarraydict[j].key); var array = arrayDict.CreateArray(json.plistarraydict[j].value.key); for (int k = 0; k < json.plistarraydict[j].value.value.Length; k++) { array.AddString(json.plistarraydict[j].value.value[k]); } } } } proj.WriteToFile(projPath); plist.WriteToFile(plistPath); #endif }
public static void OnPostProcessUpdateProjectDeps( BuildTarget buildTarget, string pathToBuiltProject) { if (!InjectDependencies()) return; // If the Pods directory does not exist, the pod download step // failed. var podsDir = Path.Combine(pathToBuiltProject, "Pods"); if (!Directory.Exists(podsDir)) return; Directory.CreateDirectory(Path.Combine(pathToBuiltProject, "Frameworks")); Directory.CreateDirectory(Path.Combine(pathToBuiltProject, "Resources")); string pbxprojPath = GetProjectPath(pathToBuiltProject); var project = new UnityEditor.iOS.Xcode.PBXProject(); project.ReadFromString(File.ReadAllText(pbxprojPath)); string target = project.TargetGuidByName(TARGET_NAME); HashSet<string> frameworks = new HashSet<string>(); HashSet<string> linkFlags = new HashSet<string>(); foreach (var frameworkFullPath in Directory.GetDirectories(podsDir, "*.framework", SearchOption.AllDirectories)) { string frameworkName = new DirectoryInfo(frameworkFullPath).Name; string destFrameworkPath = Path.Combine("Frameworks", frameworkName); string destFrameworkFullPath = Path.Combine(pathToBuiltProject, destFrameworkPath); // Only move this framework if it contains a library. // Skip frameworks that consist of just resources, they're handled // in a separate import step. if (!File.Exists(Path.Combine( frameworkFullPath, Path.GetFileName(frameworkFullPath) .Replace(".framework", "")))) { continue; } PlayServicesSupport.DeleteExistingFileOrDirectory( destFrameworkFullPath); Directory.Move(frameworkFullPath, destFrameworkFullPath); project.AddFileToBuild( target, project.AddFile(destFrameworkPath, destFrameworkPath, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); string moduleMapPath = Path.Combine(Path.Combine(destFrameworkFullPath, "Modules"), "module.modulemap"); if (File.Exists(moduleMapPath)) { // Parse the modulemap, format spec here: // http://clang.llvm.org/docs/Modules.html#module-map-language using (StreamReader moduleMapFile = new StreamReader(moduleMapPath)) { string line; char[] delim = {' '}; while ((line = moduleMapFile.ReadLine()) != null) { string[] items = line.TrimStart(delim).Split(delim, 2); if (items.Length > 1) { if (items[0] == "link") { if (items[1].StartsWith("framework")) { items = items[1].Split(delim, 2); frameworks.Add(items[1].Trim( new char[] {'\"'}) + ".framework"); } else { linkFlags.Add("-l" + items[1]); } } } } } } string resourcesFolder = Path.Combine(destFrameworkFullPath, "Resources"); if (Directory.Exists(resourcesFolder)) { string[] resFiles = Directory.GetFiles(resourcesFolder); string[] resFolders = Directory.GetDirectories(resourcesFolder); foreach (var resFile in resFiles) { string destFile = Path.Combine("Resources", Path.GetFileName(resFile)); File.Copy(resFile, Path.Combine(pathToBuiltProject, destFile), true); project.AddFileToBuild( target, project.AddFile( destFile, destFile, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); } foreach (var resFolder in resFolders) { string destFolder = Path.Combine("Resources", new DirectoryInfo(resFolder).Name); string destFolderFullPath = Path.Combine(pathToBuiltProject, destFolder); PlayServicesSupport.DeleteExistingFileOrDirectory( destFolderFullPath); Directory.Move(resFolder, destFolderFullPath); project.AddFileToBuild( target, project.AddFile( destFolder, destFolder, UnityEditor.iOS.Xcode.PBXSourceTree.Source)); } } } foreach (var framework in frameworks) { project.AddFrameworkToProject(target, framework, false); } foreach (var linkFlag in linkFlags) { project.AddBuildProperty(target, "OTHER_LDFLAGS", linkFlag); } File.WriteAllText(pbxprojPath, project.WriteToString()); }
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) { if (target != BuildTarget.iOS) { return; } #if UNITY_IPHONE && UNITY_EDITOR_WIN UnityEngine.Debug.LogWarning("ISD Postprocess is not avaliable for Win"); #endif #if UNITY_IPHONE && UNITY_EDITOR_OSX UnityEngine.Debug.Log("SA.IOSDeploy.PostProcess Started"); Process myCustomProcess = new Process(); myCustomProcess.StartInfo.FileName = "python"; List <string> frmwrkWithOpt = new List <string>(); foreach (BaseFramework framework in ISD_Settings.Instance.BaseFrameworks) { string optional = "|0"; if (framework.IsOptional) { optional = "|1"; } frmwrkWithOpt.Add(framework.Name + optional); } List <string> libWithOpt = new List <string>(); foreach (Lib lib in ISD_Settings.Instance.Libraries) { string optional = "|0"; if (lib.IsOptional) { optional = "|1"; } libWithOpt.Add(lib.Name + optional); } foreach (string fileName in ISD_Settings.Instance.langFolders) { string tempPath = Path.Combine(pathToBuiltProject, fileName + ".lproj"); if (!Directory.Exists(tempPath)) { Directory.CreateDirectory(tempPath); } } List <string> LinkerFlags = new List <string>(); List <string> CompileFlags = new List <string>(); foreach (Flag flag in ISD_Settings.Instance.Flags) { if (flag.Type.Equals(FlagType.LinkerFlag)) { LinkerFlags.Add(flag.Name); } else if (flag.Type.Equals(FlagType.CompilerFlag)) { CompileFlags.Add(flag.Name); } } string frameworks = string.Join(" ", frmwrkWithOpt.ToArray()); string libraries = string.Join(" ", libWithOpt.ToArray()); string linkFlags = string.Join(" ", LinkerFlags.ToArray()); string compileFlags = string.Join(" ", CompileFlags.ToArray()); string languageFolders = string.Join(" ", ISD_Settings.Instance.langFolders.ToArray()); #if UNITY_5 if (BuildTarget.iOS == target) { UnityEditor.iOS.Xcode.PBXProject proj = new UnityEditor.iOS.Xcode.PBXProject(); string projPath = Path.Combine(pathToBuiltProject, "Unity-iPhone.xcodeproj/project.pbxproj"); proj.ReadFromString(File.ReadAllText(projPath)); string targetGUID = proj.TargetGuidByName("Unity-iPhone"); if (ISD_Settings.Instance.enableBitCode) { proj.SetBuildProperty(targetGUID, "ENABLE_BITCODE", "YES"); } else { proj.SetBuildProperty(targetGUID, "ENABLE_BITCODE", "NO"); } if (ISD_Settings.Instance.enableTestability) { proj.SetBuildProperty(targetGUID, "ENABLE_TESTABILITY", "YES"); } else { proj.SetBuildProperty(targetGUID, "ENABLE_TESTABILITY", "NO"); } if (ISD_Settings.Instance.generateProfilingCode) { proj.SetBuildProperty(targetGUID, "GENERATE_PROFILING_CODE", "YES"); } else { proj.SetBuildProperty(targetGUID, "GENERATE_PROFILING_CODE", "NO"); } File.WriteAllText(projPath, proj.WriteToString()); } #endif myCustomProcess.StartInfo.Arguments = string.Format("Assets/" + SA.Common.Config.MODULS_PATH + "IOSDeploy/Scripts/Editor/post_process.py \"{0}\" \"{1}\" \"{2}\" \"{3}\" \"{4}\" \"{5}\"", new object[] { pathToBuiltProject, frameworks, libraries, compileFlags, linkFlags, languageFolders }); myCustomProcess.StartInfo.UseShellExecute = false; myCustomProcess.StartInfo.RedirectStandardOutput = true; myCustomProcess.Start(); myCustomProcess.WaitForExit(); XmlDocument document = new XmlDocument(); string filePath = Path.Combine(pathToBuiltProject, "Info.plist"); document.Load(filePath); document.PreserveWhitespace = true; foreach (Variable var in ISD_Settings.Instance.PlistVariables) { // XmlNode temp = document.SelectSingleNode( "/plist/dict/key[text() = '" + var.Name + "']" ); // if(temp == null) { XmlNode valNode = null; switch (var.Type) { case PlistValueTypes.Array: valNode = document.CreateElement("array"); AddArrayToPlist(var, valNode, document); break; case PlistValueTypes.Boolean: valNode = document.CreateElement(var.BooleanValue.ToString().ToLower()); break; case PlistValueTypes.Dictionary: valNode = document.CreateElement("dict"); AddDictionaryToPlist(var, valNode, document); break; case PlistValueTypes.Float: valNode = document.CreateElement("real"); valNode.InnerText = var.FloatValue.ToString(); break; case PlistValueTypes.Integer: valNode = document.CreateElement("integer"); valNode.InnerText = var.IntegerValue.ToString(); break; case PlistValueTypes.String: valNode = document.CreateElement("string"); valNode.InnerText = var.StringValue; break; } XmlNode keyNode = document.CreateElement("key"); keyNode.InnerText = var.Name; document.DocumentElement.FirstChild.AppendChild(keyNode); document.DocumentElement.FirstChild.AppendChild(valNode); //} } XmlWriterSettings settings = new XmlWriterSettings { Indent = true, IndentChars = "\t", NewLineHandling = NewLineHandling.None }; XmlWriter xmlwriter = XmlWriter.Create(filePath, settings); document.Save(xmlwriter); xmlwriter.Close(); System.IO.StreamReader reader = new System.IO.StreamReader(filePath); string textPlist = reader.ReadToEnd(); reader.Close(); //strip extra indentation (not really necessary) textPlist = (new Regex("^\\t", RegexOptions.Multiline)).Replace(textPlist, ""); //strip whitespace from booleans (not really necessary) textPlist = (new Regex("<(true|false) />", RegexOptions.IgnoreCase)).Replace(textPlist, "<$1/>"); int fixupStart = textPlist.IndexOf("<!DOCTYPE plist PUBLIC"); if (fixupStart >= 0) { int fixupEnd = textPlist.IndexOf('>', fixupStart); if (fixupEnd >= 0) { string fixedPlist = textPlist.Substring(0, fixupStart); fixedPlist += "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"; fixedPlist += textPlist.Substring(fixupEnd + 1); textPlist = fixedPlist; } } System.IO.StreamWriter writer = new System.IO.StreamWriter(filePath, false); writer.Write(textPlist); writer.Close(); UnityEngine.Debug.Log("SA.IOSDeploy.PostProcess Finished."); #endif }
public XCProject(string filePath) : this() { if (!Directory.Exists(filePath)) { Debug.LogWarning("XCode project path does not exist: " + filePath); return; } if (filePath.EndsWith(".xcodeproj")) { // Debug.Log( "Opening project " + filePath ); this.projectRootPath = Path.GetDirectoryName(filePath); this.filePath = filePath; } else { // Debug.Log( "Looking for xcodeproj files in " + filePath ); string[] projects = Directory.GetDirectories(filePath, "*.xcodeproj"); if (projects.Length == 0) { Debug.LogWarning("Error: missing xcodeproj file"); return; } this.projectRootPath = filePath; //if the path is relative to the project, we need to make it absolute if (!Path.IsPathRooted(projectRootPath)) { projectRootPath = Application.dataPath.Replace("Assets", "") + projectRootPath; } // Debug.Log ("projectRootPath adjusted to " + projectRootPath); this.filePath = projects[0]; } projectFileInfo = new FileInfo(Path.Combine(this.filePath, "project.pbxproj")); StreamReader streamReader = projectFileInfo.OpenText(); string contents = streamReader.ReadToEnd(); streamReader.Close(); // Get xcode project xcodeProject = GetXcodeProject(filePath); targetGUID = GetUnityTargetGUID(); PBXParser parser = new PBXParser(); _datastore = parser.Decode(contents); if (_datastore == null) { throw new System.Exception("Project file not found at file path " + filePath); } if (!_datastore.ContainsKey("objects")) { Debug.Log("Error " + _datastore.Count); return; } _objects = (PBXDictionary)_datastore["objects"]; modified = false; _rootObjectKey = (string)_datastore["rootObject"]; if (!string.IsNullOrEmpty(_rootObjectKey)) { _project = new PBXProject(_rootObjectKey, (PBXDictionary)_objects[_rootObjectKey]); _rootGroup = new PBXGroup(_rootObjectKey, (PBXDictionary)_objects[_project.mainGroupID]); PBXNativeTarget _unityNativeTarget = GetUnityNativeTarget(); _targetBuildPhases = (PBXList)_unityNativeTarget.data["buildPhases"]; } else { Debug.LogWarning("error: project has no root object"); _project = null; _rootGroup = null; } }