From 93ed53790cb1e2d5f25f26156ee5c6590b0d3150 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 21 Jul 2023 12:01:01 -0400 Subject: bootstrap: Unconditionally build libjsoncpp --- Source/cmJSONHelpers.h | 4 ---- bootstrap | 55 ++++++++++++++++++++++---------------------------- 2 files changed, 24 insertions(+), 35 deletions(-) diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h index 94641de..5dfb154 100644 --- a/Source/cmJSONHelpers.h +++ b/Source/cmJSONHelpers.h @@ -38,7 +38,6 @@ using ObjectErrorGenerator = std::function; const auto EXPECTED_TYPE = [](const std::string& type) { return [type](const Json::Value* value, cmJSONState* state) -> void { -#if !defined(CMAKE_BOOTSTRAP) if (state->key().empty()) { state->AddErrorAtValue(cmStrCat("Expected ", type), value); return; @@ -48,7 +47,6 @@ const auto EXPECTED_TYPE = [](const std::string& type) { errMsg = cmStrCat(errMsg, ", got: ", value->asString()); } state->AddErrorAtValue(errMsg, value); -#endif }; }; const auto INVALID_STRING = [](const Json::Value* value, @@ -75,7 +73,6 @@ const auto INVALID_NAMED_OBJECT = const Json::Value::Members& extraFields) -> ErrorGenerator { return [nameGenerator, errorType, extraFields]( const Json::Value* value, cmJSONState* state) -> void { -#if !defined(CMAKE_BOOTSTRAP) std::string name = nameGenerator(value, state); switch (errorType) { case ObjectError::RequiredMissing: @@ -102,7 +99,6 @@ const auto INVALID_NAMED_OBJECT = value); break; } -#endif }; }; }; diff --git a/bootstrap b/bootstrap index cc60425..82c5957 100755 --- a/bootstrap +++ b/bootstrap @@ -414,6 +414,7 @@ CMAKE_CXX_SOURCES="\ cmInstallTargetGenerator \ cmInstallTargetsCommand \ cmInstalledFile \ + cmJSONState \ cmLDConfigLDConfigTool \ cmLDConfigTool \ cmLinkDirectoriesCommand \ @@ -588,6 +589,12 @@ LIBRHASH_C_SOURCES="\ librhash/sha512.c \ " +JSONCPP_CXX_SOURCES="\ + src/lib_json/json_reader.cpp \ + src/lib_json/json_value.cpp \ + src/lib_json/json_writer.cpp \ + " + if ${cmake_system_mingw}; then LIBUV_C_SOURCES="\ src/fs-poll.c \ @@ -1091,12 +1098,6 @@ if test "${cmake_bootstrap_generator}" = "Ninja"; then cmFortranLexer \ cmFortranParser \ " - - JSONCPP_CXX_SOURCES="\ - src/lib_json/json_reader.cpp \ - src/lib_json/json_value.cpp \ - src/lib_json/json_writer.cpp \ - " else CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES} \ cmDepends \ @@ -1110,8 +1111,6 @@ else cmMakefileUtilityTargetGenerator \ cmProcessTools \ " - - JSONCPP_CXX_SOURCES= fi # Add Cygwin-specific flags @@ -1725,12 +1724,10 @@ if test "x${bootstrap_system_librhash}" = "x"; then objs="${objs} rhash-`cmake_obj ${a}`" done fi -if test "${cmake_bootstrap_generator}" = "Ninja"; then - if test "x${bootstrap_system_jsoncpp}" = "x"; then - for a in ${JSONCPP_CXX_SOURCES}; do - objs="${objs} jsoncpp-`cmake_obj ${a}`" - done - fi +if test "x${bootstrap_system_jsoncpp}" = "x"; then + for a in ${JSONCPP_CXX_SOURCES}; do + objs="${objs} jsoncpp-`cmake_obj ${a}`" + done fi libs="" @@ -1799,17 +1796,15 @@ if test "x${bootstrap_system_librhash}" != "x"; then libs="${libs} -lrhash" fi -if test "${cmake_bootstrap_generator}" = "Ninja"; then - jsoncpp_cxx_flags= - if test "x${bootstrap_system_jsoncpp}" = "x"; then - jsoncpp_cxx_flags="${jsoncpp_cxx_flags} `cmake_escape_shell "-I${cmake_source_dir}/Utilities/cmjsoncpp/include"`" - else - if test `which pkg-config`; then - use_jsoncpp_flags="`pkg-config --cflags jsoncpp`" - cmake_cxx_flags="${cmake_cxx_flags} ${use_jsoncpp_flags}" - fi - libs="${libs} -ljsoncpp" +jsoncpp_cxx_flags= +if test "x${bootstrap_system_jsoncpp}" = "x"; then + jsoncpp_cxx_flags="${jsoncpp_cxx_flags} `cmake_escape_shell "-I${cmake_source_dir}/Utilities/cmjsoncpp/include"`" +else + if test `which pkg-config`; then + use_jsoncpp_flags="`pkg-config --cflags jsoncpp`" + cmake_cxx_flags="${cmake_cxx_flags} ${use_jsoncpp_flags}" fi + libs="${libs} -ljsoncpp" fi if test "x${cmake_ansi_cxx_flags}" != "x"; then @@ -1949,13 +1944,11 @@ if test "x${bootstrap_system_librhash}" = "x"; then write_source_rule "c" "rhash-`cmake_obj ${a}`" "${src}" "" done fi -if test "${cmake_bootstrap_generator}" = "Ninja"; then - if test "x${bootstrap_system_jsoncpp}" = "x"; then - for a in ${JSONCPP_CXX_SOURCES}; do - src=`cmake_escape_artifact "${cmake_source_dir}/Utilities/cmjsoncpp/${a}"` - write_source_rule "cxx" "jsoncpp-`cmake_obj ${a}`" "${src}" "${jsoncpp_cxx_flags}" - done - fi +if test "x${bootstrap_system_jsoncpp}" = "x"; then + for a in ${JSONCPP_CXX_SOURCES}; do + src=`cmake_escape_artifact "${cmake_source_dir}/Utilities/cmjsoncpp/${a}"` + write_source_rule "cxx" "jsoncpp-`cmake_obj ${a}`" "${src}" "${jsoncpp_cxx_flags}" + done fi if test "${cmake_bootstrap_generator}" = "Ninja"; then echo " -- cgit v0.12 From 7050ac56a11768c90f55654aa3f63d02bb549243 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 17 May 2023 13:50:32 -0400 Subject: macOS: Add support for linking against .xcframework folders Issue: #21752 --- Help/command/target_link_libraries.rst | 6 + Help/prop_tgt/IMPORTED_LOCATION.rst | 6 + .../dev/xcframework-target-link-libraries.rst | 7 + Source/CMakeLists.txt | 4 + Source/cmComputeLinkInformation.cxx | 88 +++++++++++ Source/cmComputeLinkInformation.h | 5 + Source/cmGeneratorTarget.cxx | 41 +++++ Source/cmGeneratorTarget.h | 2 + Source/cmGlobalXCodeGenerator.cxx | 63 +++++++- Source/cmLocalGenerator.cxx | 39 +++++ Source/cmLocalGenerator.h | 3 + Source/cmPlistParser.cxx | 33 ++++ Source/cmPlistParser.h | 13 ++ Source/cmSystemTools.cxx | 6 + Source/cmSystemTools.h | 3 + Source/cmTarget.cxx | 20 +++ Source/cmXcFramework.cxx | 174 +++++++++++++++++++++ Source/cmXcFramework.h | 44 ++++++ Tests/RunCMake/CMakeLists.txt | 17 ++ Tests/RunCMake/XcFramework/CMakeLists.txt | 3 + Tests/RunCMake/XcFramework/RunCMakeTest.cmake | 83 ++++++++++ .../create-executable-framework-ios.cmake | 1 + ...reate-executable-framework-link-phase-ios.cmake | 1 + ...ate-executable-framework-link-phase-macos.cmake | 1 + ...eate-executable-framework-link-phase-tvos.cmake | 1 + ...-executable-framework-link-phase-visionos.cmake | 1 + ...e-executable-framework-link-phase-watchos.cmake | 1 + .../create-executable-framework-macos.cmake | 1 + .../create-executable-framework-tvos.cmake | 1 + .../create-executable-framework-visionos.cmake | 1 + .../create-executable-framework-watchos.cmake | 1 + ...ate-executable-incomplete-link-phase-result.txt | 1 + ...ate-executable-incomplete-link-phase-stderr.txt | 11 ++ .../create-executable-incomplete-link-phase.cmake | 1 + .../create-executable-incomplete-result.txt | 1 + .../create-executable-incomplete-stderr.txt | 10 ++ .../XcFramework/create-executable-incomplete.cmake | 1 + .../create-executable-library-ios.cmake | 1 + .../create-executable-library-link-phase-ios.cmake | 1 + ...reate-executable-library-link-phase-macos.cmake | 1 + ...create-executable-library-link-phase-tvos.cmake | 1 + ...te-executable-library-link-phase-visionos.cmake | 1 + ...ate-executable-library-link-phase-watchos.cmake | 1 + .../create-executable-library-macos.cmake | 1 + .../create-executable-library-tvos.cmake | 1 + .../create-executable-library-visionos.cmake | 1 + .../create-executable-library-watchos.cmake | 1 + .../XcFramework/create-executable-link-phase.cmake | 2 + .../create-executable-target-framework-ios.cmake | 1 + ...xecutable-target-framework-link-phase-ios.cmake | 1 + ...cutable-target-framework-link-phase-macos.cmake | 1 + ...ecutable-target-framework-link-phase-tvos.cmake | 1 + ...able-target-framework-link-phase-visionos.cmake | 1 + ...table-target-framework-link-phase-watchos.cmake | 1 + .../create-executable-target-framework-macos.cmake | 1 + .../create-executable-target-framework-tvos.cmake | 1 + ...eate-executable-target-framework-visionos.cmake | 1 + ...reate-executable-target-framework-watchos.cmake | 1 + ...cutable-target-incomplete-link-phase-result.txt | 1 + ...cutable-target-incomplete-link-phase-stderr.txt | 11 ++ ...e-executable-target-incomplete-link-phase.cmake | 1 + .../create-executable-target-incomplete-result.txt | 1 + .../create-executable-target-incomplete-stderr.txt | 10 ++ .../create-executable-target-incomplete.cmake | 1 + .../create-executable-target-library-ios.cmake | 1 + ...-executable-target-library-link-phase-ios.cmake | 1 + ...xecutable-target-library-link-phase-macos.cmake | 1 + ...executable-target-library-link-phase-tvos.cmake | 1 + ...utable-target-library-link-phase-visionos.cmake | 1 + ...cutable-target-library-link-phase-watchos.cmake | 1 + .../create-executable-target-library-macos.cmake | 1 + .../create-executable-target-library-tvos.cmake | 1 + ...create-executable-target-library-visionos.cmake | 1 + .../create-executable-target-library-watchos.cmake | 1 + .../create-executable-target-link-phase.cmake | 2 + .../XcFramework/create-executable-target.cmake | 21 +++ Tests/RunCMake/XcFramework/create-executable.cmake | 18 +++ .../XcFramework/create-framework-ios.cmake | 1 + .../XcFramework/create-framework-macos.cmake | 1 + .../XcFramework/create-framework-tvos.cmake | 1 + .../XcFramework/create-framework-visionos.cmake | 1 + .../XcFramework/create-framework-watchos.cmake | 1 + Tests/RunCMake/XcFramework/create-framework.cmake | 3 + .../XcFramework/create-library-common.cmake | 12 ++ .../RunCMake/XcFramework/create-library-ios.cmake | 1 + .../XcFramework/create-library-macos.cmake | 1 + .../RunCMake/XcFramework/create-library-tvos.cmake | 1 + .../XcFramework/create-library-visionos.cmake | 1 + .../XcFramework/create-library-watchos.cmake | 1 + Tests/RunCMake/XcFramework/create-library.cmake | 1 + Tests/RunCMake/XcFramework/myexe/myexe.c | 7 + .../XcFramework/mylib/include/mylib/mylib.h | 3 + Tests/RunCMake/XcFramework/mylib/mylib.c | 3 + bootstrap | 2 + 94 files changed, 828 insertions(+), 6 deletions(-) create mode 100644 Help/release/dev/xcframework-target-link-libraries.rst create mode 100644 Source/cmPlistParser.cxx create mode 100644 Source/cmPlistParser.h create mode 100644 Source/cmXcFramework.cxx create mode 100644 Source/cmXcFramework.h create mode 100644 Tests/RunCMake/XcFramework/CMakeLists.txt create mode 100644 Tests/RunCMake/XcFramework/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-framework-ios.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-framework-link-phase-ios.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-framework-link-phase-macos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-framework-link-phase-tvos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-framework-link-phase-visionos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-framework-link-phase-watchos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-framework-macos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-framework-tvos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-framework-visionos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-framework-watchos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase-result.txt create mode 100644 Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase-stderr.txt create mode 100644 Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-incomplete-result.txt create mode 100644 Tests/RunCMake/XcFramework/create-executable-incomplete-stderr.txt create mode 100644 Tests/RunCMake/XcFramework/create-executable-incomplete.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-library-ios.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-library-link-phase-ios.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-library-link-phase-macos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-library-link-phase-tvos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-library-link-phase-visionos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-library-link-phase-watchos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-library-macos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-library-tvos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-library-visionos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-library-watchos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-link-phase.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-framework-ios.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-ios.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-macos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-tvos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-visionos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-watchos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-framework-macos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-framework-tvos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-framework-visionos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-framework-watchos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase-result.txt create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase-stderr.txt create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-incomplete-result.txt create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-incomplete-stderr.txt create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-incomplete.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-library-ios.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-ios.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-macos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-tvos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-visionos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-watchos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-library-macos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-library-tvos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-library-visionos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-library-watchos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target-link-phase.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable-target.cmake create mode 100644 Tests/RunCMake/XcFramework/create-executable.cmake create mode 100644 Tests/RunCMake/XcFramework/create-framework-ios.cmake create mode 100644 Tests/RunCMake/XcFramework/create-framework-macos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-framework-tvos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-framework-visionos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-framework-watchos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-framework.cmake create mode 100644 Tests/RunCMake/XcFramework/create-library-common.cmake create mode 100644 Tests/RunCMake/XcFramework/create-library-ios.cmake create mode 100644 Tests/RunCMake/XcFramework/create-library-macos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-library-tvos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-library-visionos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-library-watchos.cmake create mode 100644 Tests/RunCMake/XcFramework/create-library.cmake create mode 100644 Tests/RunCMake/XcFramework/myexe/myexe.c create mode 100644 Tests/RunCMake/XcFramework/mylib/include/mylib/mylib.h create mode 100644 Tests/RunCMake/XcFramework/mylib/mylib.c diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst index 1d27660..cc6bc0f 100644 --- a/Help/command/target_link_libraries.rst +++ b/Help/command/target_link_libraries.rst @@ -66,6 +66,12 @@ Each ```` may be: :ref:`usage requirement `. This has the same effect as passing the framework directory as an include directory. + .. versionadded:: 3.28 + + The library file may point to a ``.xcframework`` folder on macOS. If it + does, the target will get the selected library's ``Headers`` directory as + a usage requirement. + .. versionadded:: 3.8 On :ref:`Visual Studio Generators` for VS 2010 and above, library files ending in ``.targets`` will be treated as MSBuild targets files and diff --git a/Help/prop_tgt/IMPORTED_LOCATION.rst b/Help/prop_tgt/IMPORTED_LOCATION.rst index 50c3658..915085b 100644 --- a/Help/prop_tgt/IMPORTED_LOCATION.rst +++ b/Help/prop_tgt/IMPORTED_LOCATION.rst @@ -20,6 +20,12 @@ non-imported targets. For frameworks on macOS, this may be the location of the framework folder itself. +.. versionadded:: 3.28 + + This may be the location of a ``.xcframework`` folder on macOS. If it is, + any target that links against it will get the selected library's ``Headers`` + directory as a usage requirement. + The ``IMPORTED_LOCATION`` target property may be overridden for a given configuration ```` by the configuration-specific :prop_tgt:`IMPORTED_LOCATION_` target property. Furthermore, diff --git a/Help/release/dev/xcframework-target-link-libraries.rst b/Help/release/dev/xcframework-target-link-libraries.rst new file mode 100644 index 0000000..7edded5 --- /dev/null +++ b/Help/release/dev/xcframework-target-link-libraries.rst @@ -0,0 +1,7 @@ +xcframework-target-link-libraries +--------------------------------- + +* Targets may now link against an ``.xcframework`` folder in + :command:`target_link_libraries`. +* The :prop_tgt:`IMPORTED_LOCATION` property of a target may now be an + ``.xcframework`` folder. diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 708aec7..a067766 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -371,6 +371,8 @@ add_library( cmNewLineStyle.cxx cmOrderDirectories.cxx cmOrderDirectories.h + cmPlistParser.cxx + cmPlistParser.h cmPolicies.h cmPolicies.cxx cmProcessOutput.cxx @@ -451,6 +453,8 @@ add_library( cmWorkerPool.h cmWorkingDirectory.cxx cmWorkingDirectory.h + cmXcFramework.cxx + cmXcFramework.h cmXMLParser.cxx cmXMLParser.h cmXMLSafe.cxx diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index a50ce11..be73fa3 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -29,6 +29,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmValue.h" +#include "cmXcFramework.h" #include "cmake.h" // #define CM_COMPUTE_LINK_INFO_DEBUG @@ -373,6 +374,10 @@ cmComputeLinkInformation::cmComputeLinkInformation( this->LibraryFeatureDescriptors.emplace( "__CMAKE_LINK_FRAMEWORK", LibraryFeatureDescriptor{ "__CMAKE_LINK_FRAMEWORK", "" }); + // To link xcframework using a full path + this->LibraryFeatureDescriptors.emplace( + "__CMAKE_LINK_XCFRAMEWORK", + LibraryFeatureDescriptor{ "__CMAKE_LINK_XCFRAMEWORK", "" }); // Check the platform policy for missing soname case. this->NoSONameUsesPath = @@ -519,6 +524,12 @@ cmComputeLinkInformation::GetFrameworkPathsEmitted() const return this->FrameworkPathsEmitted; } +std::vector const& +cmComputeLinkInformation::GetXcFrameworkHeaderPaths() const +{ + return this->XcFrameworkHeaderPaths; +} + const std::set& cmComputeLinkInformation::GetSharedLibrariesLinked() const { @@ -1159,6 +1170,13 @@ void cmComputeLinkInformation::AddItem(LinkEntry const& entry) } else { this->ObjectLibrariesLinked.push_back(entry.Target); } + } else if (this->GlobalGenerator->IsXcode() && + !tgt->GetImportedXcFrameworkPath(config).empty()) { + this->Items.emplace_back( + tgt->GetImportedXcFrameworkPath(config), ItemIsPath::Yes, tgt, + this->FindLibraryFeature(entry.Feature == DEFAULT + ? "__CMAKE_LINK_XCFRAMEWORK" + : entry.Feature)); } else { // Decide whether to use an import library. cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(config) @@ -1198,6 +1216,25 @@ void cmComputeLinkInformation::AddItem(LinkEntry const& entry) this->AddRuntimeDLL(tgt); } } + + auto xcFrameworkPath = tgt->GetImportedXcFrameworkPath(config); + if (!xcFrameworkPath.empty()) { + auto plist = cmParseXcFrameworkPlist(xcFrameworkPath, *this->Makefile, + item.Backtrace); + if (!plist) { + return; + } + if (auto const* library = + plist->SelectSuitableLibrary(*this->Makefile, item.Backtrace)) { + if (!library->HeadersPath.empty()) { + this->AddXcFrameworkHeaderPath(cmStrCat(xcFrameworkPath, '/', + library->LibraryIdentifier, + '/', library->HeadersPath)); + } + } else { + return; + } + } } else { // This is not a CMake target. Use the name given. if (cmHasSuffix(entry.Feature, "FRAMEWORK"_s) || @@ -1206,6 +1243,12 @@ void cmComputeLinkInformation::AddItem(LinkEntry const& entry) this->Target->IsApple())) { // This is a framework. this->AddFrameworkItem(entry); + } else if (cmHasSuffix(entry.Feature, "XCFRAMEWORK"_s) || + (entry.Feature == DEFAULT && + cmSystemTools::IsPathToXcFramework(item.Value) && + this->Target->IsApple())) { + // This is a framework. + this->AddXcFrameworkItem(entry); } else if (cmSystemTools::FileIsFullPath(item.Value)) { if (cmSystemTools::FileIsDirectory(item.Value)) { // This is a directory. @@ -1945,6 +1988,46 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry) } } +void cmComputeLinkInformation::AddXcFrameworkItem(LinkEntry const& entry) +{ + auto plist = cmParseXcFrameworkPlist(entry.Item.Value, *this->Makefile, + entry.Item.Backtrace); + if (!plist) { + return; + } + + if (auto const* lib = + plist->SelectSuitableLibrary(*this->Makefile, entry.Item.Backtrace)) { + if (this->GlobalGenerator->IsXcode()) { + this->Items.emplace_back( + entry.Item.Value, ItemIsPath::Yes, nullptr, + this->FindLibraryFeature(entry.Feature == DEFAULT + ? "__CMAKE_LINK_XCFRAMEWORK" + : entry.Feature)); + } else { + auto libraryPath = cmStrCat( + entry.Item.Value, '/', lib->LibraryIdentifier, '/', lib->LibraryPath); + LinkEntry libraryEntry( + BT(libraryPath, entry.Item.Backtrace), entry.Target); + + if (cmSystemTools::IsPathToFramework(libraryPath) && + this->Target->IsApple()) { + // This is a framework. + this->AddFrameworkItem(libraryEntry); + } else { + this->Depends.push_back(libraryPath); + this->AddFullItem(libraryEntry); + this->AddLibraryRuntimeInfo(libraryPath); + if (!lib->HeadersPath.empty()) { + this->AddXcFrameworkHeaderPath(cmStrCat(entry.Item.Value, '/', + lib->LibraryIdentifier, '/', + lib->HeadersPath)); + } + } + } + } +} + void cmComputeLinkInformation::DropDirectoryItem(BT const& item) { // A full path to a directory was found as a link item. Warn the @@ -1982,6 +2065,11 @@ void cmComputeLinkInformation::AddFrameworkPath(std::string const& p) } } +void cmComputeLinkInformation::AddXcFrameworkHeaderPath(std::string const& p) +{ + this->XcFrameworkHeaderPaths.push_back(p); +} + bool cmComputeLinkInformation::CheckSharedLibNoSOName(LinkEntry const& entry) { // This platform will use the path to a library as its soname if the diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 8393a29..e75423f 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -88,6 +88,7 @@ public: std::vector const& GetDepends() const; std::vector const& GetFrameworkPaths() const; std::set const& GetFrameworkPathsEmitted() const; + std::vector const& GetXcFrameworkHeaderPaths() const; std::string GetLinkLanguage() const { return this->LinkLanguage; } std::vector const& GetRuntimeSearchPath() const; std::string const& GetRuntimeFlag() const { return this->RuntimeFlag; } @@ -132,6 +133,7 @@ private: std::vector Directories; std::vector Depends; std::vector FrameworkPaths; + std::vector XcFrameworkHeaderPaths; std::vector RuntimeSearchPath; std::set SharedLibrariesLinked; std::vector ObjectLibrariesLinked; @@ -204,6 +206,7 @@ private: bool CheckImplicitDirItem(LinkEntry const& entry); void AddUserItem(LinkEntry const& entry, bool pathNotKnown); void AddFrameworkItem(LinkEntry const& entry); + void AddXcFrameworkItem(LinkEntry const& entry); void DropDirectoryItem(BT const& item); bool CheckSharedLibNoSOName(LinkEntry const& entry); void AddSharedLibNoSOName(LinkEntry const& entry); @@ -214,6 +217,8 @@ private: void AddFrameworkPath(std::string const& p); std::set FrameworkPathsEmitted; + void AddXcFrameworkHeaderPath(std::string const& p); + // Linker search path computation. std::unique_ptr OrderLinkerSearchPath; bool FinishLinkerSearchDirectories(); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 42be082..cff1574 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -8874,6 +8874,47 @@ std::string cmGeneratorTarget::GenerateHeaderSetVerificationFile( return filename; } +std::string cmGeneratorTarget::GetImportedXcFrameworkPath( + const std::string& config) const +{ + if (!(this->IsApple() && this->IsImported() && + (this->GetType() == cmStateEnums::SHARED_LIBRARY || + this->GetType() == cmStateEnums::STATIC_LIBRARY || + this->GetType() == cmStateEnums::UNKNOWN_LIBRARY))) { + return {}; + } + + std::string desiredConfig = config; + if (config.empty()) { + desiredConfig = "NOCONFIG"; + } + + std::string result; + + cmValue loc = nullptr; + cmValue imp = nullptr; + std::string suffix; + + if (this->Target->GetMappedConfig(desiredConfig, loc, imp, suffix)) { + if (loc) { + result = *loc; + } else { + std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix); + if (cmValue configLocation = this->GetProperty(impProp)) { + result = *configLocation; + } else if (cmValue location = this->GetProperty("IMPORTED_LOCATION")) { + result = *location; + } + } + + if (cmSystemTools::IsPathToXcFramework(result)) { + return result; + } + } + + return {}; +} + bool cmGeneratorTarget::HaveFortranSources(std::string const& config) const { auto sources = cmGeneratorTarget::GetSourceFiles(config); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index a03513d..753d6f3 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -926,6 +926,8 @@ public: cmSourceFile& source, const std::string& dir, cm::optional>& languages) const; + std::string GetImportedXcFrameworkPath(const std::string& config) const; + private: void AddSourceCommon(const std::string& src, bool before = false); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 0472631..247d4fc 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -53,6 +53,7 @@ #include "cmXCodeObject.h" #include "cmXCodeScheme.h" #include "cmXMLWriter.h" +#include "cmXcFramework.h" #include "cmake.h" #if !defined(CMAKE_BOOTSTRAP) && defined(__APPLE__) @@ -1061,12 +1062,14 @@ bool IsLinkPhaseLibraryExtension(const std::string& fileExt) { // Empty file extension is a special case for paths to framework's // internal binary which could be MyFw.framework/Versions/*/MyFw - return (fileExt == ".framework" || fileExt == ".a" || fileExt == ".o" || - fileExt == ".dylib" || fileExt == ".tbd" || fileExt.empty()); + return (fileExt == ".framework" || fileExt == ".xcframework" || + fileExt == ".a" || fileExt == ".o" || fileExt == ".dylib" || + fileExt == ".tbd" || fileExt.empty()); } bool IsLibraryType(const std::string& fileType) { - return (fileType == "wrapper.framework" || fileType == "archive.ar" || + return (fileType == "wrapper.framework" || + fileType == "wrapper.xcframework" || fileType == "archive.ar" || fileType == "compiled.mach-o.objfile" || fileType == "compiled.mach-o.dylib" || fileType == "compiled.mach-o.executable" || @@ -1079,6 +1082,9 @@ std::string GetDirectoryValueFromFileExtension(const std::string& dirExt) if (ext == "framework") { return "wrapper.framework"; } + if (ext == "xcframework") { + return "wrapper.xcframework"; + } if (ext == "xcassets") { return "folder.assetcatalog"; } @@ -3607,6 +3613,8 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) bool canUseLinkPhase = !libItem.HasFeature() || libItem.GetFeatureName() == "__CMAKE_LINK_FRAMEWORK"_s || libItem.GetFeatureName() == "FRAMEWORK"_s || + libItem.GetFeatureName() == "__CMAKE_LINK_XCFRAMEWORK"_s || + libItem.GetFeatureName() == "XCFRAMEWORK"_s || libItem.GetFeatureName() == "WEAK_FRAMEWORK"_s || libItem.GetFeatureName() == "WEAK_LIBRARY"_s; if (canUseLinkPhase) { @@ -3917,12 +3925,14 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) if (cmSystemTools::FileIsFullPath(cleanPath)) { cleanPath = cmSystemTools::CollapseFullPath(cleanPath); } - bool isFramework = + bool isXcFramework = + cmHasSuffix(libName.GetFeatureName(), "XCFRAMEWORK"_s); + bool isFramework = !isXcFramework && cmHasSuffix(libName.GetFeatureName(), "FRAMEWORK"_s); if (isFramework) { const auto fwDescriptor = this->SplitFrameworkPath( cleanPath, cmGlobalGenerator::FrameworkFormat::Extended); - if (!fwDescriptor->Directory.empty() && + if (isFramework && !fwDescriptor->Directory.empty() && emitted.insert(fwDescriptor->Directory).second) { // This is a search path we had not added before and it isn't // an implicit search path, so we need it @@ -3940,13 +3950,54 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) fwDescriptor->GetLinkName())) .Value); } + } else if (isXcFramework) { + auto plist = cmParseXcFrameworkPlist( + cleanPath, *this->Makefiles.front(), libName.Value.Backtrace); + if (!plist) { + return; + } + if (auto const* library = plist->SelectSuitableLibrary( + *this->Makefiles.front(), libName.Value.Backtrace)) { + auto libraryPath = + cmStrCat(cleanPath, '/', library->LibraryIdentifier, '/', + library->LibraryPath); + if (auto const fwDescriptor = this->SplitFrameworkPath( + libraryPath, + cmGlobalGenerator::FrameworkFormat::Relaxed)) { + if (!fwDescriptor->Directory.empty() && + emitted.insert(fwDescriptor->Directory).second) { + // This is a search path we had not added before and it + // isn't an implicit search path, so we need it + fwSearchPaths.Add( + this->XCodeEscapePath(fwDescriptor->Directory)); + } + libPaths.Add(cmStrCat( + "-framework ", + this->XCodeEscapePath(fwDescriptor->GetLinkName()))); + } else { + libPaths.Add( + libName.GetFormattedItem(this->XCodeEscapePath(libraryPath)) + .Value); + if (!library->HeadersPath.empty()) { + this->AppendBuildSettingAttribute( + target, "HEADER_SEARCH_PATHS", + this->CreateString(this->XCodeEscapePath( + cmStrCat(cleanPath, '/', library->LibraryIdentifier, '/', + library->HeadersPath))), + configName); + } + } + } else { + return; + } } else { libPaths.Add( libName.GetFormattedItem(this->XCodeEscapePath(cleanPath)) .Value); } if ((!libName.Target || libName.Target->IsImported()) && - (isFramework || IsLinkPhaseLibraryExtension(cleanPath))) { + (isFramework || isXcFramework || + IsLinkPhaseLibraryExtension(cleanPath))) { // Create file reference for embedding auto it = this->ExternalLibRefs.find(cleanPath); if (it == this->ExternalLibRefs.end()) { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index cf1eb96..acefedc 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1659,6 +1659,8 @@ std::vector> cmLocalGenerator::GetTargetCompileFlags( this->AppendFlags(compileFlags, mf->GetDefineFlags()); this->AppendFlags(compileFlags, this->GetFrameworkFlags(lang, config, target)); + this->AppendFlags(compileFlags, + this->GetXcFrameworkFlags(lang, config, target)); if (!compileFlags.empty()) { flags.emplace_back(std::move(compileFlags)); @@ -1724,6 +1726,43 @@ std::string cmLocalGenerator::GetFrameworkFlags(std::string const& lang, return flags; } +std::string cmLocalGenerator::GetXcFrameworkFlags(std::string const& lang, + std::string const& config, + cmGeneratorTarget* target) +{ + cmLocalGenerator* lg = target->GetLocalGenerator(); + cmMakefile* mf = lg->GetMakefile(); + + if (!target->IsApple()) { + return std::string(); + } + + cmValue includeSearchFlag = + mf->GetDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_", lang)); + cmValue sysIncludeSearchFlag = + mf->GetDefinition(cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", lang)); + + if (!includeSearchFlag && !sysIncludeSearchFlag) { + return std::string{}; + } + + std::string flags; + if (cmComputeLinkInformation* cli = target->GetLinkInformation(config)) { + std::vector const& paths = cli->GetXcFrameworkHeaderPaths(); + for (std::string const& path : paths) { + if (sysIncludeSearchFlag && + target->IsSystemIncludeDirectory(path, config, lang)) { + flags += *sysIncludeSearchFlag; + } else { + flags += *includeSearchFlag; + } + flags += lg->ConvertToOutputFormat(path, cmOutputConverter::SHELL); + flags += " "; + } + } + return flags; +} + void cmLocalGenerator::GetTargetDefines(cmGeneratorTarget const* target, std::string const& config, std::string const& lang, diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index c811408..7734cbe 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -520,6 +520,9 @@ public: std::string GetFrameworkFlags(std::string const& l, std::string const& config, cmGeneratorTarget* target); + std::string GetXcFrameworkFlags(std::string const& l, + std::string const& config, + cmGeneratorTarget* target); virtual std::string GetTargetFortranFlags(cmGeneratorTarget const* target, std::string const& config); diff --git a/Source/cmPlistParser.cxx b/Source/cmPlistParser.cxx new file mode 100644 index 0000000..ce3c171 --- /dev/null +++ b/Source/cmPlistParser.cxx @@ -0,0 +1,33 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmPlistParser.h" + +#include +#include + +#include "cmUVProcessChain.h" +#include "cmUVStream.h" + +cm::optional cmParsePlist(const std::string& filename) +{ + cmUVProcessChainBuilder builder; + builder.AddCommand( + { "/usr/bin/plutil", "-convert", "json", "-o", "-", filename }); + builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT); + + auto chain = builder.Start(); + chain.Wait(); + + auto const& status = chain.GetStatus(0); + if (status.ExitStatus != 0) { + return cm::nullopt; + } + + Json::Reader reader; + Json::Value value; + cmUVPipeIStream outputStream(chain.GetLoop(), chain.OutputStream()); + if (!reader.parse(outputStream, value)) { + return cm::nullopt; + } + return cm::optional(value); +} diff --git a/Source/cmPlistParser.h b/Source/cmPlistParser.h new file mode 100644 index 0000000..2ace254 --- /dev/null +++ b/Source/cmPlistParser.h @@ -0,0 +1,13 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include + +#include + +namespace Json { +class Value; +} + +cm::optional cmParsePlist(const std::string& filename); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 1fb0079..f014de9 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1900,6 +1900,12 @@ bool cmSystemTools::IsPathToFramework(const std::string& path) cmHasLiteralSuffix(path, ".framework")); } +bool cmSystemTools::IsPathToXcFramework(const std::string& path) +{ + return (cmSystemTools::FileIsFullPath(path) && + cmHasLiteralSuffix(path, ".xcframework")); +} + bool cmSystemTools::IsPathToMacOSSharedLibrary(const std::string& path) { return (cmSystemTools::FileIsFullPath(path) && diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 7d55d4b..6592f84 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -111,6 +111,9 @@ public: //! Return true if the path is a framework static bool IsPathToFramework(const std::string& path); + //! Return true if the path is a xcframework + static bool IsPathToXcFramework(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); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 1281bc6..76a14b8 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -40,6 +40,7 @@ #include "cmSystemTools.h" #include "cmTargetPropertyComputer.h" #include "cmValue.h" +#include "cmXcFramework.h" #include "cmake.h" template <> @@ -2800,6 +2801,25 @@ std::string cmTarget::ImportedGetFullPath( } } } + if (this->IsApple() && + (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY || + this->impl->TargetType == cmStateEnums::STATIC_LIBRARY || + this->impl->TargetType == cmStateEnums::UNKNOWN_LIBRARY) && + cmSystemTools::IsPathToXcFramework(result)) { + auto plist = cmParseXcFrameworkPlist(result, *this->impl->Makefile, + this->impl->Backtrace); + if (!plist) { + return ""; + } + auto const* library = plist->SelectSuitableLibrary( + *this->impl->Makefile, this->impl->Backtrace); + if (library) { + result = cmStrCat(result, '/', library->LibraryIdentifier, '/', + library->LibraryPath); + } else { + return ""; + } + } break; case cmStateEnums::ImportLibraryArtifact: diff --git a/Source/cmXcFramework.cxx b/Source/cmXcFramework.cxx new file mode 100644 index 0000000..c91e7f2 --- /dev/null +++ b/Source/cmXcFramework.cxx @@ -0,0 +1,174 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmXcFramework.h" + +#include +#include + +#include + +#include + +#include "cmJSONHelpers.h" +#include "cmJSONState.h" +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmPlistParser.h" +#include "cmStringAlgorithms.h" +#include "cmake.h" + +namespace { +struct PlistMetadata +{ + std::string CFBundlePackageType; + std::string XCFrameworkFormatVersion; +}; + +auto const PlistMetadataHelper = + cmJSONHelperBuilder::Object{} + .Bind("CFBundlePackageType"_s, &PlistMetadata::CFBundlePackageType, + cmJSONHelperBuilder::String()) + .Bind("XCFrameworkFormatVersion"_s, + &PlistMetadata::XCFrameworkFormatVersion, + cmJSONHelperBuilder::String()); + +bool PlistSupportedPlatformHelper( + cmXcFrameworkPlistSupportedPlatform& platform, const Json::Value* value, + cmJSONState* /*state*/) +{ + if (!value) { + return false; + } + + if (!value->isString()) { + return false; + } + + if (value->asString() == "macos") { + platform = cmXcFrameworkPlistSupportedPlatform::macOS; + return true; + } + if (value->asString() == "ios") { + platform = cmXcFrameworkPlistSupportedPlatform::iOS; + return true; + } + if (value->asString() == "tvos") { + platform = cmXcFrameworkPlistSupportedPlatform::tvOS; + return true; + } + if (value->asString() == "watchos") { + platform = cmXcFrameworkPlistSupportedPlatform::watchOS; + return true; + } + if (value->asString() == "xros") { + platform = cmXcFrameworkPlistSupportedPlatform::visionOS; + return true; + } + + return false; +} + +auto const PlistLibraryHelper = + cmJSONHelperBuilder::Object{} + .Bind("LibraryIdentifier"_s, &cmXcFrameworkPlistLibrary::LibraryIdentifier, + cmJSONHelperBuilder::String()) + .Bind("LibraryPath"_s, &cmXcFrameworkPlistLibrary::LibraryPath, + cmJSONHelperBuilder::String()) + .Bind("HeadersPath"_s, &cmXcFrameworkPlistLibrary::HeadersPath, + cmJSONHelperBuilder::String(), false) + .Bind("SupportedArchitectures"_s, + &cmXcFrameworkPlistLibrary::SupportedArchitectures, + cmJSONHelperBuilder::Vector( + JsonErrors::EXPECTED_TYPE("array"), cmJSONHelperBuilder::String())) + .Bind("SupportedPlatform"_s, &cmXcFrameworkPlistLibrary::SupportedPlatform, + PlistSupportedPlatformHelper); + +auto const PlistHelper = + cmJSONHelperBuilder::Object{}.Bind( + "AvailableLibraries"_s, &cmXcFrameworkPlist::AvailableLibraries, + cmJSONHelperBuilder::Vector( + JsonErrors::EXPECTED_TYPE("array"), PlistLibraryHelper)); +} + +cm::optional cmParseXcFrameworkPlist( + const std::string& xcframeworkPath, const cmMakefile& mf, + const cmListFileBacktrace& bt) +{ + std::string plistPath = cmStrCat(xcframeworkPath, "/Info.plist"); + + auto value = cmParsePlist(plistPath); + if (!value) { + mf.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Unable to parse plist file:\n ", plistPath), bt); + return cm::nullopt; + } + + cmJSONState state; + + PlistMetadata metadata; + if (!PlistMetadataHelper(metadata, &*value, &state)) { + mf.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Invalid xcframework .plist file:\n ", plistPath), bt); + return cm::nullopt; + } + if (metadata.CFBundlePackageType != "XFWK" || + metadata.XCFrameworkFormatVersion != "1.0") { + mf.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Expected:\n ", plistPath, + "\nto have CFBundlePackageType \"XFWK\" and " + "XCFrameworkFormatVersion \"1.0\""), + bt); + return cm::nullopt; + } + + cmXcFrameworkPlist plist; + if (!PlistHelper(plist, &*value, &state)) { + mf.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Invalid xcframework .plist file:\n ", plistPath), bt); + return cm::nullopt; + } + plist.Path = plistPath; + return cm::optional(plist); +} + +const cmXcFrameworkPlistLibrary* cmXcFrameworkPlist::SelectSuitableLibrary( + const cmMakefile& mf, const cmListFileBacktrace& bt) const +{ + auto systemName = mf.GetSafeDefinition("CMAKE_SYSTEM_NAME"); + + for (auto const& lib : this->AvailableLibraries) { + std::string supportedSystemName; + switch (lib.SupportedPlatform) { + case cmXcFrameworkPlistSupportedPlatform::macOS: + supportedSystemName = "Darwin"; + break; + case cmXcFrameworkPlistSupportedPlatform::iOS: + supportedSystemName = "iOS"; + break; + case cmXcFrameworkPlistSupportedPlatform::tvOS: + supportedSystemName = "tvOS"; + break; + case cmXcFrameworkPlistSupportedPlatform::watchOS: + supportedSystemName = "watchOS"; + break; + case cmXcFrameworkPlistSupportedPlatform::visionOS: + supportedSystemName = "visionOS"; + break; + } + + if (systemName == supportedSystemName) { + return &lib; + } + } + + mf.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Unable to find suitable library in:\n ", this->Path, + "\nfor system name \"", systemName, '"'), + bt); + return nullptr; +} diff --git a/Source/cmXcFramework.h b/Source/cmXcFramework.h new file mode 100644 index 0000000..c35df11 --- /dev/null +++ b/Source/cmXcFramework.h @@ -0,0 +1,44 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include +#include + +#include + +#include "cmListFileCache.h" + +class cmMakefile; + +enum class cmXcFrameworkPlistSupportedPlatform +{ + macOS, + iOS, + tvOS, + watchOS, + visionOS, +}; + +struct cmXcFrameworkPlistLibrary +{ + std::string LibraryIdentifier; + std::string LibraryPath; + std::string HeadersPath; + std::vector SupportedArchitectures; + cmXcFrameworkPlistSupportedPlatform SupportedPlatform; +}; + +struct cmXcFrameworkPlist +{ + std::string Path; + std::vector AvailableLibraries; + + const cmXcFrameworkPlistLibrary* SelectSuitableLibrary( + const cmMakefile& mf, + const cmListFileBacktrace& bt = cmListFileBacktrace{}) const; +}; + +cm::optional cmParseXcFrameworkPlist( + const std::string& xcframeworkPath, const cmMakefile& mf, + const cmListFileBacktrace& bt = cmListFileBacktrace{}); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index d20af29..280b81e 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -703,6 +703,23 @@ endif() if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.0) add_RunCMake_test(Framework) + if(NOT DEFINED CMake_TEST_XcFramework) + set(CMake_TEST_XcFramework ON) + endif() + if(CMake_TEST_XcFramework AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 11.0) + set(XcFramework_ARGS -DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION}) + add_RunCMake_test(XcFramework) + + # This test can take a very long time due to lots of combinations. + # Use a long default timeout and provide an option to customize it. + if(NOT DEFINED CMake_TEST_XcFramework_TIMEOUT) + set(CMake_TEST_XcFramework_TIMEOUT 3000) + endif() + set_tests_properties(RunCMake.XcFramework PROPERTIES + TIMEOUT "${CMake_TEST_XcFramework_TIMEOUT}" + RUN_SERIAL TRUE + ) + endif() endif() add_RunCMake_test(File_Archive) diff --git a/Tests/RunCMake/XcFramework/CMakeLists.txt b/Tests/RunCMake/XcFramework/CMakeLists.txt new file mode 100644 index 0000000..54a4d62 --- /dev/null +++ b/Tests/RunCMake/XcFramework/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.26) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/XcFramework/RunCMakeTest.cmake b/Tests/RunCMake/XcFramework/RunCMakeTest.cmake new file mode 100644 index 0000000..dcfaad4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/RunCMakeTest.cmake @@ -0,0 +1,83 @@ +include(RunCMake) + +function(create_library type platform system_name archs) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/create-${type}-${platform}-build) + run_cmake_with_options(create-${type}-${platform} -DCMAKE_SYSTEM_NAME=${system_name} -DCMAKE_OSX_ARCHITECTURES=${archs} -DCMAKE_INSTALL_PREFIX=${RunCMake_TEST_BINARY_DIR}/install) + + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(create-${type}-${platform}-build ${CMAKE_COMMAND} --build . --config Release) + run_cmake_command(create-${type}-${platform}-install ${CMAKE_COMMAND} --install . --config Release) +endfunction() + +function(create_libraries type) + create_library(${type} macos Darwin "${macos_archs_2}") + create_library(${type} ios iOS "arm64") + create_library(${type} tvos tvOS "arm64") + create_library(${type} watchos watchOS "armv7k\\\\;arm64_32") + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 15) + create_library(${type} visionos visionOS "arm64") + endif() +endfunction() + +function(create_xcframework name type platforms) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/create-xcframework-${name}-build) + set(args) + foreach(platform IN LISTS platforms) + if(type STREQUAL "framework") + list(APPEND args -framework ${RunCMake_BINARY_DIR}/create-${type}-${platform}-build/install/lib/mylib.framework) + else() + list(APPEND args -library ${RunCMake_BINARY_DIR}/create-${type}-${platform}-build/install/lib/libmylib.a -headers ${RunCMake_SOURCE_DIR}/mylib/include) + endif() + endforeach() + run_cmake_command(create-xcframework-${name} xcodebuild -create-xcframework ${args} -output ${RunCMake_TEST_BINARY_DIR}/mylib.xcframework) +endfunction() + +function(create_executable name xcfname system_name archs) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/create-executable-${name}-build) + run_cmake_with_options(create-executable-${name} -DCMAKE_SYSTEM_NAME=${system_name} -DCMAKE_OSX_ARCHITECTURES=${archs} -DMYLIB_LIBRARY=${RunCMake_BINARY_DIR}/create-xcframework-${xcfname}-build/mylib.xcframework) + + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(create-executable-${name}-build ${CMAKE_COMMAND} --build . --config Release) +endfunction() + +function(create_executables name type) + create_executable(${name}-macos ${type} Darwin "${macos_archs_2}") + create_executable(${name}-ios ${type} iOS "arm64") + create_executable(${name}-tvos ${type} tvOS "arm64") + create_executable(${name}-watchos ${type} watchOS "armv7k\\\\;arm64_32") + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 15) + create_executable(${name}-visionos ${type} visionOS "arm64") + endif() +endfunction() + +set(xcframework_platforms macos ios tvos watchos) +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 15) + list(APPEND xcframework_platforms visionos) +endif() +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12) + set(macos_archs_1 "x86_64\\;arm64") + set(macos_archs_2 "x86_64\\\\;arm64") +else() + set(macos_archs_1 "x86_64") + set(macos_archs_2 "x86_64") +endif() + +create_libraries(library) +create_libraries(framework) +create_xcframework(library library "${xcframework_platforms}") +create_xcframework(framework framework "${xcframework_platforms}") +create_xcframework(incomplete framework "tvos;watchos") +create_executables(library library) +create_executables(framework framework) +run_cmake_with_options(create-executable-incomplete -DCMAKE_SYSTEM_NAME=Darwin "-DCMAKE_OSX_ARCHITECTURES=${macos_archs_1}" -DMYLIB_LIBRARY=${RunCMake_BINARY_DIR}/create-xcframework-incomplete-build/mylib.xcframework) +create_executables(target-library library) +create_executables(target-framework framework) +run_cmake_with_options(create-executable-target-incomplete -DCMAKE_SYSTEM_NAME=Darwin "-DCMAKE_OSX_ARCHITECTURES=${macos_archs_1}" -DMYLIB_LIBRARY=${RunCMake_BINARY_DIR}/create-xcframework-incomplete-build/mylib.xcframework) +if(RunCMake_GENERATOR STREQUAL "Xcode" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12) + create_executables(library-link-phase library) + create_executables(framework-link-phase framework) + run_cmake_with_options(create-executable-incomplete-link-phase -DCMAKE_SYSTEM_NAME=Darwin "-DCMAKE_OSX_ARCHITECTURES=${macos_archs_1}" -DMYLIB_LIBRARY=${RunCMake_BINARY_DIR}/create-xcframework-incomplete-build/mylib.xcframework) + create_executables(target-library-link-phase library) + create_executables(target-framework-link-phase framework) + run_cmake_with_options(create-executable-target-incomplete-link-phase -DCMAKE_SYSTEM_NAME=Darwin "-DCMAKE_OSX_ARCHITECTURES=${macos_archs_1}" -DMYLIB_LIBRARY=${RunCMake_BINARY_DIR}/create-xcframework-incomplete-build/mylib.xcframework) +endif() diff --git a/Tests/RunCMake/XcFramework/create-executable-framework-ios.cmake b/Tests/RunCMake/XcFramework/create-executable-framework-ios.cmake new file mode 100644 index 0000000..760d9d4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-framework-ios.cmake @@ -0,0 +1 @@ +include(create-executable.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-ios.cmake b/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-ios.cmake new file mode 100644 index 0000000..2888c85 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-ios.cmake @@ -0,0 +1 @@ +include(create-executable-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-macos.cmake b/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-macos.cmake new file mode 100644 index 0000000..2888c85 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-macos.cmake @@ -0,0 +1 @@ +include(create-executable-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-tvos.cmake b/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-tvos.cmake new file mode 100644 index 0000000..2888c85 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-tvos.cmake @@ -0,0 +1 @@ +include(create-executable-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-visionos.cmake b/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-visionos.cmake new file mode 100644 index 0000000..2888c85 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-visionos.cmake @@ -0,0 +1 @@ +include(create-executable-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-watchos.cmake b/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-watchos.cmake new file mode 100644 index 0000000..2888c85 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-framework-link-phase-watchos.cmake @@ -0,0 +1 @@ +include(create-executable-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-framework-macos.cmake b/Tests/RunCMake/XcFramework/create-executable-framework-macos.cmake new file mode 100644 index 0000000..760d9d4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-framework-macos.cmake @@ -0,0 +1 @@ +include(create-executable.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-framework-tvos.cmake b/Tests/RunCMake/XcFramework/create-executable-framework-tvos.cmake new file mode 100644 index 0000000..760d9d4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-framework-tvos.cmake @@ -0,0 +1 @@ +include(create-executable.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-framework-visionos.cmake b/Tests/RunCMake/XcFramework/create-executable-framework-visionos.cmake new file mode 100644 index 0000000..760d9d4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-framework-visionos.cmake @@ -0,0 +1 @@ +include(create-executable.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-framework-watchos.cmake b/Tests/RunCMake/XcFramework/create-executable-framework-watchos.cmake new file mode 100644 index 0000000..760d9d4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-framework-watchos.cmake @@ -0,0 +1 @@ +include(create-executable.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase-result.txt b/Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase-stderr.txt b/Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase-stderr.txt new file mode 100644 index 0000000..5b43e19 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase-stderr.txt @@ -0,0 +1,11 @@ +CMake Error at create-executable\.cmake:[0-9]+ \(target_link_libraries\): + Unable to find suitable library in: + + [^ +]*/Tests/RunCMake/XcFramework/create-xcframework-incomplete-build/mylib\.xcframework/Info\.plist + + for system name "Darwin" +Call Stack \(most recent call first\): + create-executable-link-phase\.cmake:[0-9]+ \(include\) + create-executable-incomplete-link-phase\.cmake:[0-9]+ \(include\) + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase.cmake b/Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase.cmake new file mode 100644 index 0000000..2888c85 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-incomplete-link-phase.cmake @@ -0,0 +1 @@ +include(create-executable-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-incomplete-result.txt b/Tests/RunCMake/XcFramework/create-executable-incomplete-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-incomplete-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/XcFramework/create-executable-incomplete-stderr.txt b/Tests/RunCMake/XcFramework/create-executable-incomplete-stderr.txt new file mode 100644 index 0000000..66b7d62 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-incomplete-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at create-executable\.cmake:[0-9]+ \(target_link_libraries\): + Unable to find suitable library in: + + [^ +]*/Tests/RunCMake/XcFramework/create-xcframework-incomplete-build/mylib\.xcframework/Info\.plist + + for system name "Darwin" +Call Stack \(most recent call first\): + create-executable-incomplete\.cmake:[0-9]+ \(include\) + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/XcFramework/create-executable-incomplete.cmake b/Tests/RunCMake/XcFramework/create-executable-incomplete.cmake new file mode 100644 index 0000000..760d9d4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-incomplete.cmake @@ -0,0 +1 @@ +include(create-executable.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-library-ios.cmake b/Tests/RunCMake/XcFramework/create-executable-library-ios.cmake new file mode 100644 index 0000000..760d9d4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-library-ios.cmake @@ -0,0 +1 @@ +include(create-executable.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-library-link-phase-ios.cmake b/Tests/RunCMake/XcFramework/create-executable-library-link-phase-ios.cmake new file mode 100644 index 0000000..2888c85 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-library-link-phase-ios.cmake @@ -0,0 +1 @@ +include(create-executable-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-library-link-phase-macos.cmake b/Tests/RunCMake/XcFramework/create-executable-library-link-phase-macos.cmake new file mode 100644 index 0000000..2888c85 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-library-link-phase-macos.cmake @@ -0,0 +1 @@ +include(create-executable-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-library-link-phase-tvos.cmake b/Tests/RunCMake/XcFramework/create-executable-library-link-phase-tvos.cmake new file mode 100644 index 0000000..2888c85 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-library-link-phase-tvos.cmake @@ -0,0 +1 @@ +include(create-executable-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-library-link-phase-visionos.cmake b/Tests/RunCMake/XcFramework/create-executable-library-link-phase-visionos.cmake new file mode 100644 index 0000000..2888c85 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-library-link-phase-visionos.cmake @@ -0,0 +1 @@ +include(create-executable-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-library-link-phase-watchos.cmake b/Tests/RunCMake/XcFramework/create-executable-library-link-phase-watchos.cmake new file mode 100644 index 0000000..2888c85 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-library-link-phase-watchos.cmake @@ -0,0 +1 @@ +include(create-executable-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-library-macos.cmake b/Tests/RunCMake/XcFramework/create-executable-library-macos.cmake new file mode 100644 index 0000000..760d9d4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-library-macos.cmake @@ -0,0 +1 @@ +include(create-executable.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-library-tvos.cmake b/Tests/RunCMake/XcFramework/create-executable-library-tvos.cmake new file mode 100644 index 0000000..760d9d4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-library-tvos.cmake @@ -0,0 +1 @@ +include(create-executable.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-library-visionos.cmake b/Tests/RunCMake/XcFramework/create-executable-library-visionos.cmake new file mode 100644 index 0000000..760d9d4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-library-visionos.cmake @@ -0,0 +1 @@ +include(create-executable.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-library-watchos.cmake b/Tests/RunCMake/XcFramework/create-executable-library-watchos.cmake new file mode 100644 index 0000000..760d9d4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-library-watchos.cmake @@ -0,0 +1 @@ +include(create-executable.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-link-phase.cmake b/Tests/RunCMake/XcFramework/create-executable-link-phase.cmake new file mode 100644 index 0000000..9884781 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-link-phase.cmake @@ -0,0 +1,2 @@ +include(create-executable.cmake) +set_property(TARGET myexe PROPERTY XCODE_LINK_BUILD_PHASE_MODE "KNOWN_LOCATION") diff --git a/Tests/RunCMake/XcFramework/create-executable-target-framework-ios.cmake b/Tests/RunCMake/XcFramework/create-executable-target-framework-ios.cmake new file mode 100644 index 0000000..b2e3469 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-framework-ios.cmake @@ -0,0 +1 @@ +include(create-executable-target.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-ios.cmake b/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-ios.cmake new file mode 100644 index 0000000..dfeccb9 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-ios.cmake @@ -0,0 +1 @@ +include(create-executable-target-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-macos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-macos.cmake new file mode 100644 index 0000000..dfeccb9 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-macos.cmake @@ -0,0 +1 @@ +include(create-executable-target-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-tvos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-tvos.cmake new file mode 100644 index 0000000..dfeccb9 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-tvos.cmake @@ -0,0 +1 @@ +include(create-executable-target-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-visionos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-visionos.cmake new file mode 100644 index 0000000..dfeccb9 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-visionos.cmake @@ -0,0 +1 @@ +include(create-executable-target-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-watchos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-watchos.cmake new file mode 100644 index 0000000..dfeccb9 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-framework-link-phase-watchos.cmake @@ -0,0 +1 @@ +include(create-executable-target-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-framework-macos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-framework-macos.cmake new file mode 100644 index 0000000..b2e3469 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-framework-macos.cmake @@ -0,0 +1 @@ +include(create-executable-target.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-framework-tvos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-framework-tvos.cmake new file mode 100644 index 0000000..b2e3469 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-framework-tvos.cmake @@ -0,0 +1 @@ +include(create-executable-target.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-framework-visionos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-framework-visionos.cmake new file mode 100644 index 0000000..b2e3469 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-framework-visionos.cmake @@ -0,0 +1 @@ +include(create-executable-target.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-framework-watchos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-framework-watchos.cmake new file mode 100644 index 0000000..b2e3469 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-framework-watchos.cmake @@ -0,0 +1 @@ +include(create-executable-target.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase-result.txt b/Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase-stderr.txt b/Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase-stderr.txt new file mode 100644 index 0000000..1308933 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase-stderr.txt @@ -0,0 +1,11 @@ +CMake Error at create-executable-target\.cmake:[0-9]+ \(target_link_libraries\): + Unable to find suitable library in: + + [^ +]*/Tests/RunCMake/XcFramework/create-xcframework-incomplete-build/mylib\.xcframework/Info\.plist + + for system name "Darwin" +Call Stack \(most recent call first\): + create-executable-target-link-phase\.cmake:[0-9]+ \(include\) + create-executable-target-incomplete-link-phase\.cmake:[0-9]+ \(include\) + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase.cmake b/Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase.cmake new file mode 100644 index 0000000..dfeccb9 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-incomplete-link-phase.cmake @@ -0,0 +1 @@ +include(create-executable-target-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-incomplete-result.txt b/Tests/RunCMake/XcFramework/create-executable-target-incomplete-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-incomplete-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/XcFramework/create-executable-target-incomplete-stderr.txt b/Tests/RunCMake/XcFramework/create-executable-target-incomplete-stderr.txt new file mode 100644 index 0000000..716b17d --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-incomplete-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at create-executable-target\.cmake:[0-9]+ \(target_link_libraries\): + Unable to find suitable library in: + + [^ +]*/Tests/RunCMake/XcFramework/create-xcframework-incomplete-build/mylib\.xcframework/Info\.plist + + for system name "Darwin" +Call Stack \(most recent call first\): + create-executable-target-incomplete\.cmake:[0-9]+ \(include\) + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-incomplete.cmake b/Tests/RunCMake/XcFramework/create-executable-target-incomplete.cmake new file mode 100644 index 0000000..b2e3469 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-incomplete.cmake @@ -0,0 +1 @@ +include(create-executable-target.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-library-ios.cmake b/Tests/RunCMake/XcFramework/create-executable-target-library-ios.cmake new file mode 100644 index 0000000..b2e3469 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-library-ios.cmake @@ -0,0 +1 @@ +include(create-executable-target.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-ios.cmake b/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-ios.cmake new file mode 100644 index 0000000..dfeccb9 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-ios.cmake @@ -0,0 +1 @@ +include(create-executable-target-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-macos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-macos.cmake new file mode 100644 index 0000000..dfeccb9 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-macos.cmake @@ -0,0 +1 @@ +include(create-executable-target-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-tvos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-tvos.cmake new file mode 100644 index 0000000..dfeccb9 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-tvos.cmake @@ -0,0 +1 @@ +include(create-executable-target-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-visionos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-visionos.cmake new file mode 100644 index 0000000..dfeccb9 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-visionos.cmake @@ -0,0 +1 @@ +include(create-executable-target-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-watchos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-watchos.cmake new file mode 100644 index 0000000..dfeccb9 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-library-link-phase-watchos.cmake @@ -0,0 +1 @@ +include(create-executable-target-link-phase.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-library-macos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-library-macos.cmake new file mode 100644 index 0000000..b2e3469 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-library-macos.cmake @@ -0,0 +1 @@ +include(create-executable-target.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-library-tvos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-library-tvos.cmake new file mode 100644 index 0000000..b2e3469 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-library-tvos.cmake @@ -0,0 +1 @@ +include(create-executable-target.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-library-visionos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-library-visionos.cmake new file mode 100644 index 0000000..b2e3469 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-library-visionos.cmake @@ -0,0 +1 @@ +include(create-executable-target.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-library-watchos.cmake b/Tests/RunCMake/XcFramework/create-executable-target-library-watchos.cmake new file mode 100644 index 0000000..b2e3469 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-library-watchos.cmake @@ -0,0 +1 @@ +include(create-executable-target.cmake) diff --git a/Tests/RunCMake/XcFramework/create-executable-target-link-phase.cmake b/Tests/RunCMake/XcFramework/create-executable-target-link-phase.cmake new file mode 100644 index 0000000..9c0b0d5 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target-link-phase.cmake @@ -0,0 +1,2 @@ +include(create-executable-target.cmake) +set_property(TARGET myexe PROPERTY XCODE_LINK_BUILD_PHASE_MODE "KNOWN_LOCATION") diff --git a/Tests/RunCMake/XcFramework/create-executable-target.cmake b/Tests/RunCMake/XcFramework/create-executable-target.cmake new file mode 100644 index 0000000..0cc356c --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable-target.cmake @@ -0,0 +1,21 @@ +enable_language(C) + +if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "tvOS" OR CMAKE_SYSTEM_NAME STREQUAL "watchOS" OR CMAKE_SYSTEM_NAME STREQUAL "visionOS") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES") +endif() + +add_library(mylib IMPORTED STATIC) +set_property(TARGET mylib PROPERTY IMPORTED_LOCATION ${MYLIB_LIBRARY}) + +add_executable(myexe myexe/myexe.c) +target_link_libraries(myexe PRIVATE mylib) diff --git a/Tests/RunCMake/XcFramework/create-executable.cmake b/Tests/RunCMake/XcFramework/create-executable.cmake new file mode 100644 index 0000000..6706b9f --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-executable.cmake @@ -0,0 +1,18 @@ +enable_language(C) + +if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "tvOS" OR CMAKE_SYSTEM_NAME STREQUAL "watchOS" OR CMAKE_SYSTEM_NAME STREQUAL "visionOS") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES") +endif() + +add_executable(myexe myexe/myexe.c) +target_link_libraries(myexe PRIVATE ${MYLIB_LIBRARY}) diff --git a/Tests/RunCMake/XcFramework/create-framework-ios.cmake b/Tests/RunCMake/XcFramework/create-framework-ios.cmake new file mode 100644 index 0000000..8b7df9b --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-framework-ios.cmake @@ -0,0 +1 @@ +include(create-framework.cmake) diff --git a/Tests/RunCMake/XcFramework/create-framework-macos.cmake b/Tests/RunCMake/XcFramework/create-framework-macos.cmake new file mode 100644 index 0000000..8b7df9b --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-framework-macos.cmake @@ -0,0 +1 @@ +include(create-framework.cmake) diff --git a/Tests/RunCMake/XcFramework/create-framework-tvos.cmake b/Tests/RunCMake/XcFramework/create-framework-tvos.cmake new file mode 100644 index 0000000..8b7df9b --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-framework-tvos.cmake @@ -0,0 +1 @@ +include(create-framework.cmake) diff --git a/Tests/RunCMake/XcFramework/create-framework-visionos.cmake b/Tests/RunCMake/XcFramework/create-framework-visionos.cmake new file mode 100644 index 0000000..8b7df9b --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-framework-visionos.cmake @@ -0,0 +1 @@ +include(create-framework.cmake) diff --git a/Tests/RunCMake/XcFramework/create-framework-watchos.cmake b/Tests/RunCMake/XcFramework/create-framework-watchos.cmake new file mode 100644 index 0000000..8b7df9b --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-framework-watchos.cmake @@ -0,0 +1 @@ +include(create-framework.cmake) diff --git a/Tests/RunCMake/XcFramework/create-framework.cmake b/Tests/RunCMake/XcFramework/create-framework.cmake new file mode 100644 index 0000000..f4406e6 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-framework.cmake @@ -0,0 +1,3 @@ +set(CMAKE_FRAMEWORK ON) +include(create-library-common.cmake) +install(FILES mylib/include/mylib/mylib.h DESTINATION lib/mylib.framework/Headers) diff --git a/Tests/RunCMake/XcFramework/create-library-common.cmake b/Tests/RunCMake/XcFramework/create-library-common.cmake new file mode 100644 index 0000000..958660d --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-library-common.cmake @@ -0,0 +1,12 @@ +enable_language(C) + +if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "tvOS" OR CMAKE_SYSTEM_NAME STREQUAL "watchOS" OR CMAKE_SYSTEM_NAME STREQUAL "visionOS") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES") +endif() + +add_library(mylib STATIC mylib/mylib.c) +install(TARGETS mylib DESTINATION lib) diff --git a/Tests/RunCMake/XcFramework/create-library-ios.cmake b/Tests/RunCMake/XcFramework/create-library-ios.cmake new file mode 100644 index 0000000..a9f5dee --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-library-ios.cmake @@ -0,0 +1 @@ +include(create-library.cmake) diff --git a/Tests/RunCMake/XcFramework/create-library-macos.cmake b/Tests/RunCMake/XcFramework/create-library-macos.cmake new file mode 100644 index 0000000..a9f5dee --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-library-macos.cmake @@ -0,0 +1 @@ +include(create-library.cmake) diff --git a/Tests/RunCMake/XcFramework/create-library-tvos.cmake b/Tests/RunCMake/XcFramework/create-library-tvos.cmake new file mode 100644 index 0000000..a9f5dee --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-library-tvos.cmake @@ -0,0 +1 @@ +include(create-library.cmake) diff --git a/Tests/RunCMake/XcFramework/create-library-visionos.cmake b/Tests/RunCMake/XcFramework/create-library-visionos.cmake new file mode 100644 index 0000000..a9f5dee --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-library-visionos.cmake @@ -0,0 +1 @@ +include(create-library.cmake) diff --git a/Tests/RunCMake/XcFramework/create-library-watchos.cmake b/Tests/RunCMake/XcFramework/create-library-watchos.cmake new file mode 100644 index 0000000..a9f5dee --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-library-watchos.cmake @@ -0,0 +1 @@ +include(create-library.cmake) diff --git a/Tests/RunCMake/XcFramework/create-library.cmake b/Tests/RunCMake/XcFramework/create-library.cmake new file mode 100644 index 0000000..f2a5249 --- /dev/null +++ b/Tests/RunCMake/XcFramework/create-library.cmake @@ -0,0 +1 @@ +include(create-library-common.cmake) diff --git a/Tests/RunCMake/XcFramework/myexe/myexe.c b/Tests/RunCMake/XcFramework/myexe/myexe.c new file mode 100644 index 0000000..d04efbd --- /dev/null +++ b/Tests/RunCMake/XcFramework/myexe/myexe.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + mylib(); + return 0; +} diff --git a/Tests/RunCMake/XcFramework/mylib/include/mylib/mylib.h b/Tests/RunCMake/XcFramework/mylib/include/mylib/mylib.h new file mode 100644 index 0000000..1de07aa --- /dev/null +++ b/Tests/RunCMake/XcFramework/mylib/include/mylib/mylib.h @@ -0,0 +1,3 @@ +#pragma once + +extern void mylib(void); diff --git a/Tests/RunCMake/XcFramework/mylib/mylib.c b/Tests/RunCMake/XcFramework/mylib/mylib.c new file mode 100644 index 0000000..4489684 --- /dev/null +++ b/Tests/RunCMake/XcFramework/mylib/mylib.c @@ -0,0 +1,3 @@ +void mylib(void) +{ +} diff --git a/bootstrap b/bootstrap index 82c5957..8b43d20 100755 --- a/bootstrap +++ b/bootstrap @@ -451,6 +451,7 @@ CMAKE_CXX_SOURCES="\ cmGccDepfileReader \ cmReturnCommand \ cmPlaceholderExpander \ + cmPlistParser \ cmRulePlaceholderExpander \ cmRuntimeDependencyArchive \ cmScriptGenerator \ @@ -500,6 +501,7 @@ CMAKE_CXX_SOURCES="\ cmWhileCommand \ cmWindowsRegistry \ cmWorkingDirectory \ + cmXcFramework \ cmake \ cmakemain \ cmcmd \ -- cgit v0.12