From 5389bb4274f80b69e45aceffbdf3ffdb1e79908f Mon Sep 17 00:00:00 2001
From: Craig Scott <craig.scott@crascit.com>
Date: Wed, 3 Feb 2021 23:03:00 +1100
Subject: Xcode: Don't hard-code SDK-provided implicit framework search paths

When a framework is linked to a target by its full path and that
framework is located in one of the implicit framework search directories,
CMake 3.18.5 and earlier discarded that path.
ce2dee9e5ba (Xcode: Don't add framework as -framework argument in
linker info list, 2020-09-28) introduced a regression which resulted in
the framework path always being added to the search path even if it
matched one of the implicit search paths. This broke the ability to do
device and simulator builds from the same configured project.

Fixes: #21678
---
 Source/cmComputeLinkInformation.cxx |  6 ++++++
 Source/cmComputeLinkInformation.h   |  1 +
 Source/cmGlobalXCodeGenerator.cxx   | 15 ++++++++++++++-
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index d1680ad..b9f15b7 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -474,6 +474,12 @@ std::vector<std::string> const& cmComputeLinkInformation::GetFrameworkPaths()
   return this->FrameworkPaths;
 }
 
+std::set<std::string> const&
+cmComputeLinkInformation::GetFrameworkPathsEmitted() const
+{
+  return this->FrameworkPathsEmitted;
+}
+
 const std::set<const cmGeneratorTarget*>&
 cmComputeLinkInformation::GetSharedLibrariesLinked() const
 {
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index d8ec563..9fec702 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -55,6 +55,7 @@ public:
   std::vector<BT<std::string>> GetDirectoriesWithBacktraces();
   std::vector<std::string> const& GetDepends() const;
   std::vector<std::string> const& GetFrameworkPaths() const;
+  std::set<std::string> const& GetFrameworkPathsEmitted() const;
   std::string GetLinkLanguage() const { return this->LinkLanguage; }
   std::vector<std::string> const& GetRuntimeSearchPath() const;
   std::string const& GetRuntimeFlag() const { return this->RuntimeFlag; }
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index df45b35..51a7915 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -3620,6 +3620,15 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
 
     // now add the left-over link libraries
     {
+      // Keep track of framework search paths we've already added or that are
+      // part of the set of implicit search paths. We don't want to repeat
+      // them and we also need to avoid hard-coding any SDK-specific paths.
+      // This is essential for getting device-and-simulator builds to work,
+      // otherwise we end up hard-coding a path to the wrong SDK for
+      // SDK-provided frameworks that are added by their full path.
+      std::set<std::string> emitted(cli->GetFrameworkPathsEmitted());
+      const auto& fwPaths = cli->GetFrameworkPaths();
+      emitted.insert(fwPaths.begin(), fwPaths.end());
       BuildObjectListOrString libPaths(this, true);
       for (auto const& libItem : configItemMap[configName]) {
         auto const& libName = *libItem;
@@ -3633,7 +3642,11 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
             const auto fwName =
               cmSystemTools::GetFilenameWithoutExtension(libPath);
             const auto fwDir = cmSystemTools::GetParentDirectory(libPath);
-            libPaths.Add("-F " + this->XCodeEscapePath(fwDir));
+            if (emitted.insert(fwDir).second) {
+              // This is a search path we had not added before and it isn't an
+              // implicit search path, so we need it
+              libPaths.Add("-F " + this->XCodeEscapePath(fwDir));
+            }
             libPaths.Add("-framework " + fwName);
           } else {
             libPaths.Add(this->XCodeEscapePath(cleanPath));
-- 
cgit v0.12