From 375b307bae4513b69b9f86549a094da7f2e8b3a7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 18 Dec 2020 13:44:44 -0500 Subject: Apple: Fix linking to frameworks that do not exist until build time Fixes: #21621 --- Source/cmComputeLinkInformation.cxx | 18 ++++++------------ Source/cmComputeLinkInformation.h | 1 - Tests/Framework/CMakeLists.txt | 16 ++++++++++++++++ Tests/Framework/External/CMakeLists.txt | 5 +++++ Tests/Framework/External/external.c | 4 ++++ Tests/Framework/useExternal.c | 6 ++++++ 6 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 Tests/Framework/External/CMakeLists.txt create mode 100644 Tests/Framework/External/external.c create mode 100644 Tests/Framework/useExternal.c diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 201a9d9..6e1fac0 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -699,9 +699,13 @@ void cmComputeLinkInformation::AddItem(BT 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 +1310,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 diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 543b6d7..ec8d73c 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -155,7 +155,6 @@ private: void AddFullItem(BT const& item); bool CheckImplicitDirItem(std::string const& item); void AddUserItem(BT 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); diff --git a/Tests/Framework/CMakeLists.txt b/Tests/Framework/CMakeLists.txt index a313c2c..f741ec2 100644 --- a/Tests/Framework/CMakeLists.txt +++ b/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= + ) + + add_executable(useExternal useExternal.c) + target_link_libraries(useExternal PRIVATE "${ExternalFramework_INSTALL_DIR}/lib/External.framework") + add_dependencies(useExternal ExternalFramework) +endif() diff --git a/Tests/Framework/External/CMakeLists.txt b/Tests/Framework/External/CMakeLists.txt new file mode 100644 index 0000000..b9128fd --- /dev/null +++ b/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) diff --git a/Tests/Framework/External/external.c b/Tests/Framework/External/external.c new file mode 100644 index 0000000..8441e71 --- /dev/null +++ b/Tests/Framework/External/external.c @@ -0,0 +1,4 @@ +int external(void) +{ + return 0; +} diff --git a/Tests/Framework/useExternal.c b/Tests/Framework/useExternal.c new file mode 100644 index 0000000..8494b15 --- /dev/null +++ b/Tests/Framework/useExternal.c @@ -0,0 +1,6 @@ +extern int external(void); + +int main(void) +{ + return external(); +} -- cgit v0.12 From df08f8df3027db25eb1cb75fb6017c3a8c046674 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Wed, 3 Feb 2021 23:02:36 +1100 Subject: cmComputeLinkInformation: Fix misspelt private variable name --- Source/cmComputeLinkInformation.cxx | 6 +++--- Source/cmComputeLinkInformation.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 6e1fac0..d1680ad 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1336,8 +1336,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$"); @@ -1345,7 +1345,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); } } diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index ec8d73c..d8ec563 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -164,7 +164,7 @@ private: // Framework info. void ComputeFrameworkInfo(); void AddFrameworkPath(std::string const& p); - std::set FrameworkPathsEmmitted; + std::set FrameworkPathsEmitted; cmsys::RegularExpression SplitFramework; // Linker search path computation. -- cgit v0.12 From 5389bb4274f80b69e45aceffbdf3ffdb1e79908f Mon Sep 17 00:00:00 2001 From: Craig Scott 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 const& cmComputeLinkInformation::GetFrameworkPaths() return this->FrameworkPaths; } +std::set const& +cmComputeLinkInformation::GetFrameworkPathsEmitted() const +{ + return this->FrameworkPathsEmitted; +} + const std::set& 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> GetDirectoriesWithBacktraces(); std::vector const& GetDepends() const; std::vector const& GetFrameworkPaths() const; + std::set const& GetFrameworkPathsEmitted() const; std::string GetLinkLanguage() const { return this->LinkLanguage; } std::vector 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 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