Xcode: add support for embedding dynamic libraries

This commit is contained in:
Lucas SOLTIC
2021-09-14 08:37:48 +10:00
committed by Craig Scott
parent b7bcf70761
commit 6ef7bfbb64
10 changed files with 44 additions and 27 deletions

View File

@@ -3809,7 +3809,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects(
copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
this->CreateString("0"));
cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
// Collect all embedded frameworks and add them to build phase
// Collect all embedded frameworks and dylibs and add them to build phase
std::vector<std::string> relFiles = cmExpandedList(*files);
for (std::string const& relFile : relFiles) {
cmXCodeObject* buildFile{ nullptr };
@@ -3839,7 +3839,8 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects(
} else {
buildFile = it->second;
}
} else if (cmSystemTools::IsPathToFramework(relFile)) {
} else if (cmSystemTools::IsPathToFramework(relFile) ||
cmSystemTools::IsPathToMacOSSharedLibrary(relFile)) {
// This is a regular string path - create file reference
auto it = this->EmbeddedLibRefs.find(relFile);
if (it == this->EmbeddedLibRefs.end()) {
@@ -3905,6 +3906,8 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
{
static const auto dstSubfolderSpec = "10";
// Despite the name, by default Xcode uses "Embed Frameworks" build phase for
// both frameworks and dynamic libraries
this->AddEmbeddedObjects(target, "Embed Frameworks",
"XCODE_EMBED_FRAMEWORKS", dstSubfolderSpec,
NoActionOnCopyByDefault);

View File

@@ -1592,6 +1592,12 @@ bool cmSystemTools::IsPathToFramework(const std::string& path)
cmHasLiteralSuffix(path, ".framework"));
}
bool cmSystemTools::IsPathToMacOSSharedLibrary(const std::string& path)
{
return (cmSystemTools::FileIsFullPath(path) &&
cmHasLiteralSuffix(path, ".dylib"));
}
bool cmSystemTools::CreateTar(const std::string& outFileName,
const std::vector<std::string>& files,
cmTarCompression compressType, bool verbose,

View File

@@ -102,7 +102,11 @@ public:
}
//! Return true if the path is a framework
static bool IsPathToFramework(const std::string& value);
static bool IsPathToFramework(const std::string& path);
//! Return true if the path is a macOS non-framework shared library (aka
//! .dylib)
static bool IsPathToMacOSSharedLibrary(const std::string& path);
static bool DoesFileExistWithExtensions(
const std::string& name, const std::vector<std::string>& sourceExts);

View File

@@ -1,7 +1,7 @@
add_executable(app MACOSX_BUNDLE main.m)
set_target_properties(app PROPERTIES
XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}"
XCODE_EMBED_FRAMEWORKS "${EXTERNAL_DEPENDENCY}"
XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY OFF
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY OFF
)

View File

@@ -1,3 +1,3 @@
if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/sharedFrameworkExt.framework)
set(RunCMake_TEST_FAILED "Framework was not embedded at the expected location")
if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/${EXTERNAL_DEPENDENCY_NAME})
set(RunCMake_TEST_FAILED "${EXTERNAL_DEPENDENCY_NAME} was not embedded at the expected location")
endif()

View File

@@ -1,7 +1,7 @@
add_executable(app MACOSX_BUNDLE main.m)
set_target_properties(app PROPERTIES
XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}"
XCODE_EMBED_FRAMEWORKS "${EXTERNAL_DEPENDENCY}"
XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY ON
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON
)

View File

@@ -1,3 +1,3 @@
if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/subdir/sharedFrameworkExt.framework)
set(RunCMake_TEST_FAILED "Framework was not embedded at the expected location")
if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/subdir/${EXTERNAL_DEPENDENCY_NAME})
set(RunCMake_TEST_FAILED "${EXTERNAL_DEPENDENCY_NAME} was not embedded at the expected location")
endif()

View File

@@ -1,7 +1,7 @@
add_executable(app MACOSX_BUNDLE main.m)
set_target_properties(app PROPERTIES
XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}"
XCODE_EMBED_FRAMEWORKS "${EXTERNAL_DEPENDENCY}"
XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY ON
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON
XCODE_EMBED_FRAMEWORKS_PATH "subdir"

View File

@@ -1,2 +1,4 @@
add_library(sharedFrameworkExt SHARED func.m)
set_target_properties(sharedFrameworkExt PROPERTIES FRAMEWORK TRUE)
add_library(sharedDylibExt SHARED func.m)

View File

@@ -1,47 +1,49 @@
include(RunCMake)
# Build a framework that the other tests will use and treat as external.
# Build dependencies that the other tests will use and treat as external.
# Always build in the Debug configuration so that the path to the framework
# is predictable.
function(ExternalFramework)
function(ExternalDependencies)
set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExternalFramework-build)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExternalDependencies-build)
set(externalFramework ${RunCMake_TEST_BINARY_DIR}/Debug/sharedFrameworkExt.framework PARENT_SCOPE)
set(externalDylib ${RunCMake_TEST_BINARY_DIR}/Debug/libsharedDylibExt.dylib PARENT_SCOPE)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
run_cmake(ExternalFramework)
run_cmake_command(ExternalFramework-build
run_cmake(ExternalDependencies)
run_cmake_command(ExternalDependencies-build
${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR}
--config Debug
--target sharedFrameworkExt
--target sharedFrameworkExt sharedDylibExt
)
endfunction()
ExternalFramework()
ExternalDependencies()
set(RunCMake_TEST_OPTIONS -DEXTERNAL_FWK=${externalFramework})
run_cmake(EmbedFrameworksFlagsOff)
function(TestFlagsOn testName)
function(TestFlagsOn testName dependencyName)
set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-build)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-${dependencyName}-build)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
run_cmake(${testName})
run_cmake_command(${testName}-build
run_cmake_command(${testName}-${dependencyName}-build
${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR}
--config Debug
--target app
)
endfunction()
TestFlagsOn(EmbedFrameworksFlagsOnNoSubdir)
TestFlagsOn(EmbedFrameworksFlagsOnWithSubdir)
foreach(dependency ${externalFramework} ${externalDylib})
cmake_path(GET dependency FILENAME dependencyName)
set(RunCMake_TEST_OPTIONS -DEXTERNAL_DEPENDENCY=${dependency} -DEXTERNAL_DEPENDENCY_NAME=${dependencyName})
run_cmake(EmbedFrameworksFlagsOff)
TestFlagsOn(EmbedFrameworksFlagsOnNoSubdir ${dependencyName})
TestFlagsOn(EmbedFrameworksFlagsOnWithSubdir ${dependencyName})
endforeach()
unset(RunCMake_TEST_OPTIONS)
function(TestAppExtension platform)
set(testName EmbedAppExtensions-${platform})