mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-04 21:00:17 -06:00
GenEx/LINK_LIBRARY: Add features for framework support on Apple
This commit is contained in:
11
Help/release/dev/Apple-link-framework.rst
Normal file
11
Help/release/dev/Apple-link-framework.rst
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Apple-link-framework
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
* The :genex:`LINK_LIBRARY` generator expression gained the ability to link
|
||||||
|
frameworks in various ways when targeting ``Apple`` platforms. The following
|
||||||
|
new features were added:
|
||||||
|
|
||||||
|
* ``FRAMEWORK``
|
||||||
|
* ``NEEDED_FRAMEWORK``
|
||||||
|
* ``REEXPORT_FRAMEWORK``
|
||||||
|
* ``WEAK_FRAMEWORK``
|
||||||
@@ -3,3 +3,43 @@
|
|||||||
* ``DEFAULT``: This feature enables default link expression. This is mainly
|
* ``DEFAULT``: This feature enables default link expression. This is mainly
|
||||||
useful with :prop_tgt:`LINK_LIBRARY_OVERRIDE` and
|
useful with :prop_tgt:`LINK_LIBRARY_OVERRIDE` and
|
||||||
:prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties.
|
:prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties.
|
||||||
|
|
||||||
|
**Features available in Apple environments**
|
||||||
|
|
||||||
|
It is assumed that the linker used is the one provided by `XCode` or is
|
||||||
|
compatible with it.
|
||||||
|
|
||||||
|
* ``FRAMEWORK``: This option tells the linker to search for the specified
|
||||||
|
framework (use linker option ``-framework``).
|
||||||
|
* ``NEEDED_FRAMEWORK``: This is the same as the ``FRAMEWORK`` feature but means
|
||||||
|
to really link with the framework even if no symbols are used from it (use
|
||||||
|
linker option ``-needed_framework``).
|
||||||
|
* ``REEXPORT_FRAMEWORK``: This is the same as the ``FRAMEWORK`` feature but
|
||||||
|
also specifies that all symbols in that framework should be available to
|
||||||
|
clients linking to the library being created (use linker option
|
||||||
|
``-reexport_framework``).
|
||||||
|
* ``WEAK_FRAMEWORK``: This is the same as the ``FRAMEWORK`` feature but forces
|
||||||
|
the framework and all references to it to be marked as weak imports (use
|
||||||
|
linker option ``-weak_framework``).
|
||||||
|
|
||||||
|
Features for framework linking have a special handling in ``CMake``: the
|
||||||
|
framework can be specified as a ``CMake`` framework target or file path. In
|
||||||
|
the later case, if the path includes a directory part, this one will be
|
||||||
|
specified as framework search path at link step.
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
add_library(lib SHARED ...)
|
||||||
|
target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:NEEDED_FRAMEWORK,/path/to/my_framework>")
|
||||||
|
|
||||||
|
# at link step we will have:
|
||||||
|
# -F/path/to -needed_framework my_framework
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The expected formats for the file path, with optional parts specified as
|
||||||
|
``()?``, are:
|
||||||
|
|
||||||
|
* (/path/to/)?FwName(.framework)?
|
||||||
|
* (/path/to/)?FwName.framework/FwName
|
||||||
|
* (/path/to/)?FwName.framework/Versions/\*/FwName
|
||||||
|
|||||||
@@ -38,3 +38,18 @@ set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_NONE "")
|
|||||||
if(UNIX)
|
if(UNIX)
|
||||||
list(APPEND CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "rt" "pthread" "dl")
|
list(APPEND CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "rt" "pthread" "dl")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
# Defines host link features for frameworks
|
||||||
|
set(CMAKE_CUDA_LINK_USING_FRAMEWORK "LINKER:-framework,<LIBRARY>")
|
||||||
|
set(CMAKE_CUDA_LINK_USING_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_CUDA_LINK_USING_NEEDED_FRAMEWORK "LINKER:-needed_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_CUDA_LINK_USING_NEEDED_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_CUDA_LINK_USING_REEXPORT_FRAMEWORK "LINKER:-reexport_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_CUDA_LINK_USING_REEXPORT_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_CUDA_LINK_USING_WEAK_FRAMEWORK "LINKER:-weak_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_CUDA_LINK_USING_WEAK_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -1 +1,15 @@
|
|||||||
set(CMAKE_Swift_SYSROOT_FLAG "-sdk")
|
set(CMAKE_Swift_SYSROOT_FLAG "-sdk")
|
||||||
|
|
||||||
|
|
||||||
|
# Defines host link features for frameworks
|
||||||
|
set(CMAKE_Swift_LINK_USING_FRAMEWORK "LINKER:-framework,<LIBRARY>")
|
||||||
|
set(CMAKE_Swift_LINK_USING_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_Swift_LINK_USING_NEEDED_FRAMEWORK "LINKER:-needed_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_Swift_LINK_USING_NEEDED_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_Swift_LINK_USING_REEXPORT_FRAMEWORK "LINKER:-reexport_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_Swift_LINK_USING_REEXPORT_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_Swift_LINK_USING_WEAK_FRAMEWORK "LINKER:-weak_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_Swift_LINK_USING_WEAK_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|||||||
@@ -17,3 +17,17 @@ set(CMAKE_SHARED_MODULE_CREATE_CUDA_FLAGS "-shared -Wl,-headerpad_max_install_na
|
|||||||
|
|
||||||
set(CMAKE_CUDA_CREATE_SHARED_LIBRARY "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>${__IMPLICIT_LINKS}")
|
set(CMAKE_CUDA_CREATE_SHARED_LIBRARY "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>${__IMPLICIT_LINKS}")
|
||||||
set(CMAKE_CUDA_CREATE_SHARED_MODULE "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>${__IMPLICIT_LINKS}")
|
set(CMAKE_CUDA_CREATE_SHARED_MODULE "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>${__IMPLICIT_LINKS}")
|
||||||
|
|
||||||
|
|
||||||
|
# Defines host link features for frameworks
|
||||||
|
set(CMAKE_CUDA_LINK_USING_FRAMEWORK "LINKER:-framework,<LIBRARY>")
|
||||||
|
set(CMAKE_CUDA_LINK_USING_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_CUDA_LINK_USING_NEEDED_FRAMEWORK "LINKER:-needed_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_CUDA_LINK_USING_NEEDED_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_CUDA_LINK_USING_REEXPORT_FRAMEWORK "LINKER:-reexport_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_CUDA_LINK_USING_REEXPORT_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_CUDA_LINK_USING_WEAK_FRAMEWORK "LINKER:-weak_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_CUDA_LINK_USING_WEAK_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|||||||
@@ -106,6 +106,19 @@ foreach(lang C CXX Fortran OBJC OBJCXX)
|
|||||||
# Set default framework search path flag for languages known to use a
|
# Set default framework search path flag for languages known to use a
|
||||||
# preprocessor that may find headers in frameworks.
|
# preprocessor that may find headers in frameworks.
|
||||||
set(CMAKE_${lang}_FRAMEWORK_SEARCH_FLAG -F)
|
set(CMAKE_${lang}_FRAMEWORK_SEARCH_FLAG -F)
|
||||||
|
|
||||||
|
# Defines link features for frameworks
|
||||||
|
set(CMAKE_${lang}_LINK_USING_FRAMEWORK "LINKER:-framework,<LIBRARY>")
|
||||||
|
set(CMAKE_${lang}_LINK_USING_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_${lang}_LINK_USING_NEEDED_FRAMEWORK "LINKER:-needed_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_${lang}_LINK_USING_NEEDED_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_${lang}_LINK_USING_REEXPORT_FRAMEWORK "LINKER:-reexport_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_${lang}_LINK_USING_REEXPORT_FRAMEWORK_SUPPORTED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_${lang}_LINK_USING_WEAK_FRAMEWORK "LINKER:-weak_framework,<LIBRARY>")
|
||||||
|
set(CMAKE_${lang}_LINK_USING_WEAK_FRAMEWORK_SUPPORTED TRUE)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# default to searching for frameworks first
|
# default to searching for frameworks first
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <cm/memory>
|
#include <cm/memory>
|
||||||
#include <cm/optional>
|
#include <cm/optional>
|
||||||
#include <cmext/algorithm>
|
#include <cmext/algorithm>
|
||||||
|
#include <cmext/string_view>
|
||||||
|
|
||||||
#include "cmComputeLinkDepends.h"
|
#include "cmComputeLinkDepends.h"
|
||||||
#include "cmGeneratorTarget.h"
|
#include "cmGeneratorTarget.h"
|
||||||
@@ -19,7 +20,6 @@
|
|||||||
#include "cmMakefile.h"
|
#include "cmMakefile.h"
|
||||||
#include "cmMessageType.h"
|
#include "cmMessageType.h"
|
||||||
#include "cmOrderDirectories.h"
|
#include "cmOrderDirectories.h"
|
||||||
#include "cmOutputConverter.h"
|
|
||||||
#include "cmPlaceholderExpander.h"
|
#include "cmPlaceholderExpander.h"
|
||||||
#include "cmPolicies.h"
|
#include "cmPolicies.h"
|
||||||
#include "cmState.h"
|
#include "cmState.h"
|
||||||
@@ -1045,12 +1045,14 @@ void cmComputeLinkInformation::AddItem(LinkEntry const& entry)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is not a CMake target. Use the name given.
|
// This is not a CMake target. Use the name given.
|
||||||
if (cmSystemTools::FileIsFullPath(item.Value)) {
|
if (cmHasSuffix(entry.Feature, "FRAMEWORK"_s) ||
|
||||||
if (cmSystemTools::IsPathToFramework(item.Value) &&
|
(entry.Feature == DEFAULT &&
|
||||||
this->Makefile->IsOn("APPLE")) {
|
cmSystemTools::IsPathToFramework(item.Value) &&
|
||||||
// This is a framework.
|
this->Makefile->IsOn("APPLE"))) {
|
||||||
this->AddFrameworkItem(entry);
|
// This is a framework.
|
||||||
} else if (cmSystemTools::FileIsDirectory(item.Value)) {
|
this->AddFrameworkItem(entry);
|
||||||
|
} else if (cmSystemTools::FileIsFullPath(item.Value)) {
|
||||||
|
if (cmSystemTools::FileIsDirectory(item.Value)) {
|
||||||
// This is a directory.
|
// This is a directory.
|
||||||
this->DropDirectoryItem(item);
|
this->DropDirectoryItem(item);
|
||||||
} else {
|
} else {
|
||||||
@@ -1425,11 +1427,41 @@ void cmComputeLinkInformation::AddTargetItem(LinkEntry const& entry)
|
|||||||
this->OldLinkDirItems.push_back(item.Value);
|
this->OldLinkDirItems.push_back(item.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now add the full path to the library.
|
if (target->IsFrameworkOnApple() && this->GlobalGenerator->IsXcode() &&
|
||||||
this->Items.emplace_back(item, ItemIsPath::Yes, target,
|
entry.Feature == DEFAULT) {
|
||||||
this->FindLibraryFeature(entry.Feature == DEFAULT
|
// ensure FRAMEWORK feature is loaded
|
||||||
? "__CMAKE_LINK_LIBRARY"
|
this->AddLibraryFeature("FRAMEWORK");
|
||||||
: entry.Feature));
|
}
|
||||||
|
|
||||||
|
if (cmHasSuffix(entry.Feature, "FRAMEWORK"_s) &&
|
||||||
|
target->IsFrameworkOnApple() && !this->GlobalGenerator->IsXcode()) {
|
||||||
|
// Add the framework directory and the framework item itself
|
||||||
|
auto fwItems = this->GlobalGenerator->SplitFrameworkPath(item.Value, true);
|
||||||
|
if (!fwItems) {
|
||||||
|
this->CMakeInstance->IssueMessage(
|
||||||
|
MessageType::FATAL_ERROR,
|
||||||
|
cmStrCat("Could not parse framework path \"", item.Value,
|
||||||
|
"\" linked by target ", this->Target->GetName(), '.'),
|
||||||
|
item.Backtrace);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!fwItems->first.empty()) {
|
||||||
|
// Add the directory portion to the framework search path.
|
||||||
|
this->AddFrameworkPath(fwItems->first);
|
||||||
|
}
|
||||||
|
this->Items.emplace_back(fwItems->second, ItemIsPath::Yes, target,
|
||||||
|
this->FindLibraryFeature(entry.Feature));
|
||||||
|
} else {
|
||||||
|
// Now add the full path to the library.
|
||||||
|
this->Items.emplace_back(
|
||||||
|
item, ItemIsPath::Yes, target,
|
||||||
|
this->FindLibraryFeature(
|
||||||
|
entry.Feature == DEFAULT
|
||||||
|
? (target->IsFrameworkOnApple() && this->GlobalGenerator->IsXcode()
|
||||||
|
? "FRAMEWORK"
|
||||||
|
: "__CMAKE_LINK_LIBRARY")
|
||||||
|
: entry.Feature));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmComputeLinkInformation::AddFullItem(LinkEntry const& entry)
|
void cmComputeLinkInformation::AddFullItem(LinkEntry const& entry)
|
||||||
@@ -1680,7 +1712,8 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry)
|
|||||||
std::string const& item = entry.Item.Value;
|
std::string const& item = entry.Item.Value;
|
||||||
|
|
||||||
// Try to separate the framework name and path.
|
// Try to separate the framework name and path.
|
||||||
auto fwItems = this->GlobalGenerator->SplitFrameworkPath(item);
|
auto fwItems =
|
||||||
|
this->GlobalGenerator->SplitFrameworkPath(item, entry.Feature != DEFAULT);
|
||||||
if (!fwItems) {
|
if (!fwItems) {
|
||||||
std::ostringstream e;
|
std::ostringstream e;
|
||||||
e << "Could not parse framework path \"" << item << "\" "
|
e << "Could not parse framework path \"" << item << "\" "
|
||||||
@@ -1691,24 +1724,34 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry)
|
|||||||
|
|
||||||
std::string fw_path = std::move(fwItems->first);
|
std::string fw_path = std::move(fwItems->first);
|
||||||
std::string fw = std::move(fwItems->second);
|
std::string fw = std::move(fwItems->second);
|
||||||
std::string full_fw = cmStrCat(fw_path, '/', fw, ".framework/", fw);
|
std::string full_fw = cmStrCat(fw, ".framework/", fw);
|
||||||
|
|
||||||
// Add the directory portion to the framework search path.
|
if (!fw_path.empty()) {
|
||||||
this->AddFrameworkPath(fw_path);
|
full_fw = cmStrCat(fw_path, '/', full_fw);
|
||||||
|
// Add the directory portion to the framework search path.
|
||||||
|
this->AddFrameworkPath(fw_path);
|
||||||
|
}
|
||||||
|
|
||||||
// add runtime information
|
// add runtime information
|
||||||
this->AddLibraryRuntimeInfo(full_fw);
|
this->AddLibraryRuntimeInfo(full_fw);
|
||||||
|
|
||||||
|
if (entry.Feature == DEFAULT) {
|
||||||
|
// ensure FRAMEWORK feature is loaded
|
||||||
|
this->AddLibraryFeature("FRAMEWORK");
|
||||||
|
}
|
||||||
|
|
||||||
if (this->GlobalGenerator->IsXcode()) {
|
if (this->GlobalGenerator->IsXcode()) {
|
||||||
// Add framework path - it will be handled by Xcode after it's added to
|
// Add framework path - it will be handled by Xcode after it's added to
|
||||||
// "Link Binary With Libraries" build phase
|
// "Link Binary With Libraries" build phase
|
||||||
this->Items.emplace_back(item, ItemIsPath::Yes);
|
this->Items.emplace_back(item, ItemIsPath::Yes, nullptr,
|
||||||
|
this->FindLibraryFeature(entry.Feature == DEFAULT
|
||||||
|
? "FRAMEWORK"
|
||||||
|
: entry.Feature));
|
||||||
} else {
|
} else {
|
||||||
// Add the item using the -framework option.
|
this->Items.emplace_back(fw, ItemIsPath::Yes, nullptr,
|
||||||
this->Items.emplace_back(std::string("-framework"), ItemIsPath::No);
|
this->FindLibraryFeature(entry.Feature == DEFAULT
|
||||||
cmOutputConverter converter(this->Makefile->GetStateSnapshot());
|
? "FRAMEWORK"
|
||||||
fw = converter.EscapeForShell(fw);
|
: entry.Feature));
|
||||||
this->Items.emplace_back(fw, ItemIsPath::No);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ public:
|
|||||||
cmGeneratorTarget const* Target = nullptr;
|
cmGeneratorTarget const* Target = nullptr;
|
||||||
|
|
||||||
bool HasFeature() const { return this->Feature != nullptr; }
|
bool HasFeature() const { return this->Feature != nullptr; }
|
||||||
|
const std::string& GetFeatureName() const
|
||||||
|
{
|
||||||
|
return HasFeature() ? this->Feature->Name
|
||||||
|
: cmComputeLinkDepends::LinkEntry::DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
BT<std::string> GetFormattedItem(std::string const& path) const
|
BT<std::string> GetFormattedItem(std::string const& path) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2529,7 +2529,8 @@ bool cmGlobalGenerator::NameResolvesToFramework(
|
|||||||
// .tbd files also can be located in SDK frameworks (they are
|
// .tbd files also can be located in SDK frameworks (they are
|
||||||
// placeholders for actual libraries shipped with the OS)
|
// placeholders for actual libraries shipped with the OS)
|
||||||
cm::optional<std::pair<std::string, std::string>>
|
cm::optional<std::pair<std::string, std::string>>
|
||||||
cmGlobalGenerator::SplitFrameworkPath(const std::string& path) const
|
cmGlobalGenerator::SplitFrameworkPath(const std::string& path,
|
||||||
|
bool extendedFormat) const
|
||||||
{
|
{
|
||||||
// Check for framework structure:
|
// Check for framework structure:
|
||||||
// (/path/to/)?FwName.framework
|
// (/path/to/)?FwName.framework
|
||||||
@@ -2550,6 +2551,16 @@ cmGlobalGenerator::SplitFrameworkPath(const std::string& path) const
|
|||||||
return std::pair<std::string, std::string>{ frameworkPath.match(2), name };
|
return std::pair<std::string, std::string>{ frameworkPath.match(2), name };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (extendedFormat) {
|
||||||
|
// path format can be more flexible: (/path/to/)?fwName(.framework)?
|
||||||
|
auto fwDir = cmSystemTools::GetParentDirectory(path);
|
||||||
|
auto name = cmSystemTools::GetFilenameLastExtension(path) == ".framework"
|
||||||
|
? cmSystemTools::GetFilenameWithoutExtension(path)
|
||||||
|
: cmSystemTools::GetFilenameName(path);
|
||||||
|
|
||||||
|
return std::pair<std::string, std::string>{ fwDir, name };
|
||||||
|
}
|
||||||
|
|
||||||
return cm::nullopt;
|
return cm::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -368,9 +368,12 @@ public:
|
|||||||
that is a framework. */
|
that is a framework. */
|
||||||
bool NameResolvesToFramework(const std::string& libname) const;
|
bool NameResolvesToFramework(const std::string& libname) const;
|
||||||
/** Split a framework path to the directory and name of the framework
|
/** Split a framework path to the directory and name of the framework
|
||||||
* returns std::nullopt if the path does not match with framework format */
|
* returns std::nullopt if the path does not match with framework format
|
||||||
|
* when extendedFormat is true, required format is relaxed (i.e. extension
|
||||||
|
* `.framework' is optional). Used when FRAMEWORK link feature is
|
||||||
|
* specified */
|
||||||
cm::optional<std::pair<std::string, std::string>> SplitFrameworkPath(
|
cm::optional<std::pair<std::string, std::string>> SplitFrameworkPath(
|
||||||
const std::string& path) const;
|
const std::string& path, bool extendedFormat = false) const;
|
||||||
|
|
||||||
cmMakefile* FindMakefile(const std::string& start_dir) const;
|
cmMakefile* FindMakefile(const std::string& start_dir) const;
|
||||||
cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const;
|
cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const;
|
||||||
|
|||||||
@@ -3519,13 +3519,14 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
|
|||||||
} else {
|
} else {
|
||||||
linkDir = libItem->Value.Value;
|
linkDir = libItem->Value.Value;
|
||||||
}
|
}
|
||||||
linkDir = this->GetLibraryOrFrameworkPath(linkDir);
|
if (cmHasSuffix(libItem->GetFeatureName(), "FRAMEWORK"_s)) {
|
||||||
bool isFramework = cmSystemTools::IsPathToFramework(linkDir);
|
auto fwItems = this->SplitFrameworkPath(linkDir, true);
|
||||||
linkDir = cmSystemTools::GetParentDirectory(linkDir);
|
if (fwItems && !fwItems->first.empty()) {
|
||||||
if (isFramework) {
|
linkDir = std::move(fwItems->first);
|
||||||
if (std::find(frameworkSearchPaths.begin(), frameworkSearchPaths.end(),
|
if (std::find(frameworkSearchPaths.begin(), frameworkSearchPaths.end(),
|
||||||
linkDir) == frameworkSearchPaths.end()) {
|
linkDir) == frameworkSearchPaths.end()) {
|
||||||
frameworkSearchPaths.push_back(linkDir);
|
frameworkSearchPaths.push_back(linkDir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (std::find(linkSearchPaths.begin(), linkSearchPaths.end(), linkDir) ==
|
if (std::find(linkSearchPaths.begin(), linkSearchPaths.end(), linkDir) ==
|
||||||
@@ -3533,7 +3534,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
|
|||||||
linkSearchPaths.push_back(linkDir);
|
linkSearchPaths.push_back(linkDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add target dependency
|
|
||||||
if (libItem->Target && !libItem->Target->IsImported()) {
|
if (libItem->Target && !libItem->Target->IsImported()) {
|
||||||
for (auto const& configName : this->CurrentConfigurationTypes) {
|
for (auto const& configName : this->CurrentConfigurationTypes) {
|
||||||
target->AddDependTarget(configName, libItem->Target->GetName());
|
target->AddDependTarget(configName, libItem->Target->GetName());
|
||||||
@@ -3707,24 +3708,27 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
|
|||||||
if (cmSystemTools::FileIsFullPath(cleanPath)) {
|
if (cmSystemTools::FileIsFullPath(cleanPath)) {
|
||||||
cleanPath = cmSystemTools::CollapseFullPath(cleanPath);
|
cleanPath = cmSystemTools::CollapseFullPath(cleanPath);
|
||||||
}
|
}
|
||||||
const auto libPath = this->GetLibraryOrFrameworkPath(cleanPath);
|
bool isFramework =
|
||||||
if (cmSystemTools::StringEndsWith(libPath.c_str(), ".framework")) {
|
cmHasSuffix(libName.GetFeatureName(), "FRAMEWORK"_s);
|
||||||
const auto fwName =
|
if (isFramework) {
|
||||||
cmSystemTools::GetFilenameWithoutExtension(libPath);
|
const auto fwItems =
|
||||||
const auto fwDir = cmSystemTools::GetParentDirectory(libPath);
|
this->SplitFrameworkPath(cleanPath, isFramework);
|
||||||
if (emitted.insert(fwDir).second) {
|
if (!fwItems->first.empty() &&
|
||||||
// This is a search path we had not added before and it isn't an
|
emitted.insert(fwItems->first).second) {
|
||||||
// implicit search path, so we need it
|
// This is a search path we had not added before and it isn't
|
||||||
libPaths.Add("-F " + this->XCodeEscapePath(fwDir));
|
// an implicit search path, so we need it
|
||||||
|
libPaths.Add("-F " + this->XCodeEscapePath(fwItems->first));
|
||||||
}
|
}
|
||||||
libPaths.Add("-framework " + this->XCodeEscapePath(fwName));
|
libPaths.Add(
|
||||||
|
libName.GetFormattedItem(this->XCodeEscapePath(fwItems->second))
|
||||||
|
.Value);
|
||||||
} else {
|
} else {
|
||||||
libPaths.Add(
|
libPaths.Add(
|
||||||
libName.GetFormattedItem(this->XCodeEscapePath(cleanPath))
|
libName.GetFormattedItem(this->XCodeEscapePath(cleanPath))
|
||||||
.Value);
|
.Value);
|
||||||
}
|
}
|
||||||
if ((!libName.Target || libName.Target->IsImported()) &&
|
if ((!libName.Target || libName.Target->IsImported()) &&
|
||||||
IsLinkPhaseLibraryExtension(libPath)) {
|
(isFramework || IsLinkPhaseLibraryExtension(cleanPath))) {
|
||||||
// Create file reference for embedding
|
// Create file reference for embedding
|
||||||
auto it = this->ExternalLibRefs.find(cleanPath);
|
auto it = this->ExternalLibRefs.find(cleanPath);
|
||||||
if (it == this->ExternalLibRefs.end()) {
|
if (it == this->ExternalLibRefs.end()) {
|
||||||
@@ -3892,8 +3896,8 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
|
|||||||
{
|
{
|
||||||
static const auto dstSubfolderSpec = "10";
|
static const auto dstSubfolderSpec = "10";
|
||||||
|
|
||||||
// Despite the name, by default Xcode uses "Embed Frameworks" build phase for
|
// Despite the name, by default Xcode uses "Embed Frameworks" build phase
|
||||||
// both frameworks and dynamic libraries
|
// for both frameworks and dynamic libraries
|
||||||
this->AddEmbeddedObjects(target, "Embed Frameworks",
|
this->AddEmbeddedObjects(target, "Embed Frameworks",
|
||||||
"XCODE_EMBED_FRAMEWORKS", dstSubfolderSpec,
|
"XCODE_EMBED_FRAMEWORKS", dstSubfolderSpec,
|
||||||
NoActionOnCopyByDefault);
|
NoActionOnCopyByDefault);
|
||||||
|
|||||||
@@ -659,6 +659,7 @@ add_RunCMake_test(target_link_libraries-LINK_LIBRARY -DCMAKE_SYSTEM_NAME=${CMAKE
|
|||||||
-DMSYS=${MSYS}
|
-DMSYS=${MSYS}
|
||||||
-DCYGWIN=${CYGWIN}
|
-DCYGWIN=${CYGWIN}
|
||||||
-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
|
-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
|
||||||
|
-DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION}
|
||||||
-DMSVC_VERSION=${MSVC_VERSION}
|
-DMSVC_VERSION=${MSVC_VERSION}
|
||||||
-DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX}
|
-DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX}
|
||||||
-DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX}
|
-DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||||
|
|||||||
@@ -79,3 +79,21 @@ if ((RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Xcode"
|
|||||||
unset(RunCMake_TEST_OUTPUT_MERGE)
|
unset(RunCMake_TEST_OUTPUT_MERGE)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Apple framework features
|
||||||
|
if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang"))
|
||||||
|
run_cmake(apple_framework)
|
||||||
|
run_cmake_target(apple_framework framework main-framework)
|
||||||
|
run_cmake_target(apple_framework reexport_framework main-reexport_framework)
|
||||||
|
run_cmake_target(apple_framework weak_framework main-weak_framework)
|
||||||
|
|
||||||
|
run_cmake_target(apple_framework target-framework main-target-framework)
|
||||||
|
run_cmake_target(apple_framework target-reexport_framework main-target-reexport_framework)
|
||||||
|
run_cmake_target(apple_framework target-weak_framework main-target-weak_framework)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_C_COMPILER_VERSION GREATER_EQUAL "12")
|
||||||
|
run_cmake_target(apple_framework needed_framework main-needed_framework)
|
||||||
|
|
||||||
|
run_cmake_target(apple_framework target-needed_framework main-target-needed_framework)
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
enable_language(OBJCXX)
|
||||||
|
|
||||||
|
|
||||||
|
# feature FRAMEWORK
|
||||||
|
add_library(foo-framework SHARED foo.mm)
|
||||||
|
target_link_libraries(foo-framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>")
|
||||||
|
|
||||||
|
add_executable(main-framework main.mm)
|
||||||
|
target_link_libraries(main-framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" foo-framework)
|
||||||
|
|
||||||
|
|
||||||
|
# feature NEEDED_FRAMEWORK
|
||||||
|
add_library(foo-needed_framework SHARED foo.mm)
|
||||||
|
target_link_libraries(foo-needed_framework PRIVATE "$<LINK_LIBRARY:NEEDED_FRAMEWORK,Foundation>")
|
||||||
|
|
||||||
|
add_executable(main-needed_framework main.mm)
|
||||||
|
target_link_libraries(main-needed_framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" foo-needed_framework)
|
||||||
|
|
||||||
|
|
||||||
|
# feature REEXPORT_FRAMEWORK
|
||||||
|
add_library(foo-reexport_framework SHARED foo.mm)
|
||||||
|
target_link_libraries(foo-reexport_framework PRIVATE "$<LINK_LIBRARY:REEXPORT_FRAMEWORK,Foundation>")
|
||||||
|
|
||||||
|
add_executable(main-reexport_framework main.mm)
|
||||||
|
target_link_libraries(main-reexport_framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" foo-reexport_framework)
|
||||||
|
|
||||||
|
|
||||||
|
# feature WEAK_FRAMEWORK
|
||||||
|
add_library(foo-weak_framework SHARED foo.mm)
|
||||||
|
target_link_libraries(foo-weak_framework PRIVATE "$<LINK_LIBRARY:WEAK_FRAMEWORK,Foundation>")
|
||||||
|
|
||||||
|
add_executable(main-weak_framework main.mm)
|
||||||
|
target_link_libraries(main-weak_framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" foo-weak_framework)
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
## Consumption of target specified as FRAMEWORK
|
||||||
|
add_library(target-framework SHARED foo.mm)
|
||||||
|
set_target_properties(target-framework PROPERTIES FRAMEWORK TRUE)
|
||||||
|
target_link_libraries(target-framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>")
|
||||||
|
|
||||||
|
|
||||||
|
# feature FRAMEWORK
|
||||||
|
add_executable(main-target-framework main.mm)
|
||||||
|
target_link_libraries(main-target-framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:FRAMEWORK,target-framework>")
|
||||||
|
|
||||||
|
|
||||||
|
# feature NEEDED_FRAMEWORK
|
||||||
|
add_executable(main-target-needed_framework main.mm)
|
||||||
|
target_link_libraries(main-target-needed_framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:NEEDED_FRAMEWORK,target-framework>")
|
||||||
|
|
||||||
|
|
||||||
|
# feature REEXPORT_FRAMEWORK
|
||||||
|
add_executable(main-target-reexport_framework main.mm)
|
||||||
|
target_link_libraries(main-target-reexport_framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:REEXPORT_FRAMEWORK,target-framework>")
|
||||||
|
|
||||||
|
|
||||||
|
# feature WEAK_FRAMEWORK
|
||||||
|
add_executable(main-target-weak_framework main.mm)
|
||||||
|
target_link_libraries(main-target-weak_framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:REEXPORT_FRAMEWORK,target-framework>")
|
||||||
9
Tests/RunCMake/target_link_libraries-LINK_LIBRARY/foo.h
Normal file
9
Tests/RunCMake/target_link_libraries-LINK_LIBRARY/foo.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface Foo : NSObject {
|
||||||
|
NSNumber* age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property (nonatomic, retain) NSNumber* age;
|
||||||
|
|
||||||
|
@end
|
||||||
7
Tests/RunCMake/target_link_libraries-LINK_LIBRARY/foo.mm
Normal file
7
Tests/RunCMake/target_link_libraries-LINK_LIBRARY/foo.mm
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#import "foo.h"
|
||||||
|
|
||||||
|
@implementation Foo
|
||||||
|
|
||||||
|
@synthesize age;
|
||||||
|
|
||||||
|
@end
|
||||||
14
Tests/RunCMake/target_link_libraries-LINK_LIBRARY/main.mm
Normal file
14
Tests/RunCMake/target_link_libraries-LINK_LIBRARY/main.mm
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "foo.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
Foo *theFoo = [[Foo alloc] init];
|
||||||
|
theFoo.age = [NSNumber numberWithInt:argc];
|
||||||
|
NSLog(@"%d\n",[theFoo.age intValue]);
|
||||||
|
std::cout << [theFoo.age intValue] << std::endl;
|
||||||
|
[pool release];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user