| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 | //-----------------------------------------------------------------------------// Copyright 2012-2024 RenderHeads Ltd.  All rights reserved.//-----------------------------------------------------------------------------#if (UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS) && UNITY_2017_1_OR_NEWER// Unity versions where xcframework support was added// 2023.2.18f1// 2022.3.23f1// 2021.3.37f1// There has to be a better way...#if UNITY_2023_2_OR_NEWER && !(UNITY_2023_2_0 || UNITY_2023_2_1 || UNITY_2023_2_2 || UNITY_2023_2_3 || UNITY_2023_2_4 || UNITY_2023_2_5 || UNITY_2023_2_6 || UNITY_2023_2_7 || UNITY_2023_2_8 || UNITY_2023_2_9 || UNITY_2023_2_10 || UNITY_2023_2_11 || UNITY_2023_2_12 || UNITY_2023_2_13 || UNITY_2023_2_14 || UNITY_2023_2_15 || UNITY_2023_2_16 || UNITY_2023_2_17)#define AVPROVIDEO_UNITY_SUPPORTS_XCFRAMEWORKS#elif UNITY_2023_1_OR_NEWER#define AVPROVIDEO_UNITY_DOES_NOT_SUPPORT_XCFRAMEWORKS#elif UNITY_2022_3_OR_NEWER && !(UNITY_2022_3_0 || UNITY_2022_3_1 || UNITY_2022_3_2 || UNITY_2022_3_3 || UNITY_2022_3_4 || UNITY_2022_3_5 || UNITY_2022_3_6 || UNITY_2022_3_7 || UNITY_2022_3_8 || UNITY_2022_3_9 || UNITY_2022_3_10 || UNITY_2022_3_11 || UNITY_2022_3_12 || UNITY_2022_3_13 || UNITY_2022_3_14 || UNITY_2022_3_15 || UNITY_2022_3_16 || UNITY_2022_3_17 || UNITY_2022_3_18 || UNITY_2022_3_19 || UNITY_2022_3_20 || UNITY_2022_3_21 || UNITY_2022_3_22)#define AVPROVIDEO_UNITY_SUPPORTS_XCFRAMEWORKS#elif UNITY_2022_1_OR_NEWER#define AVPROVIDEO_UNITY_DOES_NOT_SUPPORT_XCFRAMEWORKS#elif UNITY_2021_3_OR_NEWER && !(UNITY_2021_3_0 || UNITY_2021_3_1 || UNITY_2021_3_2 || UNITY_2021_3_3 || UNITY_2021_3_4 || UNITY_2021_3_5 || UNITY_2021_3_6 || UNITY_2021_3_7 || UNITY_2021_3_8 || UNITY_2021_3_9 || UNITY_2021_3_10 || UNITY_2021_3_11 || UNITY_2021_3_12 || UNITY_2021_3_13 || UNITY_2021_3_14 || UNITY_2021_3_15 || UNITY_2021_3_16 || UNITY_2021_3_17 || UNITY_2021_3_18 || UNITY_2021_3_19 || UNITY_2021_3_20 || UNITY_2021_3_21 || UNITY_2021_3_22 || UNITY_2021_3_23 || UNITY_2021_3_24 || UNITY_2021_3_25 || UNITY_2021_3_26 || UNITY_2021_3_27 || UNITY_2021_3_28 || UNITY_2021_3_29 || UNITY_2021_3_30 || UNITY_2021_3_31 || UNITY_2021_3_32 || UNITY_2021_3_33 || UNITY_2021_3_34 || UNITY_2021_3_35 || UNITY_2021_3_36)#define AVPROVIDEO_UNITY_SUPPORTS_XCFRAMEWORKS#else#define AVPROVIDEO_UNITY_DOES_NOT_SUPPORT_XCFRAMEWORKS#endifusing UnityEngine;using UnityEditor;using UnityEditor.Callbacks;using UnityEditor.iOS.Xcode;using System;using System.Collections.Generic;using System.IO;namespace RenderHeads.Media.AVProVideo.Editor{	public class PostProcessBuild_iOS	{		const string AVProVideoPluginName = "AVProVideo.xcframework";		const string AVProVideoBootstrap = "extern void AVPPluginUnityRegisterRenderingPlugin(void*);\nvoid AVPPluginBootstrap(void) {\n\tAVPPluginUnityRegisterRenderingPlugin(UnityRegisterRenderingPluginV5);\n}\n";		const string AVProVideoForceSwift = "import Foundation\n";		private class Platform		{			public BuildTarget target { get; }			public string name { get; }			public string guid { get; }			public static Platform GetPlatformForTarget(BuildTarget target)			{				switch (target)				{					case BuildTarget.iOS:						return new Platform(BuildTarget.iOS, "iOS", "a7ee58e0e533849d3a37458bc7df6df7");					case BuildTarget.tvOS:						return new Platform(BuildTarget.tvOS, "tvOS", "f83f62879d8fb417cb18d0547c9bfd02");#if UNITY_2022_3					case BuildTarget.VisionOS:						return new Platform(BuildTarget.VisionOS, "visionOS", "fe151797423674af0941aae11c872b90");#endif					default:						return null;				}			}			private Platform(BuildTarget target, string name, string guid)			{				this.target = target;				this.name = name;				this.guid = guid;			}		}		/// <summary>		/// Get the plugin path for the platform specified		/// </summary>		/// <param name="platform">The platform</param>		/// <param name="pluginName">The plugin's file name</param>		/// <returns>The path of the plugin within Unity's assets folder</returns>		private static string PluginPathForPlatform(Platform platform, string pluginName)		{			// See if we can find the plugin by GUID			string pluginPath = AssetDatabase.GUIDToAssetPath(platform.guid);			// If not, try and find it by name			if (pluginPath.Length == 0)			{				Debug.LogWarningFormat("[AVProVideo] Failed to find plugin by GUID, will attempt to find it by name.");				string[] guids = AssetDatabase.FindAssets(pluginName);				if (guids != null && guids.Length > 0)				{					foreach (string guid in guids)					{						string assetPath = AssetDatabase.GUIDToAssetPath(guid);						if (assetPath.Contains(platform.name))						{							pluginPath = assetPath;							break;						}					}				}			}			if (pluginPath.Length > 0)			{				Debug.LogFormat("[AVProVideo] Found plugin at '{0}'", pluginPath);			}			return pluginPath;		}		/// <summary>		/// Gets the target guid if Unity's framework target from the project provided		/// </summary>		/// <param name="project">The project to get the guid from</param>		/// <returns></returns>		private static string GetUnityFrameworkTargetGuid(PBXProject project)		{			return project.GetUnityFrameworkTargetGuid();		}		/// <summary>		/// Copies a directory.		/// </summary>		/// <remarks>		/// Intended for use outside of Unity's project structure, this will skip meta files when copying.		/// </remarks>		/// <param name="src">The directory info of the directory to copy</param>		/// <param name="dst">The directory info of the destination directory</param>		private static void CopyDirectory(DirectoryInfo srcDirInfo, DirectoryInfo dstDirInfo)		{			// Make sure the target directory exists			Directory.CreateDirectory(dstDirInfo.FullName);			// Copy over the sub-directories			foreach (DirectoryInfo subSrcDirInfo in srcDirInfo.GetDirectories())			{				DirectoryInfo subDstDirInfo = dstDirInfo.CreateSubdirectory(subSrcDirInfo.Name);				CopyDirectory(subSrcDirInfo, subDstDirInfo);			}			// Copy over the files			foreach (FileInfo srcFileInfo in srcDirInfo.GetFiles())			{				if (srcFileInfo.Extension == ".meta")				{					// Do not want to copy Unity's meta files into the built project					continue;				}				else				if (srcFileInfo.Name == ".DS_Store")				{					// Do not want to copy .DS_Store files into the built project					continue;				}				else				{					srcFileInfo.CopyTo(Path.Combine(dstDirInfo.FullName, srcFileInfo.Name), true);				}			}		}		/// <summary>		/// Copies a directory.		/// </summary>		/// <remarks>		/// Intended for use outside of Unity's project structure, this will skip meta files when copying.		/// </remarks>		/// <param name="src">The path of the directory to copy</param>		/// <param name="dst">The path where the directory will be copied to</param>		private static void CopyDirectory(string src, string dst)		{			CopyDirectory(new DirectoryInfo(src), new DirectoryInfo(dst));		}		/// <summary>		/// Tests the target build platform to see if it's supported by this script		/// </summary>		/// <param name="target">The target build platform</param>		/// <returns>true if the build target is supported, false otherwise</returns>		private static bool IsBuildTargetSupported(BuildTarget target)		{			switch (target)			{				case BuildTarget.iOS:				case BuildTarget.tvOS:#if UNITY_2022_3				case BuildTarget.VisionOS:#endif					return true;				default:					return false;			}		}		/// <summary>		/// Gets the Xcode project name for the target specified.		/// </summary>		/// <param name="target">The build target</param>		/// <returns>The Xcode project name</returns>		private static string GetXcodeProjectNameForBuildTarget(BuildTarget target)		{			switch (target)			{				case BuildTarget.iOS:				case BuildTarget.tvOS:					return "Unity-iPhone.xcodeproj";#if UNITY_2022_3				case BuildTarget.VisionOS:					return "Unity-VisionOS.xcodeproj";#endif				default:					Debug.LogError($"[AVProVideo] GetXcodeProjectNameForBuildTarget - unrecognised build target: {target}");					return null;			}		}		// Converts the Unity asset path to the expected path in the built Xcode project.		private static string ConvertPluginAssetPathToXcodeProjectPath(string pluginPath, string subFolder)		{			List<string> components = new List<string>(pluginPath.Split(new char[] { '/' }));#if UNITY_TVOS			// Unity just copies the xcframework into the frameworks folder			string frameworkPath = Path.Combine(subFolder, components[^1]);#else	#if UNITY_VISIONOS			// For reasons unknown unity puts everything under an ARM64 folder on visionOS			components.Insert(0, "ARM64");			components.Insert(0, subFolder);	#else			components[0] = subFolder;	#endif	#if UNITY_2019_1_OR_NEWER				string frameworkPath = string.Join("/", components);	#else				string frameworkPath = string.Join("/", components.ToArray());	#endif#endif			return frameworkPath;		}		//		private static void StripMetaFilesFromDirectory(DirectoryInfo dirInfo)		{			// Remove any meta files			foreach (FileInfo srcFileInfo in dirInfo.GetFiles())			{				if (srcFileInfo.Extension == ".meta")				{					Debug.Log($"[AVProVideo] Deleting {srcFileInfo.FullName}");					File.Delete(srcFileInfo.FullName);				}				else				if (srcFileInfo.Name == ".DS_Store")				{					Debug.Log($"[AVProVideo] Deleting {srcFileInfo.FullName}");					File.Delete(srcFileInfo.FullName);				}			}			// Do the same for any sub-directories			foreach (DirectoryInfo subDirInfo in dirInfo.GetDirectories("*"))			{				StripMetaFilesFromDirectory(subDirInfo);			}		}		/// <summary>		/// Post-process the generated Xcode project to add the plugin and any build configuration required.		/// </summary>		/// <param name="target">The target build platform</param>		/// <param name="path">The path to the built project</param>		[PostProcessBuild]		public static void ModifyProject(BuildTarget target, string path)		{			if (!IsBuildTargetSupported(target))			{				// Nothing to be done				return;			}			Debug.Log("[AVProVideo] Post-processing generated Xcode project...");			Platform platform = Platform.GetPlatformForTarget(target);			if (platform == null)			{				Debug.LogWarningFormat("[AVProVideo] Unknown build target: {0}, stopping", target);				return;			}			// Create the path to the generated Xcode project file			string xcodeProjectName = GetXcodeProjectNameForBuildTarget(target);			if (xcodeProjectName == null)			{				return;			}			string xcodeProjectPath = Path.Combine(path, xcodeProjectName, "project.pbxproj");			Debug.Log($"[AVProVideo] Opening Xcode project at: {path}");			// Open the project			PBXProject project = new PBXProject();			project.ReadFromFile(xcodeProjectPath);			// Attempt to find the plugin path			string pluginPath = PluginPathForPlatform(platform, AVProVideoPluginName);			if (pluginPath.Length == 0)			{				Debug.LogErrorFormat("[AVProVideo] Failed to find '{0}' for '{1}' in the Unity project. Something is horribly wrong, please reinstall AVPro Video.", AVProVideoPluginName, platform);				return;			}			Debug.Log($"[AVProVideo] Plugin path: {pluginPath}");			string destPluginPath = Path.Combine("Libraries", "AVProVideo");			Directory.CreateDirectory(Path.Combine(path, destPluginPath));			// Get the Unity framework target GUID			string unityFrameworkTargetGuid = GetUnityFrameworkTargetGuid(project);#if AVPROVIDEO_UNITY_DOES_NOT_SUPPORT_XCFRAMEWORKS			// Get the path to the xcframework			string xcframeworkPath = Path.Combine(destPluginPath, AVProVideoPluginName);			// Copy over the xcframework to the generated xcode project			Debug.Log($"[AVProVideo] Copying AVProVideo.xcframework into the Xcode project at {destPluginPath}");			CopyDirectory(pluginPath, Path.Combine(path, xcframeworkPath));			if (!project.ContainsFileByProjectPath(xcframeworkPath))			{				Debug.Log("[AVProVideo] Adding AVProVideo.xcframework to the UnityFramework target");				// Add the xcframework and sundry files to the project				string xcframeworkGuid = project.AddFile(xcframeworkPath, xcframeworkPath);				// Get the frameworks build phase and add the xcframework to it				string frameworksBuildPhaseForUnityFrameworkTarget = project.GetFrameworksBuildPhaseByTarget(unityFrameworkTargetGuid);				project.AddFileToBuildSection(unityFrameworkTargetGuid, frameworksBuildPhaseForUnityFrameworkTarget, xcframeworkGuid);			}#else			// If we've upgraded Unity to a version that supports xcframeworks we need to purge the meta files from the plugin			// string xcframeworkPath = ConvertPluginAssetPathToXcodeProjectPath(pluginPath, "Frameworks");			string xcframeworkPath = string.Empty;			IReadOnlyList<string> paths = project.GetRealPathsOfAllFiles(PBXSourceTree.Source);			foreach (string p in paths)			{				if (p.EndsWith(AVProVideoPluginName))				{					xcframeworkPath = p;					break;				}			}			if (!string.IsNullOrEmpty(xcframeworkPath))			{				string dest_xcframeworkPath = Path.Combine(path, xcframeworkPath);				Debug.Log($"[AVProVideo] xcframework path is: {dest_xcframeworkPath}");				StripMetaFilesFromDirectory(new DirectoryInfo(dest_xcframeworkPath));			}			// string dest_xcframeworkPath = Path.Combine(path, xcframeworkPath);			// if (!project.ContainsFileByProjectPath(xcframeworkPath))			// {			// 	Debug.Log("[AVProVideo] Stripping meta files from AVProVideo.xcframework");			// 	StripMetaFilesFromDirectory(new DirectoryInfo(dest_xcframeworkPath));			// }			else			{				Debug.LogError($"[AVProVideo] Failed to find AVProPlugin.xcframework in the built project");			}#endif			Debug.Log("[AVProVideo] Writing AVProVideoBootstrap.m to the UnityFramework target");			string bootstrapPath = Path.Combine(destPluginPath, "AVProVideoBootstrap.m");			File.WriteAllText(Path.Combine(path, bootstrapPath), AVProVideoBootstrap);			string bootstrapGuid = project.AddFile(bootstrapPath, bootstrapPath);			project.AddFileToBuild(unityFrameworkTargetGuid, bootstrapGuid);			string forceSwiftPath = Path.Combine(destPluginPath, "AVProVideoForceSwift.swift");			Debug.Log("[AVProVideo] Writing AVProVideoForceSwift.swift to the UnityFramework target");			File.WriteAllText(Path.Combine(path, forceSwiftPath), AVProVideoForceSwift);			string forceSwiftGuid = project.AddFile(forceSwiftPath, forceSwiftPath);			project.AddFileToBuild(unityFrameworkTargetGuid, forceSwiftGuid);			// Make sure the swift version is set to 5.0			string swiftVersionStr = project.GetBuildPropertyForAnyConfig(unityFrameworkTargetGuid, "SWIFT_VERSION");			decimal swiftVersion;			if (!Decimal.TryParse(swiftVersionStr, out swiftVersion) || (swiftVersion < 5))			{				Debug.Log("[AVProVideo] setting SWIFT_VERSION to 5.0 for the UnityFramework target");				project.SetBuildProperty(unityFrameworkTargetGuid, "SWIFT_VERSION", "5.0");			}			// Done			project.WriteToFile(xcodeProjectPath);			Debug.Log("[AVProVideo] Finished modifying Xcode project");		}	}}#endif
 |