From 6ef7bfbb645c9f232b41b66b8fb334da8b5ca947 Mon Sep 17 00:00:00 2001 From: Lucas SOLTIC Date: Tue, 14 Sep 2021 08:37:48 +1000 Subject: Xcode: add support for embedding dynamic libraries --- Source/cmGlobalXCodeGenerator.cxx | 7 +++-- Source/cmSystemTools.cxx | 6 ++++ Source/cmSystemTools.h | 6 +++- .../EmbedFrameworksFlagsOff.cmake | 2 +- ...mbedFrameworksFlagsOnNoSubdir-build-check.cmake | 4 +-- .../EmbedFrameworksFlagsOnNoSubdir.cmake | 2 +- ...edFrameworksFlagsOnWithSubdir-build-check.cmake | 4 +-- .../EmbedFrameworksFlagsOnWithSubdir.cmake | 2 +- .../XcodeProject-Embed/ExternalDependencies.cmake | 4 +++ .../XcodeProject-Embed/ExternalFramework.cmake | 2 -- .../RunCMake/XcodeProject-Embed/RunCMakeTest.cmake | 36 ++++++++++++---------- 11 files changed, 46 insertions(+), 29 deletions(-) create mode 100644 Tests/RunCMake/XcodeProject-Embed/ExternalDependencies.cmake delete mode 100644 Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index fa76b01..4ccc955 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -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 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); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 54fe7a1..a20e787 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -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& files, cmTarCompression compressType, bool verbose, diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 44ccbf7..be817b1 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -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& sourceExts); diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake index f4fe07f..54375d5 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake @@ -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 ) diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake index e4ea55d..23fd49d 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake @@ -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() diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake index 79d8d77..c76226f 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake @@ -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 ) diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake index 57c79ea..732f04c 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake @@ -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() diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake index 4c78199..f83b1bf 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake @@ -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" diff --git a/Tests/RunCMake/XcodeProject-Embed/ExternalDependencies.cmake b/Tests/RunCMake/XcodeProject-Embed/ExternalDependencies.cmake new file mode 100644 index 0000000..8c7b06a --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/ExternalDependencies.cmake @@ -0,0 +1,4 @@ +add_library(sharedFrameworkExt SHARED func.m) +set_target_properties(sharedFrameworkExt PROPERTIES FRAMEWORK TRUE) + +add_library(sharedDylibExt SHARED func.m) diff --git a/Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake b/Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake deleted file mode 100644 index 64e2f95..0000000 --- a/Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake +++ /dev/null @@ -1,2 +0,0 @@ -add_library(sharedFrameworkExt SHARED func.m) -set_target_properties(sharedFrameworkExt PROPERTIES FRAMEWORK TRUE) diff --git a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake index e94d084..f3a6918 100644 --- a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake @@ -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}) -- cgit v0.12