diff --git a/source/IOSResolver/src/IOSResolver.cs b/source/IOSResolver/src/IOSResolver.cs index 336cd168..1ae1fa7d 100644 --- a/source/IOSResolver/src/IOSResolver.cs +++ b/source/IOSResolver/src/IOSResolver.cs @@ -480,6 +480,13 @@ protected override bool Read(string filename, Logger logger) { // Whether to statically link framework in the Podfile. private const string PREFERENCE_PODFILE_STATIC_LINK_FRAMEWORKS = PREFERENCE_NAMESPACE + "PodfileStaticLinkFrameworks"; + // Whether to add Dummy.swift to the generated Xcode project as a workaround to support pods + // with Swift Framework. + private const string PREFERENCE_SWIFT_FRAMEWORK_SUPPORT_WORKAROUND = + PREFERENCE_NAMESPACE + "SwiftFrameworkSupportWorkaroundEnabled"; + // The Swift Language Version (SWIFT_VERSION) to update to the generated Xcode Project. + private const string PREFERENCE_SWIFT_LANGUAGE_VERSION = + PREFERENCE_NAMESPACE + "SwiftLanguageVersion"; // Whether to add an main target to Podfile for Unity 2019.3+. private const string PREFERENCE_PODFILE_ALWAYS_ADD_MAIN_TARGET = PREFERENCE_NAMESPACE + "PodfileAlwaysAddMainTarget"; @@ -499,6 +506,8 @@ protected override bool Read(string filename, Logger logger) { PREFERENCE_SKIP_POD_INSTALL_WHEN_USING_WORKSPACE_INTEGRATION, PREFERENCE_PODFILE_ADD_USE_FRAMEWORKS, PREFERENCE_PODFILE_STATIC_LINK_FRAMEWORKS, + PREFERENCE_SWIFT_FRAMEWORK_SUPPORT_WORKAROUND, + PREFERENCE_SWIFT_LANGUAGE_VERSION, PREFERENCE_PODFILE_ALWAYS_ADD_MAIN_TARGET, PREFERENCE_PODFILE_ALLOW_PODS_IN_MULTIPLE_TARGETS }; @@ -1032,12 +1041,40 @@ public static bool PodfileAddUseFrameworks { /// public static bool PodfileStaticLinkFrameworks { get { return settings.GetBool(PREFERENCE_PODFILE_STATIC_LINK_FRAMEWORKS, - defaultValue: false); } + defaultValue: true); } set { settings.SetBool(PREFERENCE_PODFILE_STATIC_LINK_FRAMEWORKS, value); } } + /// + /// Whether to enable Swift Framework support workaround. + /// If enabled, iOS Resolver adds a Dummy.swift to the generated Xcode project, and change build + // properties in order to properly include Swift Standard Libraries. + /// + public static bool SwiftFrameworkSupportWorkaroundEnabled { + get { return settings.GetBool(PREFERENCE_SWIFT_FRAMEWORK_SUPPORT_WORKAROUND, + defaultValue: false); } + set { + settings.SetBool(PREFERENCE_SWIFT_FRAMEWORK_SUPPORT_WORKAROUND, value); + } + } + + /// + /// The value used to set Xcode build property: Swift Language Version (SWIFT_VERSION). + /// It is default to "5" but Xcode may add or remove options over time. + /// If blank, iOS Resolver will not override the build property. + /// Please check the build property "Swift Language Version" options in Xcode project first + /// before changing this value. + /// + public static string SwiftLanguageVersion { + get { return settings.GetString(PREFERENCE_SWIFT_LANGUAGE_VERSION, + defaultValue: "5.0"); } + set { + settings.SetString(PREFERENCE_SWIFT_LANGUAGE_VERSION, value); + } + } + /// /// Whether to add the main target to Podfile for Unity 2019.3+. True by default. /// If true, iOS Resolver will add the following lines to Podfile, on top of 'UnityFramework' @@ -1838,6 +1875,21 @@ public static void OnPostProcessPatchProject(BuildTarget buildTarget, PatchProject(buildTarget, pathToBuiltProject); } + /// + /// Post-processing build step to add dummy swift file + /// + [PostProcessBuildAttribute(BUILD_ORDER_PATCH_PROJECT)] + public static void OnPostProcessAddDummySwiftFile(BuildTarget buildTarget, + string pathToBuiltProject) { + if (!InjectDependencies() || + !PodfileGenerationEnabled || + !PodfileAddUseFrameworks || + !SwiftFrameworkSupportWorkaroundEnabled) { + return; + } + AddDummySwiftFile(buildTarget, pathToBuiltProject); + } + /// /// Get Xcode target names using a method that works across all Unity versions. /// @@ -1935,6 +1987,42 @@ internal static void PatchProject( File.WriteAllText(pbxprojPath, project.WriteToString()); } + internal static void AddDummySwiftFile( + BuildTarget buildTarget, string pathToBuiltProject) { + string pbxprojPath = GetProjectPath(pathToBuiltProject); + var project = new UnityEditor.iOS.Xcode.PBXProject(); + project.ReadFromString(File.ReadAllText(pbxprojPath)); + + string DUMMY_SWIFT_FILE_NAME = "Dummy.swift"; + string DUMMY_SWIFT_FILE_CONTENT = + "// Generated by External Dependency Manager for Unity\n" + + "import Foundation"; + string dummySwiftPath = Path.Combine(pathToBuiltProject, DUMMY_SWIFT_FILE_NAME); + if (!File.Exists(dummySwiftPath)) { + File.WriteAllText(dummySwiftPath, DUMMY_SWIFT_FILE_CONTENT); + } + + foreach (var target in GetXcodeTargetGuids(project, includeAllTargets: false)) { + project.AddFileToBuild( + target, + project.AddFile(DUMMY_SWIFT_FILE_NAME, + DUMMY_SWIFT_FILE_NAME, + UnityEditor.iOS.Xcode.PBXSourceTree.Source)); + if(!string.IsNullOrEmpty(SwiftLanguageVersion)) { + project.SetBuildProperty(target, "SWIFT_VERSION", SwiftLanguageVersion); + } + + // These build properties are only required for multi-target Xcode project, which is + // generated from 2019.3+. + if(MultipleXcodeTargetsSupported) { + project.SetBuildProperty(target, "CLANG_ENABLE_MODULES", "YES"); + project.SetBuildProperty(target, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES"); + } + } + + File.WriteAllText(pbxprojPath, project.WriteToString()); + } + /// /// Post-processing build step to generate the podfile for ios. /// @@ -1942,6 +2030,7 @@ internal static void PatchProject( public static void OnPostProcessGenPodfile(BuildTarget buildTarget, string pathToBuiltProject) { if (!InjectDependencies() || !PodfileGenerationEnabled) return; + Log("OnPostProcessGenPodfile!", level: LogLevel.Error); GenPodfile(buildTarget, pathToBuiltProject); } diff --git a/source/IOSResolver/src/IOSResolverSettingsDialog.cs b/source/IOSResolver/src/IOSResolverSettingsDialog.cs index 0a705f15..bfcb7932 100644 --- a/source/IOSResolver/src/IOSResolverSettingsDialog.cs +++ b/source/IOSResolver/src/IOSResolverSettingsDialog.cs @@ -39,6 +39,8 @@ private class Settings { internal int cocoapodsIntegrationMenuIndex; internal bool podfileAddUseFrameworks; internal bool podfileStaticLinkFrameworks; + internal bool swiftFrameworkSupportWorkaroundEnabled; + internal string swiftLanguageVersion; internal bool podfileAlwaysAddMainTarget; internal bool podfileAllowPodsInMultipleTargets; internal bool useProjectSettings; @@ -57,6 +59,9 @@ internal Settings() { IOSResolver.CocoapodsIntegrationMethodPref); podfileAddUseFrameworks = IOSResolver.PodfileAddUseFrameworks; podfileStaticLinkFrameworks = IOSResolver.PodfileStaticLinkFrameworks; + swiftFrameworkSupportWorkaroundEnabled = + IOSResolver.SwiftFrameworkSupportWorkaroundEnabled; + swiftLanguageVersion = IOSResolver.SwiftLanguageVersion; podfileAlwaysAddMainTarget = IOSResolver.PodfileAlwaysAddMainTarget; podfileAllowPodsInMultipleTargets = IOSResolver.PodfileAllowPodsInMultipleTargets; useProjectSettings = IOSResolver.UseProjectSettings; @@ -76,6 +81,9 @@ internal void Save() { integrationMapping[cocoapodsIntegrationMenuIndex]; IOSResolver.PodfileAddUseFrameworks = podfileAddUseFrameworks; IOSResolver.PodfileStaticLinkFrameworks = podfileStaticLinkFrameworks; + IOSResolver.SwiftFrameworkSupportWorkaroundEnabled = + swiftFrameworkSupportWorkaroundEnabled; + IOSResolver.SwiftLanguageVersion = swiftLanguageVersion; IOSResolver.PodfileAlwaysAddMainTarget = podfileAlwaysAddMainTarget; IOSResolver.PodfileAllowPodsInMultipleTargets = podfileAllowPodsInMultipleTargets; IOSResolver.UseProjectSettings = useProjectSettings; @@ -99,6 +107,8 @@ internal void Save() { IOSResolver.CocoapodsIntegrationMethod.None, }; + private Vector2 scrollPosition = new Vector2(0, 0); + // enum to index (linear search because there's no point in creating a reverse mapping // with such a small list). private static int FindIndexFromCocoapodsIntegrationMethod( @@ -137,6 +147,8 @@ public void OnGUI() { IOSResolverVersionNumber.Value.Minor, IOSResolverVersionNumber.Value.Build)); + scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); + GUILayout.BeginHorizontal(); GUILayout.Label("Podfile Generation", EditorStyles.boldLabel); settings.podfileGenerationEnabled = @@ -222,6 +234,8 @@ public void OnGUI() { settings.podfileStaticLinkFrameworks = EditorGUILayout.Toggle(settings.podfileStaticLinkFrameworks); GUILayout.EndHorizontal(); + GUILayout.Label("Link frameworks statically is recommended just in case any pod " + + "framework includes static libraries."); } if (IOSResolver.MultipleXcodeTargetsSupported) { @@ -248,6 +262,33 @@ public void OnGUI() { } } + if (settings.podfileAddUseFrameworks) { + GUILayout.BeginHorizontal(); + GUILayout.Label("Enable Swift Framework Support Workaround", + EditorStyles.boldLabel); + settings.swiftFrameworkSupportWorkaroundEnabled = + EditorGUILayout.Toggle(settings.swiftFrameworkSupportWorkaroundEnabled); + GUILayout.EndHorizontal(); + GUILayout.Label("This workround patches the Xcode project to properly link Swift " + + "Standard Library when some plugins depend on Swift Framework " + + "pods by:"); + GUILayout.Label("1. Add a dummy Swift file to Xcode project."); + GUILayout.Label("2. Enable 'CLANG_ENABLE_MODULES' and " + + "'ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES' build settings and set " + + "'SWIFT_VERSION' to the value below."); + + if (settings.swiftFrameworkSupportWorkaroundEnabled) { + GUILayout.BeginHorizontal(); + GUILayout.Label("Swift Framework Version", + EditorStyles.boldLabel); + settings.swiftLanguageVersion = + EditorGUILayout.TextField(settings.swiftLanguageVersion); + GUILayout.EndHorizontal(); + GUILayout.Label("Used to override 'SWIFT_VERSION' build setting in Xcode. " + + "Leave it blank to prevent override."); + } + } + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); } @@ -263,8 +304,11 @@ public void OnGUI() { settings.useProjectSettings = EditorGUILayout.Toggle(settings.useProjectSettings); GUILayout.EndHorizontal(); - GUILayout.Space(10); + EditorGUILayout.EndScrollView(); + GUILayout.EndVertical(); + GUILayout.BeginVertical(); + GUILayout.Space(10); if (GUILayout.Button("Reset to Defaults")) { // Load default settings into the dialog but preserve the state in the user's // saved preferences. @@ -314,6 +358,12 @@ public void OnGUI() { new KeyValuePair( "podfileAllowPodsInMultipleTargets", IOSResolver.PodfileAllowPodsInMultipleTargets.ToString()), + new KeyValuePair( + "swiftFrameworkSupportWorkaroundEnabled", + IOSResolver.SwiftFrameworkSupportWorkaroundEnabled.ToString()), + new KeyValuePair( + "swiftLanguageVersion", + IOSResolver.SwiftLanguageVersion.ToString()), }, "Settings Save"); settings.Save();