Browse Source

Merge topic 'xcode-framework-path' into release-3.19

5389bb4274 Xcode: Don't hard-code SDK-provided implicit framework search paths
df08f8df30 cmComputeLinkInformation: Fix misspelt private variable name
375b307bae Apple: Fix linking to frameworks that do not exist until build time

Acked-by: Kitware Robot <[email protected]>
Merge-request: !5760
Brad King 4 years ago
parent
commit
7b9ea201fc

+ 15 - 15
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
 {
@@ -699,9 +705,13 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item,
   } else {
     // This is not a CMake target.  Use the name given.
     if (cmSystemTools::FileIsFullPath(item.Value)) {
-      if (cmSystemTools::FileIsDirectory(item.Value)) {
+      if (cmSystemTools::IsPathToFramework(item.Value) &&
+          this->Makefile->IsOn("APPLE")) {
+        // This is a framework.
+        this->AddFrameworkItem(item.Value);
+      } else if (cmSystemTools::FileIsDirectory(item.Value)) {
         // This is a directory.
-        this->AddDirectoryItem(item.Value);
+        this->DropDirectoryItem(item.Value);
       } else {
         // Use the full path given to the library file.
         this->Depends.push_back(item.Value);
@@ -1306,16 +1316,6 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
   }
 }
 
-void cmComputeLinkInformation::AddDirectoryItem(std::string const& item)
-{
-  if (this->Makefile->IsOn("APPLE") &&
-      cmSystemTools::IsPathToFramework(item)) {
-    this->AddFrameworkItem(item);
-  } else {
-    this->DropDirectoryItem(item);
-  }
-}
-
 void cmComputeLinkInformation::DropDirectoryItem(std::string const& item)
 {
   // A full path to a directory was found as a link item.  Warn the
@@ -1342,8 +1342,8 @@ void cmComputeLinkInformation::ComputeFrameworkInfo()
     "CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES");
   this->Makefile->GetDefExpandList(implicitDirVar, implicitDirVec);
 
-  this->FrameworkPathsEmmitted.insert(implicitDirVec.begin(),
-                                      implicitDirVec.end());
+  this->FrameworkPathsEmitted.insert(implicitDirVec.begin(),
+                                     implicitDirVec.end());
 
   // Regular expression to extract a framework path and name.
   this->SplitFramework.compile("(.*)/(.*)\\.framework$");
@@ -1351,7 +1351,7 @@ void cmComputeLinkInformation::ComputeFrameworkInfo()
 
 void cmComputeLinkInformation::AddFrameworkPath(std::string const& p)
 {
-  if (this->FrameworkPathsEmmitted.insert(p).second) {
+  if (this->FrameworkPathsEmitted.insert(p).second) {
     this->FrameworkPaths.push_back(p);
   }
 }

+ 2 - 2
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; }
@@ -155,7 +156,6 @@ private:
   void AddFullItem(BT<std::string> const& item);
   bool CheckImplicitDirItem(std::string const& item);
   void AddUserItem(BT<std::string> const& item, bool pathNotKnown);
-  void AddDirectoryItem(std::string const& item);
   void AddFrameworkItem(std::string const& item);
   void DropDirectoryItem(std::string const& item);
   bool CheckSharedLibNoSOName(std::string const& item);
@@ -165,7 +165,7 @@ private:
   // Framework info.
   void ComputeFrameworkInfo();
   void AddFrameworkPath(std::string const& p);
-  std::set<std::string> FrameworkPathsEmmitted;
+  std::set<std::string> FrameworkPathsEmitted;
   cmsys::RegularExpression SplitFramework;
 
   // Linker search path computation.

+ 14 - 1
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));

+ 16 - 0
Tests/Framework/CMakeLists.txt

@@ -84,3 +84,19 @@ if(NOT XCODE OR NOT XCODE_VERSION VERSION_LESS 5)
 endif()
 
 include(CPack)
+
+if(APPLE)
+  set(ExternalFramework_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/External")
+  file(REMOVE_RECURSE "${ExternalFramework_INSTALL_DIR}")
+
+  include(ExternalProject)
+  ExternalProject_Add(ExternalFramework
+    SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/External"
+    INSTALL_DIR "${ExternalFramework_INSTALL_DIR}"
+    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
+  )
+
+  add_executable(useExternal useExternal.c)
+  target_link_libraries(useExternal PRIVATE "${ExternalFramework_INSTALL_DIR}/lib/External.framework")
+  add_dependencies(useExternal ExternalFramework)
+endif()

+ 5 - 0
Tests/Framework/External/CMakeLists.txt

@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.19)
+project(ExternalFramework C)
+add_library(External SHARED external.c)
+set_property(TARGET External PROPERTY FRAMEWORK 1)
+install(TARGETS External DESTINATION lib)

+ 4 - 0
Tests/Framework/External/external.c

@@ -0,0 +1,4 @@
+int external(void)
+{
+  return 0;
+}

+ 6 - 0
Tests/Framework/useExternal.c

@@ -0,0 +1,6 @@
+extern int external(void);
+
+int main(void)
+{
+  return external();
+}