diff --git a/exploded/Assets/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.dll b/exploded/Assets/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.dll index 30030559..42a239ea 100644 Binary files a/exploded/Assets/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.dll and b/exploded/Assets/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.dll differ diff --git a/exploded/Assets/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.pdb b/exploded/Assets/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.pdb index 493d3b28..0a19b23c 100644 Binary files a/exploded/Assets/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.pdb and b/exploded/Assets/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.pdb differ diff --git a/exploded/Assets/ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.186_manifest.txt.meta b/exploded/Assets/ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.186_manifest.txt.meta index a36e708a..57ddd364 100644 --- a/exploded/Assets/ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.186_manifest.txt.meta +++ b/exploded/Assets/ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.186_manifest.txt.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c9a3138961c74d99b7046b783112fceb +guid: a0175a47a1fc48928d528f3a4e3def63 labels: - gvh_version-1.2.186 - gvhp_exportpath-ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.186_manifest.txt diff --git a/external-dependency-manager-1.2.186.unitypackage b/external-dependency-manager-1.2.186.unitypackage index 37e58cd2..7d428112 100644 Binary files a/external-dependency-manager-1.2.186.unitypackage and b/external-dependency-manager-1.2.186.unitypackage differ diff --git a/external-dependency-manager-latest.unitypackage b/external-dependency-manager-latest.unitypackage index 37e58cd2..7d428112 100644 Binary files a/external-dependency-manager-latest.unitypackage and b/external-dependency-manager-latest.unitypackage differ diff --git a/source/IOSResolver/IOSResolver.csproj b/source/IOSResolver/IOSResolver.csproj index e16e2abf..7b0a40d3 100644 --- a/source/IOSResolver/IOSResolver.csproj +++ b/source/IOSResolver/IOSResolver.csproj @@ -50,6 +50,7 @@ + ..\AndroidResolver\bin\Release\Google.JarResolver.dll @@ -68,6 +69,7 @@ + diff --git a/source/IOSResolver/src/IOSResolver.cs b/source/IOSResolver/src/IOSResolver.cs index a272810e..5345bb93 100644 --- a/source/IOSResolver/src/IOSResolver.cs +++ b/source/IOSResolver/src/IOSResolver.cs @@ -405,6 +405,12 @@ protected override bool Read(string filename, Logger logger) { private static SortedDictionary pods = new SortedDictionary(); + // List of pods to ignore because they are replaced by Swift packages. + private static HashSet podsToIgnore = new HashSet(); + // Flag used to denoted if generating the Podfile was skipped because of no pods. + // Used by subsequent steps to know they should be skipped as well. + private static bool podfileGenerationSkipped = false; + // Order of post processing operations. private const int BUILD_ORDER_REFRESH_DEPENDENCIES = 10; private const int BUILD_ORDER_CHECK_COCOAPODS_INSTALL = 20; @@ -510,6 +516,14 @@ protected override bool Read(string filename, Logger logger) { private const string PREFERENCE_PODFILE_ALLOW_PODS_IN_MULTIPLE_TARGETS = PREFERENCE_NAMESPACE + "PodfileAllowPodsInMultipleTargets"; + // Whether to allow empty Podfile generation. + private const string PREFERENCE_ALLOW_EMPTY_PODFILE_GENERATION = + PREFERENCE_NAMESPACE + "AllowEmptyPodfileGeneration"; + + // Whether to use Swift Package Manager for dependency resolution. + private const string PREFERENCE_SWIFT_PACKAGE_MANAGER_ENABLED = + PREFERENCE_NAMESPACE + "SwiftPackageManagerEnabled"; + // List of preference keys, used to restore default settings. private static string[] PREFERENCE_KEYS = new [] { PREFERENCE_COCOAPODS_INSTALL_ENABLED, @@ -525,7 +539,9 @@ protected override bool Read(string filename, Logger logger) { PREFERENCE_SWIFT_FRAMEWORK_SUPPORT_WORKAROUND, PREFERENCE_SWIFT_LANGUAGE_VERSION, PREFERENCE_PODFILE_ALWAYS_ADD_MAIN_TARGET, - PREFERENCE_PODFILE_ALLOW_PODS_IN_MULTIPLE_TARGETS + PREFERENCE_PODFILE_ALLOW_PODS_IN_MULTIPLE_TARGETS, + PREFERENCE_ALLOW_EMPTY_PODFILE_GENERATION, + PREFERENCE_SWIFT_PACKAGE_MANAGER_ENABLED }; // Whether the xcode extension was successfully loaded. @@ -605,6 +621,9 @@ protected override bool Read(string filename, Logger logger) { // Parses dependencies from XML dependency files. private static IOSXmlDependencies xmlDependencies = new IOSXmlDependencies(); + // Parses SPM dependencies from XML dependency files. + private static SwiftPackageManager spmDependencies = new SwiftPackageManager(); + // Project level settings for this module. private static ProjectSettings settings = new ProjectSettings(PREFERENCE_NAMESPACE); @@ -1158,6 +1177,31 @@ public static bool PodfileAllowPodsInMultipleTargets { } } + /// + /// Whether to allow empty Podfile generation. True by default. + /// If true, a Podfile will be generated even if there are no Pods to install. + /// + public static bool AllowEmptyPodfileGeneration { + get { return settings.GetBool(PREFERENCE_ALLOW_EMPTY_PODFILE_GENERATION, + defaultValue: true); } + set { + settings.SetBool(PREFERENCE_ALLOW_EMPTY_PODFILE_GENERATION, value); + } + } + + /// + /// Whether to use Swift Package Manager for dependency resolution. + /// If enabled, the resolver will attempt to use SPM for packages that define SPM support, + /// falling back to Cocoapods if disabled or if the package does not support SPM. + /// + public static bool SwiftPackageManagerEnabled { + get { return settings.GetBool(PREFERENCE_SWIFT_PACKAGE_MANAGER_ENABLED, + defaultValue: true); } + set { + settings.SetBool(PREFERENCE_SWIFT_PACKAGE_MANAGER_ENABLED, value); + } + } + /// /// Whether to use project level settings. @@ -1288,7 +1332,7 @@ public static bool PodPresent(string pod) { private static bool InjectDependencies() { return (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS || EditorUserBuildSettings.activeBuildTarget == BuildTarget.tvOS) && - Enabled && pods.Count > 0; + Enabled && (pods.Count > 0 || spmDependencies.SwiftPackages.Count > 0 || AllowEmptyPodfileGeneration); } /// @@ -2148,6 +2192,17 @@ internal static void AddDummySwiftFile( File.WriteAllText(pbxprojPath, project.WriteToString()); } + [PostProcessBuildAttribute(35)] + public static void OnPostProcessResolveSwiftPackages(BuildTarget buildTarget, + string pathToBuiltProject) { + if (!InjectDependencies() || !SwiftPackageManagerEnabled) { + return; + } + var resolvedPackages = SwiftPackageManager.Resolve(spmDependencies.SwiftPackages, logger); + SwiftPackageManager.AddPackagesToProject(resolvedPackages, pathToBuiltProject, logger); + podsToIgnore = SwiftPackageManager.GetReplacedPods(resolvedPackages); + } + /// /// Post-processing build step to generate the podfile for ios. /// @@ -2155,7 +2210,8 @@ internal static void AddDummySwiftFile( public static void OnPostProcessGenPodfile(BuildTarget buildTarget, string pathToBuiltProject) { if (!InjectDependencies() || !PodfileGenerationEnabled) return; - GenPodfile(buildTarget, pathToBuiltProject); + if (pods.Count == 0 && !AllowEmptyPodfileGeneration) return; + GenPodfile(buildTarget, pathToBuiltProject, podsToIgnore); } /// @@ -2299,7 +2355,8 @@ private static string GeneratePodfileSourcesSection() { // Mono runtime from loading the Xcode API before calling the post // processing step. public static void GenPodfile(BuildTarget buildTarget, - string pathToBuiltProject) { + string pathToBuiltProject, + HashSet podsToIgnore = null) { analytics.Report("generatepodfile", "Generate Podfile"); string podfilePath = GetPodfilePath(pathToBuiltProject); @@ -2316,6 +2373,21 @@ public static void GenPodfile(BuildTarget buildTarget, } } + var filteredPods = new List(); + foreach (var pod in pods.Values) { + if (podsToIgnore != null && podsToIgnore.Contains(pod.name)) { + Log(String.Format("Skipping pod {0} because it is replaced by a Swift Package.", pod.name), verbose: true); + continue; + } + filteredPods.Add(pod); + } + if (filteredPods.Count == 0 && !AllowEmptyPodfileGeneration) { + Log("Found no pods to add, skipping generation of the Podfile"); + podfileGenerationSkipped = true; + return; + } + podfileGenerationSkipped = false; + Log(String.Format("Generating Podfile {0} with {1} integration.", podfilePath, (CocoapodsWorkspaceIntegrationEnabled ? "Xcode workspace" : (CocoapodsProjectIntegrationEnabled ? "Xcode project" : "no target"))), @@ -2340,7 +2412,7 @@ public static void GenPodfile(BuildTarget buildTarget, foreach (var target in XcodeTargetNames) { file.WriteLine(String.Format("target '{0}' do", target)); - foreach(var pod in pods.Values) { + foreach(var pod in filteredPods) { file.WriteLine(String.Format(" {0}", pod.PodFilePodLine)); } file.WriteLine("end"); @@ -2350,7 +2422,7 @@ public static void GenPodfile(BuildTarget buildTarget, file.WriteLine(String.Format("target '{0}' do", XcodeMainTargetName)); bool allowPodsInMultipleTargets = PodfileAllowPodsInMultipleTargets; int podAdded = 0; - foreach(var pod in pods.Values) { + foreach(var pod in filteredPods) { if (pod.addToAllTargets) { file.WriteLine(String.Format(" {0}{1}", allowPodsInMultipleTargets ? "" : "# ", @@ -2377,7 +2449,7 @@ public static void GenPodfile(BuildTarget buildTarget, int maxProperties = 0; int maxSources = Pod.Sources.Count; int fromXmlFileCount = 0; - foreach (var pod in pods.Values) { + foreach (var pod in filteredPods) { maxProperties = Math.Max(maxProperties, pod.propertiesByName.Count); maxSources = Math.Max(maxSources, pod.sources.Count); if (!String.IsNullOrEmpty(pod.version)) versionCount++; @@ -2387,7 +2459,7 @@ public static void GenPodfile(BuildTarget buildTarget, } analytics.Report("generatepodfile/podinfo", new KeyValuePair[] { - new KeyValuePair("numPods", pods.Count.ToString()), + new KeyValuePair("numPods", filteredPods.Count.ToString()), new KeyValuePair("numPodsWithVersions", versionCount.ToString()), new KeyValuePair("numLocalPods", @@ -2736,6 +2808,11 @@ public static void OnPostProcessInstallPods(BuildTarget buildTarget, string pathToBuiltProject) { if (!InjectDependencies() || !PodfileGenerationEnabled) return; + // If the Podfile Generation was skipped because of no pods to install, skip this step. + if (podfileGenerationSkipped) { + return; + } + if(EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS) { UpdateTargetIosSdkVersion(true); } @@ -2842,7 +2919,8 @@ public static void OnPostProcessUpdateProjectDeps( BuildTarget buildTarget, string pathToBuiltProject) { if (!InjectDependencies() || !PodfileGenerationEnabled || !CocoapodsProjectIntegrationEnabled || // Early out for Workspace level integration. - !cocoapodsToolsInstallPresent) { + !cocoapodsToolsInstallPresent || + podfileGenerationSkipped) { return; } @@ -2908,10 +2986,14 @@ private static void RefreshXmlDependencies() { foreach (var podName in podsToRemove) { pods.Remove(podName); } + spmDependencies.SwiftPackages.Clear(); + podsToIgnore.Clear(); + // Clear all sources (only can be set via XML config). Pod.Sources = new List>(); - // Read pod specifications from XML dependencies. + // Read pod and spm specifications from XML dependencies. xmlDependencies.ReadAll(logger); + spmDependencies.ReadAll(logger); } } diff --git a/source/IOSResolver/src/IOSResolverSettingsDialog.cs b/source/IOSResolver/src/IOSResolverSettingsDialog.cs index e8f7001d..756bc29f 100644 --- a/source/IOSResolver/src/IOSResolverSettingsDialog.cs +++ b/source/IOSResolver/src/IOSResolverSettingsDialog.cs @@ -43,6 +43,8 @@ private class Settings { internal string swiftLanguageVersion; internal bool podfileAlwaysAddMainTarget; internal bool podfileAllowPodsInMultipleTargets; + internal bool swiftPackageManagerEnabled; + internal bool allowEmptyPodfileGeneration; internal bool useProjectSettings; internal EditorMeasurement.Settings analyticsSettings; @@ -64,6 +66,8 @@ internal Settings() { swiftLanguageVersion = IOSResolver.SwiftLanguageVersion; podfileAlwaysAddMainTarget = IOSResolver.PodfileAlwaysAddMainTarget; podfileAllowPodsInMultipleTargets = IOSResolver.PodfileAllowPodsInMultipleTargets; + swiftPackageManagerEnabled = IOSResolver.SwiftPackageManagerEnabled; + allowEmptyPodfileGeneration = IOSResolver.AllowEmptyPodfileGeneration; useProjectSettings = IOSResolver.UseProjectSettings; analyticsSettings = new EditorMeasurement.Settings(IOSResolver.analytics); } @@ -86,6 +90,8 @@ internal void Save() { IOSResolver.SwiftLanguageVersion = swiftLanguageVersion; IOSResolver.PodfileAlwaysAddMainTarget = podfileAlwaysAddMainTarget; IOSResolver.PodfileAllowPodsInMultipleTargets = podfileAllowPodsInMultipleTargets; + IOSResolver.SwiftPackageManagerEnabled = swiftPackageManagerEnabled; + IOSResolver.AllowEmptyPodfileGeneration = allowEmptyPodfileGeneration; IOSResolver.UseProjectSettings = useProjectSettings; analyticsSettings.Save(); } @@ -149,6 +155,26 @@ public void OnGUI() { scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); + GUILayout.BeginHorizontal(); + GUILayout.Label("Swift Package Manager Integration", EditorStyles.boldLabel); + settings.swiftPackageManagerEnabled = + EditorGUILayout.Toggle(settings.swiftPackageManagerEnabled); + GUILayout.EndHorizontal(); + GUILayout.Label("Use Swift Package Manager to resolve dependencies that support it. " + + "If this is enabled, the resolver will prioritize SPM packages and " + + "fall back to Cocoapods for any dependencies that do not have an " + + "SPM equivalent specified."); + + GUILayout.BeginHorizontal(); + GUILayout.Label("Allow empty Podfile generation", EditorStyles.boldLabel); + settings.allowEmptyPodfileGeneration = + EditorGUILayout.Toggle(settings.allowEmptyPodfileGeneration); + GUILayout.EndHorizontal(); + GUILayout.Label("If enabled, a Podfile will be generated even if there are no Pods " + + "to install."); + + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); + GUILayout.BeginHorizontal(); GUILayout.Label("Podfile Generation", EditorStyles.boldLabel); settings.podfileGenerationEnabled = @@ -363,6 +389,9 @@ public void OnGUI() { new KeyValuePair( "swiftLanguageVersion", IOSResolver.SwiftLanguageVersion.ToString()), + new KeyValuePair( + "allowEmptyPodfileGeneration", + IOSResolver.AllowEmptyPodfileGeneration.ToString()), }, "Settings Save"); settings.Save(); diff --git a/source/IOSResolver/src/SwiftPackageManager.cs b/source/IOSResolver/src/SwiftPackageManager.cs new file mode 100644 index 00000000..6665feb5 --- /dev/null +++ b/source/IOSResolver/src/SwiftPackageManager.cs @@ -0,0 +1,277 @@ +// +// Copyright (C) 2022 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if UNITY_IOS + +using Google.JarResolver; +using GooglePlayServices; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Xml.Linq; +using UnityEditor; + +namespace Google { + /// + /// Represents a single Swift package framework to be added to the project. + /// This corresponds to the tag. + /// + internal class SwiftPackage { + /// + /// Name of the package framework. (e.g. "FirebaseAnalytics") + /// + public string Name { get; set; } + + /// + /// Whether the framework should be weakly linked. Defaults to false. + /// + public bool Weak { get; set; } + + /// + /// Comma-separated list of Cocoapods that this package replaces. + /// (e.g. "Firebase/Analytics,Firebase/Core") + /// + public string ReplacesPod { get; set; } + + /// + /// A reference back to the remote package this framework belongs to. + /// + public RemoteSwiftPackage RemotePackage { get; set; } + } + + /// + /// Represents a remote Swift package repository. + /// This corresponds to the tag. + /// + internal class RemoteSwiftPackage { + /// + /// The git URL of the package repository. + /// + public string Url { get; set; } + + /// + /// The version string for the package. (e.g. "9.4.0") + /// + public string Version { get; set; } + + /// + /// Whether to use "upToNextMinor" versioning. + /// + public bool UpToNextMinor { get; set; } + + /// + /// Whether to use "upToNextMajor" versioning. + /// + public bool UpToNextMajor { get; set; } + + /// + /// List of the specific package frameworks defined within this remote package. + /// + public List Packages { get; set; } = new List(); + + /// + /// The file path where this package was defined. + /// + public string DefinedIn { get; set; } + } + + /// + /// Parses Swift Package Manager dependencies from *Dependencies.xml files. + /// + internal class SwiftPackageManager : XmlDependencies { + + /// + /// List of packages that have been parsed. + /// + public List SwiftPackages = new List(); + + public SwiftPackageManager() { + dependencyType = "SPM dependencies"; + } + + /// + /// Reads and parses the dependencies from a given XML file. + /// + protected override bool Read(string filename, Logger logger) { + var packages = new List(); + var trueStrings = new HashSet { "true", "1" }; + + try { + XDocument doc = XDocument.Load(filename); + foreach (var remotePackageElement in doc.Descendants("remoteSwiftPackage")) { + var remotePackage = new RemoteSwiftPackage { + Url = (string)remotePackageElement.Attribute("url"), + Version = (string)remotePackageElement.Attribute("version"), + UpToNextMinor = trueStrings.Contains(((string)remotePackageElement.Attribute("upToNextMinor") ?? "").ToLower()), + UpToNextMajor = trueStrings.Contains(((string)remotePackageElement.Attribute("upToNextMajor") ?? "").ToLower()), + DefinedIn = filename + }; + + if (string.IsNullOrEmpty(remotePackage.Url) || string.IsNullOrEmpty(remotePackage.Version)) { + logger.Log(string.Format("Skipping remoteSwiftPackage in {0} due to missing 'url' or 'version' attribute.", filename), level: LogLevel.Warning); + continue; + } + + foreach (var packageElement in remotePackageElement.Elements("swiftPackage")) { + var swiftPackage = new SwiftPackage { + Name = (string)packageElement.Attribute("name"), + Weak = trueStrings.Contains(((string)packageElement.Attribute("weak") ?? "").ToLower()), + ReplacesPod = (string)packageElement.Attribute("replacesPod"), + RemotePackage = remotePackage + }; + + if (string.IsNullOrEmpty(swiftPackage.Name)) { + logger.Log(string.Format("Skipping swiftPackage in {0} due to missing 'name' attribute.", filename), level: LogLevel.Warning); + continue; + } + remotePackage.Packages.Add(swiftPackage); + } + packages.Add(remotePackage); + } + SwiftPackages.AddRange(packages); + } catch (System.Exception e) { + logger.Log(string.Format("Error parsing Swift Package Manager dependencies from {0}: {1}", filename, e.ToString()), level: LogLevel.Error); + return false; + } + return true; + } + + /// + /// Resolves the Swift Package Manager dependencies, handling conflicts. + /// + /// The list of swift packages to resolve. + /// A logger for reporting messages. + /// A list of resolved packages. + internal static List Resolve(List packages, Logger logger) { + var resolvedPackages = new Dictionary(); + + // Resolve remote package version conflicts. Highest version wins. + foreach (var package in packages) { + if (resolvedPackages.TryGetValue(package.Url, out var existingPackage)) { + var existingVersion = new Version(existingPackage.Version); + var newVersion = new Version(package.Version); + + if (newVersion > existingVersion) { + logger.Log(string.Format( + "SPM package version conflict for {0}. Using version {1} from {2} instead of {3} from {4}.", + package.Url, package.Version, package.DefinedIn, existingPackage.Version, existingPackage.DefinedIn), + level: LogLevel.Warning); + package.Packages.AddRange(existingPackage.Packages); + resolvedPackages[package.Url] = package; + } else { + existingPackage.Packages.AddRange(package.Packages); + } + } else { + resolvedPackages[package.Url] = package; + } + } + + // Resolve inner swiftPackage conflicts. + foreach (var remotePackage in resolvedPackages.Values) { + var packageGroups = remotePackage.Packages.GroupBy(p => p.Name) + .ToDictionary(g => g.Key, g => g.ToList()); + + var finalPackages = new List(); + foreach (var group in packageGroups) { + if (group.Value.Count == 1) { + finalPackages.Add(group.Value.First()); + continue; + } + + var mergedPackage = new SwiftPackage { + Name = group.Key, + Weak = group.Value.All(p => p.Weak), + ReplacesPod = string.Join(",", group.Value.Select(p => p.ReplacesPod) + .Where(rp => !string.IsNullOrEmpty(rp)) + .SelectMany(rp => rp.Split(',')) + .Select(p => p.Trim()) + .Distinct().ToArray()), + RemotePackage = remotePackage + }; + finalPackages.Add(mergedPackage); + } + remotePackage.Packages = finalPackages; + } + + return resolvedPackages.Values.ToList(); + } + + /// + /// Extracts the list of Cocoapods that are replaced by the given Swift packages. + /// + /// A list of resolved Swift packages. + /// A unique list of pod names to be removed. + internal static HashSet GetReplacedPods(List resolvedPackages) { + var replacedPods = new HashSet(); + foreach (var package in resolvedPackages) { + foreach (var swiftPackage in package.Packages) { + if (!string.IsNullOrEmpty(swiftPackage.ReplacesPod)) { + foreach (var pod in swiftPackage.ReplacesPod.Split(',')) { + replacedPods.Add(pod.Trim()); + } + } + } + } + return replacedPods; + } + + /// + /// Modifies the Xcode project to add the Swift Package dependencies. + /// + /// The list of resolved packages to add. + /// The path to the Xcode project. + /// A logger for reporting messages. + internal static void AddPackagesToProject(List resolvedPackages, string projectPath, Logger logger) { + if (VersionHandler.GetUnityVersionMajorMinor() < 2021.3f) { + logger.Log("Swift Package Manager integration is only supported in Unity 2021.3 and newer. Disabling.", level: LogLevel.Warning); + return; + } + + string pbxProjectPath = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(projectPath); + var project = new UnityEditor.iOS.Xcode.PBXProject(); + project.ReadFromFile(pbxProjectPath); + + string frameworkTargetGuid = project.GetUnityFrameworkTargetGuid(); + + foreach (var remotePackage in resolvedPackages) { + try { + string methodName; + if (remotePackage.UpToNextMajor) { + methodName = "AddRemotePackageReferenceAtVersionUpToNextMajor"; + } else if (remotePackage.UpToNextMinor) { + methodName = "AddRemotePackageReferenceAtVersionUpToNextMinor"; + } else { + methodName = "AddRemotePackageReferenceAtVersion"; + } + + var packageGuid = VersionHandler.InvokeInstanceMethod(project, methodName, new object[] { remotePackage.Url, remotePackage.Version }); + logger.Log(string.Format("Added SPM package {0} version {1} to project.", remotePackage.Url, remotePackage.Version), level: LogLevel.Info); + + foreach (var swiftPackage in remotePackage.Packages) { + VersionHandler.InvokeInstanceMethod(project, "AddRemotePackageFrameworkToProject", new object[] { frameworkTargetGuid, swiftPackage.Name, packageGuid, swiftPackage.Weak }); + logger.Log(string.Format(" - Added framework {0} to project.", swiftPackage.Name), level: LogLevel.Info); + } + } catch (Exception e) { + logger.Log(string.Format("Failed to add Swift Package {0}. Error: {1}", remotePackage.Url, e.Message), level: LogLevel.Error); + } + } + + project.WriteToFile(pbxProjectPath); + } + } +} +#endif // UNITY_IOS diff --git a/upm/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.dll b/upm/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.dll index 30030559..42a239ea 100755 Binary files a/upm/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.dll and b/upm/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.dll differ diff --git a/upm/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.pdb b/upm/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.pdb index 493d3b28..0a19b23c 100755 Binary files a/upm/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.pdb and b/upm/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.pdb differ diff --git a/upm/ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.186_manifest.txt.meta b/upm/ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.186_manifest.txt.meta index dca3f95f..a298af77 100644 --- a/upm/ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.186_manifest.txt.meta +++ b/upm/ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.186_manifest.txt.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c9a3138961c74d99b7046b783112fceb +guid: a0175a47a1fc48928d528f3a4e3def63 labels: - gvh - gvh_manifest