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