From a90968e044d04839e610da9a1adf7b6f390e144a Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 9 Nov 2023 16:02:40 -0500 Subject: cmExportBuildFileGenerator: Add structs for target exports --- Source/cmDyndepCollation.cxx | 6 ++++-- Source/cmExportBuildFileGenerator.cxx | 26 +++++++++++++++----------- Source/cmExportBuildFileGenerator.h | 30 +++++++++++++++++++++++++----- Source/cmExportCommand.cxx | 4 ++-- 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/Source/cmDyndepCollation.cxx b/Source/cmDyndepCollation.cxx index 75f88b2..e9f7be3 100644 --- a/Source/cmDyndepCollation.cxx +++ b/Source/cmDyndepCollation.cxx @@ -242,14 +242,16 @@ Json::Value CollationInformationExports(cmGeneratorTarget const* gt) auto const& all_build_exports = gt->Makefile->GetExportBuildFileGenerators(); for (auto const& exp : all_build_exports) { - std::vector targets; + std::vector targets; exp->GetTargets(targets); // Ignore exports sets which are not for this target. auto const& name = gt->GetName(); bool has_current_target = std::any_of(targets.begin(), targets.end(), - [name](std::string const& tname) { return tname == name; }); + [name](cmExportBuildFileGenerator::TargetExport const& te) { + return te.Name == name; + }); if (!has_current_target) { continue; } diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index eae3a74..291619f 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -10,7 +10,6 @@ #include #include -#include #include #include "cmExportSet.h" @@ -54,15 +53,15 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) { std::string expectedTargets; std::string sep; - std::vector targets; + std::vector targets; bool generatedInterfaceRequired = false; this->GetTargets(targets); - for (std::string const& tei : targets) { - cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(tei); + for (auto const& tei : targets) { + cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(tei.Name); expectedTargets += sep + this->Namespace + te->GetExportName(); sep = " "; if (this->ExportedTargets.insert(te).second) { - this->Exports.push_back(te); + this->Exports.emplace_back(te); } else { std::ostringstream e; e << "given target \"" << te->GetName() << "\" more than once."; @@ -82,7 +81,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) } // Create all the imported targets. - for (cmGeneratorTarget* gte : this->Exports) { + for (auto const& exp : this->Exports) { + cmGeneratorTarget* gte = exp.Target; this->GenerateImportTargetCode(os, gte, this->GetExportTargetType(gte)); gte->Target->AppendBuildInterfaceIncludes(); @@ -176,7 +176,9 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) void cmExportBuildFileGenerator::GenerateImportTargetsConfig( std::ostream& os, const std::string& config, std::string const& suffix) { - for (cmGeneratorTarget* target : this->Exports) { + for (auto const& exp : this->Exports) { + cmGeneratorTarget* target = exp.Target; + // Collect import properties for this target. ImportPropertyMap properties; @@ -308,7 +310,7 @@ void cmExportBuildFileGenerator::HandleMissingTarget( } void cmExportBuildFileGenerator::GetTargets( - std::vector& targets) const + std::vector& targets) const { if (this->ExportSet) { for (std::unique_ptr const& te : @@ -316,7 +318,7 @@ void cmExportBuildFileGenerator::GetTargets( if (te->NamelinkOnly) { continue; } - targets.push_back(te->TargetName); + targets.emplace_back(te->TargetName); } return; } @@ -334,9 +336,11 @@ cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg, for (auto const& exp : exportSets) { const auto& exportSet = exp.second; - std::vector targets; + std::vector targets; exportSet->GetTargets(targets); - if (cm::contains(targets, name)) { + if (std::any_of( + targets.begin(), targets.end(), + [&name](const TargetExport& te) { return te.Name == name; })) { exportFiles.push_back(exp.first); ns = exportSet->GetNamespace(); } diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index c5bb0df..2ac8fba 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -33,15 +33,25 @@ class cmTargetExport; class cmExportBuildFileGenerator : public cmExportFileGenerator { public: + struct TargetExport + { + TargetExport(std::string name) + : Name(std::move(name)) + { + } + + std::string Name; + }; + cmExportBuildFileGenerator(); /** Set the list of targets to export. */ - void SetTargets(std::vector const& targets) + void SetTargets(std::vector const& targets) { this->Targets = targets; } - void GetTargets(std::vector& targets) const; - void AppendTargets(std::vector const& targets) + void GetTargets(std::vector& targets) const; + void AppendTargets(std::vector const& targets) { cm::append(this->Targets, targets); } @@ -99,9 +109,19 @@ protected: std::pair, std::string> FindBuildExportInfo( cmGlobalGenerator* gg, const std::string& name); - std::vector Targets; + struct TargetExportPrivate + { + TargetExportPrivate(cmGeneratorTarget* target) + : Target(target) + { + } + + cmGeneratorTarget* Target; + }; + + std::vector Targets; cmExportSet* ExportSet; - std::vector Exports; + std::vector Exports; cmLocalGenerator* LG; // The directory for C++ module information. std::string CxxModulesDirectory; diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index cf1f4ad..e7a69b0 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -204,7 +204,7 @@ bool cmExportCommand(std::vector const& args, fname = dir + "/" + fname; } - std::vector targets; + std::vector targets; cmGlobalGenerator* gg = mf.GetGlobalGenerator(); @@ -242,7 +242,7 @@ bool cmExportCommand(std::vector const& args, status.SetError(e.str()); return false; } - targets.push_back(currentTarget); + targets.emplace_back(currentTarget); } if (arguments.Append) { if (cmExportBuildFileGenerator* ebfg = -- cgit v0.12 From 256bb0cc40a9f9f20452f0c0b2480886a577e7cb Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 21 Sep 2023 14:04:54 -0400 Subject: install(EXPORT): Add ability to point to .xcframework file Issue: #25262 --- Help/command/export.rst | 13 +++ Help/release/dev/install-export-xcframework.rst | 6 ++ Source/cmExportBuildAndroidMKGenerator.cxx | 4 +- Source/cmExportBuildAndroidMKGenerator.h | 6 +- Source/cmExportBuildFileGenerator.cxx | 22 ++++- Source/cmExportBuildFileGenerator.h | 9 +- Source/cmExportCommand.cxx | 30 +++++- Source/cmExportFileGenerator.cxx | 64 +++++++++---- Source/cmExportFileGenerator.h | 11 ++- Source/cmExportInstallAndroidMKGenerator.cxx | 6 +- Source/cmExportInstallAndroidMKGenerator.h | 9 +- Source/cmExportInstallFileGenerator.cxx | 23 ++++- Source/cmExportSet.cxx | 10 ++ Source/cmExportSet.h | 3 + Source/cmTargetExport.h | 1 + Tests/RunCMake/XcFramework/RunCMakeTest.cmake | 103 +++++++++++++++++++++ Tests/RunCMake/XcFramework/export-macos.cmake | 33 +++++++ Tests/RunCMake/XcFramework/import-common.cmake | 5 + .../RunCMake/XcFramework/import-genex-common.cmake | 5 + .../import-macos-build-specific-build-stdout.txt | 2 + ...ort-macos-build-specific-genex-build-stdout.txt | 2 + .../import-macos-build-specific-genex.cmake | 1 + .../XcFramework/import-macos-build-specific.cmake | 1 + .../import-macos-install-specific-build-stdout.txt | 2 + ...t-macos-install-specific-genex-build-stdout.txt | 2 + .../import-macos-install-specific-genex.cmake | 1 + ...nstall-specific-no-xcframework-build-stdout.txt | 2 + ...ort-macos-install-specific-no-xcframework.cmake | 1 + .../import-macos-install-specific.cmake | 1 + Tests/RunCMake/XcFramework/mylib-config.cmake.in | 3 + 30 files changed, 338 insertions(+), 43 deletions(-) create mode 100644 Help/release/dev/install-export-xcframework.rst create mode 100644 Tests/RunCMake/XcFramework/export-macos.cmake create mode 100644 Tests/RunCMake/XcFramework/import-common.cmake create mode 100644 Tests/RunCMake/XcFramework/import-genex-common.cmake create mode 100644 Tests/RunCMake/XcFramework/import-macos-build-specific-build-stdout.txt create mode 100644 Tests/RunCMake/XcFramework/import-macos-build-specific-genex-build-stdout.txt create mode 100644 Tests/RunCMake/XcFramework/import-macos-build-specific-genex.cmake create mode 100644 Tests/RunCMake/XcFramework/import-macos-build-specific.cmake create mode 100644 Tests/RunCMake/XcFramework/import-macos-install-specific-build-stdout.txt create mode 100644 Tests/RunCMake/XcFramework/import-macos-install-specific-genex-build-stdout.txt create mode 100644 Tests/RunCMake/XcFramework/import-macos-install-specific-genex.cmake create mode 100644 Tests/RunCMake/XcFramework/import-macos-install-specific-no-xcframework-build-stdout.txt create mode 100644 Tests/RunCMake/XcFramework/import-macos-install-specific-no-xcframework.cmake create mode 100644 Tests/RunCMake/XcFramework/import-macos-install-specific.cmake create mode 100644 Tests/RunCMake/XcFramework/mylib-config.cmake.in diff --git a/Help/command/export.rst b/Help/command/export.rst index 0440c50..f190df7 100644 --- a/Help/command/export.rst +++ b/Help/command/export.rst @@ -170,6 +170,9 @@ Configuring Exports [ENABLED (||AUTO)] [EXTRA_ARGS ...] ] [...] + [TARGET + [XCFRAMEWORK_LOCATION ] + ] [...] ) .. versionadded:: 3.29 @@ -202,3 +205,13 @@ Configure the parameters of an export. The arguments are as follows: ``EXTRA_ARGS `` Specify additional arguments to pass to :command:`find_dependency` after the ``REQUIRED`` argument. + +``TARGET `` + Specify a target to configure in this export. This argument accepts the + following additional arguments: + + ``XCFRAMEWORK_LOCATION`` + Specify the location of an ``.xcframework`` which contains the library from + this target. If specified, the generated code will check to see if the + ``.xcframework`` exists, and if it does, it will use the ``.xcframework`` + as its imported location instead of the installed library. diff --git a/Help/release/dev/install-export-xcframework.rst b/Help/release/dev/install-export-xcframework.rst new file mode 100644 index 0000000..90fce82 --- /dev/null +++ b/Help/release/dev/install-export-xcframework.rst @@ -0,0 +1,6 @@ +install-export-xcframework +-------------------------- + +* The :command:`export(SETUP)` command gained a new ``XCFRAMEWORK_LOCATION`` + argument, which can be used to specify the location of a ``.xcframework`` + that can be substituted for the installed library. diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index c54e6ac..34bda1b 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -57,8 +57,8 @@ void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode( } void cmExportBuildAndroidMKGenerator::GenerateImportPropertyCode( - std::ostream&, const std::string&, cmGeneratorTarget const*, - ImportPropertyMap const&) + std::ostream&, const std::string&, const std::string&, + cmGeneratorTarget const*, ImportPropertyMap const&, const std::string&) { } diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h index 8918ce1..9562cee 100644 --- a/Source/cmExportBuildAndroidMKGenerator.h +++ b/Source/cmExportBuildAndroidMKGenerator.h @@ -51,9 +51,9 @@ protected: void GenerateExpectedTargetsCode( std::ostream& os, const std::string& expectedTargets) override; void GenerateImportPropertyCode( - std::ostream& os, const std::string& config, - cmGeneratorTarget const* target, - ImportPropertyMap const& properties) override; + std::ostream& os, const std::string& config, const std::string& suffix, + cmGeneratorTarget const* target, ImportPropertyMap const& properties, + const std::string& importedXcFrameworkLocation) override; void GenerateMissingTargetsCheckCode(std::ostream& os) override; void GenerateFindDependencyCalls(std::ostream&) override {} void GenerateInterfaceProperties( diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 291619f..8ba8d97 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -61,7 +61,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) expectedTargets += sep + this->Namespace + te->GetExportName(); sep = " "; if (this->ExportedTargets.insert(te).second) { - this->Exports.emplace_back(te); + this->Exports.emplace_back(te, tei.XcFrameworkLocation); } else { std::ostringstream e; e << "given target \"" << te->GetName() << "\" more than once."; @@ -202,7 +202,23 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig( // properties); // Generate code in the export file. - this->GenerateImportPropertyCode(os, config, target, properties); + std::string importedXcFrameworkLocation = exp.XcFrameworkLocation; + if (!importedXcFrameworkLocation.empty()) { + importedXcFrameworkLocation = cmGeneratorExpression::Preprocess( + importedXcFrameworkLocation, + cmGeneratorExpression::PreprocessContext::BuildInterface); + importedXcFrameworkLocation = cmGeneratorExpression::Evaluate( + importedXcFrameworkLocation, exp.Target->GetLocalGenerator(), config, + exp.Target, nullptr, exp.Target); + if (!importedXcFrameworkLocation.empty() && + !cmSystemTools::FileIsFullPath(importedXcFrameworkLocation)) { + importedXcFrameworkLocation = + cmStrCat(this->LG->GetCurrentBinaryDirectory(), '/', + importedXcFrameworkLocation); + } + } + this->GenerateImportPropertyCode(os, config, suffix, target, properties, + importedXcFrameworkLocation); } } } @@ -318,7 +334,7 @@ void cmExportBuildFileGenerator::GetTargets( if (te->NamelinkOnly) { continue; } - targets.emplace_back(te->TargetName); + targets.emplace_back(te->TargetName, te->XcFrameworkLocation); } return; } diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 2ac8fba..9f11d13 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -35,12 +35,14 @@ class cmExportBuildFileGenerator : public cmExportFileGenerator public: struct TargetExport { - TargetExport(std::string name) + TargetExport(std::string name, std::string xcFrameworkLocation) : Name(std::move(name)) + , XcFrameworkLocation(std::move(xcFrameworkLocation)) { } std::string Name; + std::string XcFrameworkLocation; }; cmExportBuildFileGenerator(); @@ -111,12 +113,15 @@ protected: struct TargetExportPrivate { - TargetExportPrivate(cmGeneratorTarget* target) + TargetExportPrivate(cmGeneratorTarget* target, + std::string xcFrameworkLocation) : Target(target) + , XcFrameworkLocation(std::move(xcFrameworkLocation)) { } cmGeneratorTarget* Target; + std::string XcFrameworkLocation; }; std::vector Targets; diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index e7a69b0..9c3bc61 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -72,6 +72,8 @@ bool cmExportCommand(std::vector const& args, std::vector> PackageDependencyArgs; bool ExportPackageDependencies = false; + + std::vector> TargetArgs; }; auto parser = @@ -87,6 +89,7 @@ bool cmExportCommand(std::vector const& args, } else if (args[0] == "SETUP") { parser.Bind("SETUP"_s, &Arguments::ExportSetName); parser.Bind("PACKAGE_DEPENDENCY"_s, &Arguments::PackageDependencyArgs); + parser.Bind("TARGET"_s, &Arguments::TargetArgs); } else { parser.Bind("TARGETS"_s, &Arguments::Targets); parser.Bind("ANDROID_MK"_s, &Arguments::AndroidMKFile); @@ -159,6 +162,31 @@ bool cmExportCommand(std::vector const& args, packageDependencyArguments.ExtraArgs); } + struct TargetArguments + { + std::string XcFrameworkLocation; + }; + + auto targetParser = cmArgumentParser{}.Bind( + "XCFRAMEWORK_LOCATION"_s, &TargetArguments::XcFrameworkLocation); + + for (auto const& targetArgs : arguments.TargetArgs) { + if (targetArgs.empty()) { + continue; + } + + TargetArguments const targetArguments = + targetParser.Parse(cmMakeRange(targetArgs).advance(1), &unknownArgs); + + if (!unknownArgs.empty()) { + status.SetError("Unknown argument: \"" + unknownArgs.front() + "\"."); + return false; + } + + exportSet.SetXcFrameworkLocation(targetArgs.front(), + targetArguments.XcFrameworkLocation); + } + return true; } @@ -242,7 +270,7 @@ bool cmExportCommand(std::vector const& args, status.SetError(e.str()); return false; } - targets.emplace_back(currentTarget); + targets.emplace_back(currentTarget, std::string{}); } if (arguments.Append) { if (cmExportBuildFileGenerator* ebfg = diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 205bf08..e2c3edd 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -1154,8 +1154,9 @@ void cmExportFileGenerator::GenerateImportTargetCode( } void cmExportFileGenerator::GenerateImportPropertyCode( - std::ostream& os, const std::string& config, cmGeneratorTarget const* target, - ImportPropertyMap const& properties) + std::ostream& os, const std::string& config, const std::string& suffix, + cmGeneratorTarget const* target, ImportPropertyMap const& properties, + const std::string& importedXcFrameworkLocation) { // Construct the imported target name. std::string targetName = this->Namespace; @@ -1174,12 +1175,31 @@ void cmExportFileGenerator::GenerateImportPropertyCode( } os << ")\n"; os << "set_target_properties(" << targetName << " PROPERTIES\n"; + std::string importedLocationProp = cmStrCat("IMPORTED_LOCATION", suffix); for (auto const& property : properties) { - os << " " << property.first << " " - << cmExportFileGeneratorEscape(property.second) << "\n"; + if (importedXcFrameworkLocation.empty() || + property.first != importedLocationProp) { + os << " " << property.first << " " + << cmExportFileGeneratorEscape(property.second) << "\n"; + } } - os << " )\n" - << "\n"; + os << " )\n"; + if (!importedXcFrameworkLocation.empty()) { + auto importedLocationIt = properties.find(importedLocationProp); + if (importedLocationIt != properties.end()) { + os << "if(NOT CMAKE_VERSION VERSION_LESS \"3.28\" AND IS_DIRECTORY " + << cmExportFileGeneratorEscape(importedXcFrameworkLocation) + << ")\n" + " set_property(TARGET " + << targetName << " PROPERTY " << importedLocationProp << " " + << cmExportFileGeneratorEscape(importedXcFrameworkLocation) + << ")\nelse()\n set_property(TARGET " << targetName << " PROPERTY " + << importedLocationProp << " " + << cmExportFileGeneratorEscape(importedLocationIt->second) + << ")\nendif()\n"; + } + } + os << "\n"; } void cmExportFileGenerator::GenerateFindDependencyCalls(std::ostream& os) @@ -1310,10 +1330,16 @@ void cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os) /* clang-format off */ os << "# Loop over all imported files and verify that they actually exist\n" "foreach(_cmake_target IN LISTS _cmake_import_check_targets)\n" - " foreach(_cmake_file IN LISTS \"_cmake_import_check_files_for_${_cmake_target}\")\n" - " if(NOT EXISTS \"${_cmake_file}\")\n" - " message(FATAL_ERROR \"The imported target \\\"${_cmake_target}\\\"" - " references the file\n" + " if(CMAKE_VERSION VERSION_LESS \"3.28\"\n" + " OR NOT DEFINED " + "_cmake_import_check_xcframework_for_${_cmake_target}\n" + " OR NOT IS_DIRECTORY " + "\"${_cmake_import_check_xcframework_for_${_cmake_target}}\")\n" + " foreach(_cmake_file IN LISTS " + "\"_cmake_import_check_files_for_${_cmake_target}\")\n" + " if(NOT EXISTS \"${_cmake_file}\")\n" + " message(FATAL_ERROR \"The imported target " + "\\\"${_cmake_target}\\\" references the file\n" " \\\"${_cmake_file}\\\"\n" "but this file does not exist. Possible reasons include:\n" "* The file was deleted, renamed, or moved to another location.\n" @@ -1322,8 +1348,9 @@ void cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os) " \\\"${CMAKE_CURRENT_LIST_FILE}\\\"\n" "but not all the files it references.\n" "\")\n" - " endif()\n" - " endforeach()\n" + " endif()\n" + " endforeach()\n" + " endif()\n" " unset(_cmake_file)\n" " unset(\"_cmake_import_check_files_for_${_cmake_target}\")\n" "endforeach()\n" @@ -1336,15 +1363,18 @@ void cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os) void cmExportFileGenerator::GenerateImportedFileChecksCode( std::ostream& os, cmGeneratorTarget* target, ImportPropertyMap const& properties, - const std::set& importedLocations) + const std::set& importedLocations, + const std::string& importedXcFrameworkLocation) { // Construct the imported target name. std::string targetName = cmStrCat(this->Namespace, target->GetExportName()); - os << "list(APPEND _cmake_import_check_targets " << targetName - << " )\n" - "list(APPEND _cmake_import_check_files_for_" - << targetName << " "; + os << "list(APPEND _cmake_import_check_targets " << targetName << " )\n"; + if (!importedXcFrameworkLocation.empty()) { + os << "set(_cmake_import_check_xcframework_for_" << targetName << ' ' + << cmExportFileGeneratorEscape(importedXcFrameworkLocation) << ")\n"; + } + os << "list(APPEND _cmake_import_check_files_for_" << targetName << " "; for (std::string const& li : importedLocations) { auto pi = properties.find(li); diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index ccc10d8..554dd4a 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -84,14 +84,15 @@ protected: virtual void GenerateImportTargetCode(std::ostream& os, cmGeneratorTarget const* target, cmStateEnums::TargetType targetType); - virtual void GenerateImportPropertyCode(std::ostream& os, - const std::string& config, - cmGeneratorTarget const* target, - ImportPropertyMap const& properties); + virtual void GenerateImportPropertyCode( + std::ostream& os, const std::string& config, const std::string& suffix, + cmGeneratorTarget const* target, ImportPropertyMap const& properties, + const std::string& importedXcFrameworkLocation); virtual void GenerateImportedFileChecksCode( std::ostream& os, cmGeneratorTarget* target, ImportPropertyMap const& properties, - const std::set& importedLocations); + const std::set& importedLocations, + const std::string& importedXcFrameworkLocation); virtual void GenerateImportedFileCheckLoop(std::ostream& os); virtual void GenerateMissingTargetsCheckCode(std::ostream& os); virtual void GenerateFindDependencyCalls(std::ostream& os); diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx index 7dfdc0e..eaa85f3 100644 --- a/Source/cmExportInstallAndroidMKGenerator.cxx +++ b/Source/cmExportInstallAndroidMKGenerator.cxx @@ -80,8 +80,8 @@ void cmExportInstallAndroidMKGenerator::GenerateExpectedTargetsCode( } void cmExportInstallAndroidMKGenerator::GenerateImportPropertyCode( - std::ostream&, const std::string&, cmGeneratorTarget const*, - ImportPropertyMap const&) + std::ostream&, const std::string&, const std::string&, + cmGeneratorTarget const*, ImportPropertyMap const&, const std::string&) { } @@ -122,7 +122,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportedFileCheckLoop( void cmExportInstallAndroidMKGenerator::GenerateImportedFileChecksCode( std::ostream&, cmGeneratorTarget*, ImportPropertyMap const&, - const std::set&) + const std::set&, const std::string&) { } diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h index 9454cdf..b1778ef 100644 --- a/Source/cmExportInstallAndroidMKGenerator.h +++ b/Source/cmExportInstallAndroidMKGenerator.h @@ -45,9 +45,9 @@ protected: void GenerateExpectedTargetsCode( std::ostream& os, const std::string& expectedTargets) override; void GenerateImportPropertyCode( - std::ostream& os, const std::string& config, - cmGeneratorTarget const* target, - ImportPropertyMap const& properties) override; + std::ostream& os, const std::string& config, const std::string& suffix, + cmGeneratorTarget const* target, ImportPropertyMap const& properties, + const std::string& importedXcFrameworkLocation) override; void GenerateMissingTargetsCheckCode(std::ostream& os) override; void GenerateFindDependencyCalls(std::ostream&) override {} void GenerateInterfaceProperties( @@ -60,6 +60,7 @@ protected: void GenerateImportedFileChecksCode( std::ostream& os, cmGeneratorTarget* target, ImportPropertyMap const& properties, - const std::set& importedLocations) override; + const std::set& importedLocations, + const std::string& importedXcFrameworkLocation) override; bool GenerateImportFileConfig(const std::string& config) override; }; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index b829edd..64e694c 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -375,9 +375,26 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig( // properties); // Generate code in the export file. - this->GenerateImportPropertyCode(os, config, gtgt, properties); - this->GenerateImportedFileChecksCode(os, gtgt, properties, - importedLocations); + std::string importedXcFrameworkLocation = te->XcFrameworkLocation; + if (!importedXcFrameworkLocation.empty()) { + importedXcFrameworkLocation = cmGeneratorExpression::Preprocess( + importedXcFrameworkLocation, + cmGeneratorExpression::PreprocessContext::InstallInterface, true); + importedXcFrameworkLocation = cmGeneratorExpression::Evaluate( + importedXcFrameworkLocation, te->Target->GetLocalGenerator(), config, + te->Target, nullptr, te->Target); + if (!importedXcFrameworkLocation.empty() && + !cmSystemTools::FileIsFullPath(importedXcFrameworkLocation) && + !cmHasLiteralPrefix(importedXcFrameworkLocation, + "${_IMPORT_PREFIX}/")) { + importedXcFrameworkLocation = + cmStrCat("${_IMPORT_PREFIX}/", importedXcFrameworkLocation); + } + } + this->GenerateImportPropertyCode(os, config, suffix, gtgt, properties, + importedXcFrameworkLocation); + this->GenerateImportedFileChecksCode( + os, gtgt, properties, importedLocations, importedXcFrameworkLocation); } } } diff --git a/Source/cmExportSet.cxx b/Source/cmExportSet.cxx index aa32394..b32bb8d 100644 --- a/Source/cmExportSet.cxx +++ b/Source/cmExportSet.cxx @@ -72,6 +72,16 @@ void cmExportSet::AddInstallation(cmInstallExportGenerator const* installation) this->Installations.push_back(installation); } +void cmExportSet::SetXcFrameworkLocation(const std::string& name, + const std::string& location) +{ + for (auto& te : this->TargetExports) { + if (name == te->TargetName) { + te->XcFrameworkLocation = location; + } + } +} + cmExportSet& cmExportSetMap::operator[](const std::string& name) { auto it = this->find(name); diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h index c5fc91f..f2fc4a7 100644 --- a/Source/cmExportSet.h +++ b/Source/cmExportSet.h @@ -33,6 +33,9 @@ public: void AddInstallation(cmInstallExportGenerator const* installation); + void SetXcFrameworkLocation(const std::string& name, + const std::string& location); + std::string const& GetName() const { return this->Name; } std::vector> const& GetTargetExports() const diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h index 0dac5ca..caeb54d 100644 --- a/Source/cmTargetExport.h +++ b/Source/cmTargetExport.h @@ -38,4 +38,5 @@ public: ///@} bool NamelinkOnly = false; + std::string XcFrameworkLocation; }; diff --git a/Tests/RunCMake/XcFramework/RunCMakeTest.cmake b/Tests/RunCMake/XcFramework/RunCMakeTest.cmake index 9a13892..28e5035 100644 --- a/Tests/RunCMake/XcFramework/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcFramework/RunCMakeTest.cmake @@ -119,3 +119,106 @@ unset(RunCMake_TEST_BINARY_DIR) run_cmake(find-library) run_cmake_command(find-library-script ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/find-library.cmake) + +file(REMOVE_RECURSE ${RunCMake_BINARY_DIR}/export-install) +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/export-macos-build) +run_cmake_with_options(export-macos -DCMAKE_SYSTEM_NAME=Darwin -DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/export-install) +set(RunCMake_TEST_NO_CLEAN 1) +set(_config_arg) +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(_config_arg --config Release) +endif() +run_cmake_command(export-macos-build ${CMAKE_COMMAND} --build . ${_config_arg}) +run_cmake_command(export-macos-install ${CMAKE_COMMAND} --install . ${_config_arg}) +unset(RunCMake_TEST_NO_CLEAN) +unset(RunCMake_TEST_BINARY_DIR) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/import-macos-install-specific-no-xcframework-build) +run_cmake_with_options(import-macos-install-specific-no-xcframework -DCMAKE_SYSTEM_NAME=Darwin -Dmylib_DIR=${RunCMake_BINARY_DIR}/export-install/lib/macos/cmake/mylib) +set(RunCMake_TEST_NO_CLEAN 1) +set(_config_arg) +set(_config_dir) +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(_config_arg --config Release) + set(_config_dir /Release) +endif() +run_cmake_command(import-macos-install-specific-no-xcframework-build ${CMAKE_COMMAND} --build . ${_config_arg}) +unset(RunCMake_TEST_NO_CLEAN) +unset(RunCMake_TEST_BINARY_DIR) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/export-macos-build) +set(RunCMake_TEST_NO_CLEAN 1) +if(CMake_TEST_XCODE_VERSION VERSION_GREATER_EQUAL 15) + # 'xcodebuild -create-xcframework' fails on symlinked paths. + file(REAL_PATH "${RunCMake_SOURCE_DIR}" src_dir) + file(REAL_PATH "${RunCMake_BINARY_DIR}" bld_dir) +else() + set(src_dir "${RunCMake_SOURCE_DIR}") + set(bld_dir "${RunCMake_BINARY_DIR}") +endif() +run_cmake_command(export-install-xcframework xcodebuild -create-xcframework + -output ${bld_dir}/export-install/lib/mylib.xcframework + -library ${bld_dir}/export-install/lib/macos/libmylib.a + -headers ${src_dir}/mylib/include + ) +run_cmake_command(export-build-xcframework xcodebuild -create-xcframework + -output ${bld_dir}/export-macos-build/lib/mylib.xcframework + -library ${bld_dir}/export-macos-build/lib/macos${_config_dir}/libmylib.a + -headers ${src_dir}/mylib/include + ) +run_cmake_command(export-install-xcframework-genex xcodebuild -create-xcframework + -output ${bld_dir}/export-install/lib2/mylib-genex.xcframework + -library ${bld_dir}/export-install/lib/macos/libmylib-genex.a + -headers ${src_dir}/mylib/include + ) +run_cmake_command(export-build-xcframework-genex xcodebuild -create-xcframework + -output ${bld_dir}/export-macos-build/lib/mylib-genex.xcframework + -library ${bld_dir}/export-macos-build/lib/macos${_config_dir}/libmylib-genex.a + -headers ${src_dir}/mylib/include + ) +unset(RunCMake_TEST_NO_CLEAN) +unset(RunCMake_TEST_BINARY_DIR) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/import-macos-install-specific-build) +run_cmake_with_options(import-macos-install-specific -DCMAKE_SYSTEM_NAME=Darwin -Dmylib_DIR=${RunCMake_BINARY_DIR}/export-install/lib/macos/cmake/mylib) +set(RunCMake_TEST_NO_CLEAN 1) +set(_config_arg) +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(_config_arg --config Release) +endif() +run_cmake_command(import-macos-install-specific-build ${CMAKE_COMMAND} --build . ${_config_arg}) +unset(RunCMake_TEST_NO_CLEAN) +unset(RunCMake_TEST_BINARY_DIR) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/import-macos-build-specific-build) +run_cmake_with_options(import-macos-build-specific -DCMAKE_SYSTEM_NAME=Darwin -Dmylib_DIR=${RunCMake_BINARY_DIR}/export-macos-build/lib/macos/cmake/mylib) +set(RunCMake_TEST_NO_CLEAN 1) +set(_config_arg) +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(_config_arg --config Release) +endif() +run_cmake_command(import-macos-build-specific-build ${CMAKE_COMMAND} --build . ${_config_arg}) +unset(RunCMake_TEST_NO_CLEAN) +unset(RunCMake_TEST_BINARY_DIR) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/import-macos-install-specific-genex-build) +run_cmake_with_options(import-macos-install-specific-genex -DCMAKE_SYSTEM_NAME=Darwin -Dmylib_DIR=${RunCMake_BINARY_DIR}/export-install/lib/macos/cmake/mylib) +set(RunCMake_TEST_NO_CLEAN 1) +set(_config_arg) +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(_config_arg --config Release) +endif() +run_cmake_command(import-macos-install-specific-genex-build ${CMAKE_COMMAND} --build . ${_config_arg}) +unset(RunCMake_TEST_NO_CLEAN) +unset(RunCMake_TEST_BINARY_DIR) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/import-macos-build-specific-genex-build) +run_cmake_with_options(import-macos-build-specific-genex -DCMAKE_SYSTEM_NAME=Darwin -Dmylib_DIR=${RunCMake_BINARY_DIR}/export-macos-build/lib/macos/cmake/mylib) +set(RunCMake_TEST_NO_CLEAN 1) +set(_config_arg) +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(_config_arg --config Release) +endif() +run_cmake_command(import-macos-build-specific-genex-build ${CMAKE_COMMAND} --build . ${_config_arg}) +unset(RunCMake_TEST_NO_CLEAN) +unset(RunCMake_TEST_BINARY_DIR) diff --git a/Tests/RunCMake/XcFramework/export-macos.cmake b/Tests/RunCMake/XcFramework/export-macos.cmake new file mode 100644 index 0000000..4a9caa5 --- /dev/null +++ b/Tests/RunCMake/XcFramework/export-macos.cmake @@ -0,0 +1,33 @@ +enable_language(C) + +include(CMakePackageConfigHelpers) + +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) +target_include_directories(mylib INTERFACE $) +set_property(TARGET mylib PROPERTY ARCHIVE_OUTPUT_DIRECTORY lib/macos) + +add_library(mylib-genex STATIC mylib/mylib.c) +target_include_directories(mylib-genex INTERFACE $) +set_property(TARGET mylib-genex PROPERTY ARCHIVE_OUTPUT_DIRECTORY lib/macos) + +install(TARGETS mylib mylib-genex DESTINATION lib/macos EXPORT mylib) +install(FILES mylib/include/mylib/mylib.h DESTINATION include/mylib) +export(SETUP mylib + TARGET mylib XCFRAMEWORK_LOCATION lib/mylib.xcframework + TARGET mylib-genex XCFRAMEWORK_LOCATION "$.xcframework>$.xcframework>" + ) +install(EXPORT mylib DESTINATION lib/macos/cmake/mylib FILE mylib-targets.cmake) +export(EXPORT mylib FILE lib/macos/cmake/mylib/mylib-targets.cmake) + +configure_package_config_file(mylib-config.cmake.in mylib-config-sub.cmake INSTALL_DESTINATION lib/macos/cmake/mylib) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mylib-config-sub.cmake DESTINATION lib/macos/cmake/mylib RENAME mylib-config.cmake) + +configure_package_config_file(mylib-config.cmake.in lib/macos/cmake/mylib/mylib-config.cmake INSTALL_DESTINATION lib/macos/cmake/mylib) diff --git a/Tests/RunCMake/XcFramework/import-common.cmake b/Tests/RunCMake/XcFramework/import-common.cmake new file mode 100644 index 0000000..4def6a4 --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-common.cmake @@ -0,0 +1,5 @@ +enable_language(C) + +find_package(mylib REQUIRED) + +add_custom_target(print_loc ALL COMMAND ${CMAKE_COMMAND} -E echo "mylib location: $") diff --git a/Tests/RunCMake/XcFramework/import-genex-common.cmake b/Tests/RunCMake/XcFramework/import-genex-common.cmake new file mode 100644 index 0000000..e46902b --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-genex-common.cmake @@ -0,0 +1,5 @@ +enable_language(C) + +find_package(mylib REQUIRED) + +add_custom_target(print_loc ALL COMMAND ${CMAKE_COMMAND} -E echo "mylib-genex location: $") diff --git a/Tests/RunCMake/XcFramework/import-macos-build-specific-build-stdout.txt b/Tests/RunCMake/XcFramework/import-macos-build-specific-build-stdout.txt new file mode 100644 index 0000000..3ac467d --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-build-specific-build-stdout.txt @@ -0,0 +1,2 @@ +mylib location: [^ +]*/Tests/RunCMake/XcFramework/export-macos-build/lib/mylib\.xcframework/macos-(arm64|x86_64|arm64_x86_64)/libmylib\.a diff --git a/Tests/RunCMake/XcFramework/import-macos-build-specific-genex-build-stdout.txt b/Tests/RunCMake/XcFramework/import-macos-build-specific-genex-build-stdout.txt new file mode 100644 index 0000000..d3a20e8 --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-build-specific-genex-build-stdout.txt @@ -0,0 +1,2 @@ +mylib-genex location: [^ +]*/Tests/RunCMake/XcFramework/export-macos-build/lib/mylib-genex\.xcframework/macos-(arm64|x86_64|arm64_x86_64)/libmylib-genex\.a diff --git a/Tests/RunCMake/XcFramework/import-macos-build-specific-genex.cmake b/Tests/RunCMake/XcFramework/import-macos-build-specific-genex.cmake new file mode 100644 index 0000000..a061bd3 --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-build-specific-genex.cmake @@ -0,0 +1 @@ +include(import-genex-common.cmake) diff --git a/Tests/RunCMake/XcFramework/import-macos-build-specific.cmake b/Tests/RunCMake/XcFramework/import-macos-build-specific.cmake new file mode 100644 index 0000000..08ef6db --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-build-specific.cmake @@ -0,0 +1 @@ +include(import-common.cmake) diff --git a/Tests/RunCMake/XcFramework/import-macos-install-specific-build-stdout.txt b/Tests/RunCMake/XcFramework/import-macos-install-specific-build-stdout.txt new file mode 100644 index 0000000..1421246 --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-install-specific-build-stdout.txt @@ -0,0 +1,2 @@ +mylib location: [^ +]*/Tests/RunCMake/XcFramework/export-install/lib/mylib\.xcframework/macos-(arm64|x86_64|arm64_x86_64)/libmylib\.a diff --git a/Tests/RunCMake/XcFramework/import-macos-install-specific-genex-build-stdout.txt b/Tests/RunCMake/XcFramework/import-macos-install-specific-genex-build-stdout.txt new file mode 100644 index 0000000..5c88758 --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-install-specific-genex-build-stdout.txt @@ -0,0 +1,2 @@ +mylib-genex location: [^ +]*/Tests/RunCMake/XcFramework/export-install/lib2/mylib-genex\.xcframework/macos-(arm64|x86_64|arm64_x86_64)/libmylib-genex\.a diff --git a/Tests/RunCMake/XcFramework/import-macos-install-specific-genex.cmake b/Tests/RunCMake/XcFramework/import-macos-install-specific-genex.cmake new file mode 100644 index 0000000..a061bd3 --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-install-specific-genex.cmake @@ -0,0 +1 @@ +include(import-genex-common.cmake) diff --git a/Tests/RunCMake/XcFramework/import-macos-install-specific-no-xcframework-build-stdout.txt b/Tests/RunCMake/XcFramework/import-macos-install-specific-no-xcframework-build-stdout.txt new file mode 100644 index 0000000..1c92972 --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-install-specific-no-xcframework-build-stdout.txt @@ -0,0 +1,2 @@ +mylib location: [^ +]*/Tests/RunCMake/XcFramework/export-install/lib/macos/libmylib\.a diff --git a/Tests/RunCMake/XcFramework/import-macos-install-specific-no-xcframework.cmake b/Tests/RunCMake/XcFramework/import-macos-install-specific-no-xcframework.cmake new file mode 100644 index 0000000..08ef6db --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-install-specific-no-xcframework.cmake @@ -0,0 +1 @@ +include(import-common.cmake) diff --git a/Tests/RunCMake/XcFramework/import-macos-install-specific.cmake b/Tests/RunCMake/XcFramework/import-macos-install-specific.cmake new file mode 100644 index 0000000..08ef6db --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-install-specific.cmake @@ -0,0 +1 @@ +include(import-common.cmake) diff --git a/Tests/RunCMake/XcFramework/mylib-config.cmake.in b/Tests/RunCMake/XcFramework/mylib-config.cmake.in new file mode 100644 index 0000000..878d6e8 --- /dev/null +++ b/Tests/RunCMake/XcFramework/mylib-config.cmake.in @@ -0,0 +1,3 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/mylib-targets.cmake") -- cgit v0.12 From 37bc3400cd5abd2e9f34a9da726dcffed709f9d4 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 3 Nov 2023 17:30:42 -0400 Subject: CMakePackageConfigHelpers: Add generate_apple_platform_selection_file() Issue: #25262 --- Help/release/dev/install-export-xcframework.rst | 3 + Modules/CMakePackageConfigHelpers.cmake | 104 +++++++++++++++++++++ Modules/PlatformSelectionFile.cmake.in | 24 +++++ Tests/RunCMake/XcFramework/RunCMakeTest.cmake | 22 +++++ Tests/RunCMake/XcFramework/export-macos.cmake | 11 +++ .../import-macos-build-general-build-stdout.txt | 2 + .../XcFramework/import-macos-build-general.cmake | 1 + .../import-macos-install-general-build-stdout.txt | 2 + .../XcFramework/import-macos-install-general.cmake | 1 + 9 files changed, 170 insertions(+) create mode 100644 Modules/PlatformSelectionFile.cmake.in create mode 100644 Tests/RunCMake/XcFramework/import-macos-build-general-build-stdout.txt create mode 100644 Tests/RunCMake/XcFramework/import-macos-build-general.cmake create mode 100644 Tests/RunCMake/XcFramework/import-macos-install-general-build-stdout.txt create mode 100644 Tests/RunCMake/XcFramework/import-macos-install-general.cmake diff --git a/Help/release/dev/install-export-xcframework.rst b/Help/release/dev/install-export-xcframework.rst index 90fce82..513a552 100644 --- a/Help/release/dev/install-export-xcframework.rst +++ b/Help/release/dev/install-export-xcframework.rst @@ -4,3 +4,6 @@ install-export-xcframework * The :command:`export(SETUP)` command gained a new ``XCFRAMEWORK_LOCATION`` argument, which can be used to specify the location of a ``.xcframework`` that can be substituted for the installed library. +* The :module:`CMakePackageConfigHelpers` module gained a new + :command:`generate_apple_platform_selection_file` function, which can be + used to generate a file that includes another Apple-platform-specific file. diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake index 581e65c..dabb635 100644 --- a/Modules/CMakePackageConfigHelpers.cmake +++ b/Modules/CMakePackageConfigHelpers.cmake @@ -190,6 +190,68 @@ Please note that these files are internal to CMake and you should not call :command:`configure_file()` on them yourself, but they can be used as starting point to create more sophisticated custom ``ConfigVersion.cmake`` files. +Generating an Apple Platform Selection File +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 3.29 + +.. command:: generate_apple_platform_selection_file + + Create an Apple platform selection file: + + generate_apple_platform_selection_file( + INSTALL_DESTINATION + [MACOS_CONFIG_FILE ] + [IOS_CONFIG_FILE ] + [IOS_SIMULATOR_CONFIG_FILE ] + [TVOS_CONFIG_FILE ] + [TVOS_SIMULATOR_CONFIG_FILE ] + [WATCHOS_CONFIG_FILE ] + [WATCHOS_SIMULATOR_CONFIG_FILE ] + [VISIONOS_CONFIG_FILE ] + [VISIONOS_SIMULATOR_CONFIG_FILE ] + ) + +Writes a file for use as ``Config.cmake`` which can include an +Apple-platform-specific ``Config.cmake`` from a different +directory. This can be used in conjunction with the ``XCFRAMEWORK_LOCATION`` +argument of :command:`export(SETUP)` to export packages in a way that a project +built for any Apple platform can use them. + +``INSTALL_DESTINATION `` + Path that the file will be installed to. + +``MACOS_CONFIG_FILE `` + File to include if the platform is macOS. + +``IOS_CONFIG_FILE `` + File to include if the platform is iOS. + +``IOS_SIMULATOR_CONFIG_FILE `` + File to include if the platform is iOS Simulator. + +``TVOS_CONFIG_FILE `` + File to include if the platform is tvOS. + +``TVOS_SIMULATOR_CONFIG_FILE `` + File to include if the platform is tvOS Simulator. + +``WATCHOS_CONFIG_FILE `` + File to include if the platform is watchOS. + +``WATCHOS_SIMULATOR_CONFIG_FILE `` + File to include if the platform is watchOS Simulator. + +``VISIONOS_CONFIG_FILE `` + File to include if the platform is visionOS. + +``VISIONOS_SIMULATOR_CONFIG_FILE `` + File to include if the platform is visionOS Simulator. + +If any of the optional config files are not specified, and the consuming +project is built for their corresponding platform, an error will be thrown +when including the generated file. + Example Generating Package Files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -344,3 +406,45 @@ endmacro() configure_file("${_inputFile}" "${_outputFile}" @ONLY) endfunction() + +function(generate_apple_platform_selection_file _output_file) + set(_config_file_options + MACOS_CONFIG_FILE + IOS_CONFIG_FILE + IOS_SIMULATOR_CONFIG_FILE + TVOS_CONFIG_FILE + TVOS_SIMULATOR_CONFIG_FILE + WATCHOS_CONFIG_FILE + WATCHOS_SIMULATOR_CONFIG_FILE + VISIONOS_CONFIG_FILE + VISIONOS_SIMULATOR_CONFIG_FILE + ) + + set(_options) + set(_single + INSTALL_DESTINATION + ${_config_file_options} + ) + set(_multi) + cmake_parse_arguments(PARSE_ARGV 0 _gpsf "${_options}" "${_single}" "${_multi}") + + set(_have_relative 0) + foreach(_opt IN LISTS _config_file_options) + if(_gpsf_${_opt}) + set(_config_file "${_gpsf_${_opt}}") + if(NOT IS_ABSOLUTE "${_config_file}") + string(PREPEND _config_file [[${PACKAGE_PREFIX_DIR}/]]) + set(_have_relative 1) + endif() + set(_branch_${_opt} "include(\"${_config_file}\")") + else() + set(_branch_${_opt} "message(FATAL_ERROR \"Platform not supported\")") + endif() + endforeach() + + configure_package_config_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/PlatformSelectionFile.cmake.in" "${_output_file}" + INSTALL_DESTINATION "${_gpsf_INSTALL_DESTINATION}" + NO_SET_AND_CHECK_MACRO + NO_CHECK_REQUIRED_COMPONENTS_MACRO + ) +endfunction() diff --git a/Modules/PlatformSelectionFile.cmake.in b/Modules/PlatformSelectionFile.cmake.in new file mode 100644 index 0000000..3f80f4b --- /dev/null +++ b/Modules/PlatformSelectionFile.cmake.in @@ -0,0 +1,24 @@ +@PACKAGE_INIT@ + +string(TOLOWER "${CMAKE_OSX_SYSROOT}" _CMAKE_OSX_SYSROOT_LOWER) +if(_CMAKE_OSX_SYSROOT_LOWER MATCHES "(^|/)iphonesimulator") + @_branch_IOS_SIMULATOR_CONFIG_FILE@ +elseif(_CMAKE_OSX_SYSROOT_LOWER MATCHES "(^|/)iphoneos") + @_branch_IOS_CONFIG_FILE@ +elseif(_CMAKE_OSX_SYSROOT_LOWER MATCHES "(^|/)tvsimulator") + @_branch_TVOS_SIMULATOR_CONFIG_FILE@ +elseif(_CMAKE_OSX_SYSROOT_LOWER MATCHES "(^|/)tvos") + @_branch_TVOS_CONFIG_FILE@ +elseif(_CMAKE_OSX_SYSROOT_LOWER MATCHES "(^|/)watchsimulator") + @_branch_WATCHOS_SIMULATOR_CONFIG_FILE@ +elseif(_CMAKE_OSX_SYSROOT_LOWER MATCHES "(^|/)watchos") + @_branch_WATCHOS_CONFIG_FILE@ +elseif(_CMAKE_OSX_SYSROOT_LOWER MATCHES "(^|/)xrsimulator") + @_branch_VISIONOS_SIMULATOR_CONFIG_FILE@ +elseif(_CMAKE_OSX_SYSROOT_LOWER MATCHES "(^|/)xros") + @_branch_VISIONOS_CONFIG_FILE@ +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + @_branch_MACOS_CONFIG_FILE@ +else() + message(FATAL_ERROR "Platform not supported") +endif() diff --git a/Tests/RunCMake/XcFramework/RunCMakeTest.cmake b/Tests/RunCMake/XcFramework/RunCMakeTest.cmake index 28e5035..1fef283 100644 --- a/Tests/RunCMake/XcFramework/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcFramework/RunCMakeTest.cmake @@ -222,3 +222,25 @@ endif() run_cmake_command(import-macos-build-specific-genex-build ${CMAKE_COMMAND} --build . ${_config_arg}) unset(RunCMake_TEST_NO_CLEAN) unset(RunCMake_TEST_BINARY_DIR) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/import-macos-install-general-build) +run_cmake_with_options(import-macos-install-general -DCMAKE_SYSTEM_NAME=Darwin -Dmylib_DIR=${RunCMake_BINARY_DIR}/export-install/lib/cmake/mylib) +set(RunCMake_TEST_NO_CLEAN 1) +set(_config_arg) +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(_config_arg --config Release) +endif() +run_cmake_command(import-macos-install-general-build ${CMAKE_COMMAND} --build . ${_config_arg}) +unset(RunCMake_TEST_NO_CLEAN) +unset(RunCMake_TEST_BINARY_DIR) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/import-macos-build-general-build) +run_cmake_with_options(import-macos-build-general -DCMAKE_SYSTEM_NAME=Darwin -Dmylib_DIR=${RunCMake_BINARY_DIR}/export-macos-build/lib/cmake/mylib) +set(RunCMake_TEST_NO_CLEAN 1) +set(_config_arg) +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(_config_arg --config Release) +endif() +run_cmake_command(import-macos-build-general-build ${CMAKE_COMMAND} --build . ${_config_arg}) +unset(RunCMake_TEST_NO_CLEAN) +unset(RunCMake_TEST_BINARY_DIR) diff --git a/Tests/RunCMake/XcFramework/export-macos.cmake b/Tests/RunCMake/XcFramework/export-macos.cmake index 4a9caa5..2fac14f 100644 --- a/Tests/RunCMake/XcFramework/export-macos.cmake +++ b/Tests/RunCMake/XcFramework/export-macos.cmake @@ -31,3 +31,14 @@ configure_package_config_file(mylib-config.cmake.in mylib-config-sub.cmake INSTA install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mylib-config-sub.cmake DESTINATION lib/macos/cmake/mylib RENAME mylib-config.cmake) configure_package_config_file(mylib-config.cmake.in lib/macos/cmake/mylib/mylib-config.cmake INSTALL_DESTINATION lib/macos/cmake/mylib) + +generate_apple_platform_selection_file(mylib-config-top.cmake + INSTALL_DESTINATION lib/cmake/mylib + MACOS_CONFIG_FILE lib/macos/cmake/mylib/mylib-config.cmake + ) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mylib-config-top.cmake DESTINATION lib/cmake/mylib RENAME mylib-config.cmake) + +generate_apple_platform_selection_file(lib/cmake/mylib/mylib-config.cmake + INSTALL_DESTINATION lib/cmake/mylib + MACOS_CONFIG_FILE lib/macos/cmake/mylib/mylib-config.cmake + ) diff --git a/Tests/RunCMake/XcFramework/import-macos-build-general-build-stdout.txt b/Tests/RunCMake/XcFramework/import-macos-build-general-build-stdout.txt new file mode 100644 index 0000000..3ac467d --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-build-general-build-stdout.txt @@ -0,0 +1,2 @@ +mylib location: [^ +]*/Tests/RunCMake/XcFramework/export-macos-build/lib/mylib\.xcframework/macos-(arm64|x86_64|arm64_x86_64)/libmylib\.a diff --git a/Tests/RunCMake/XcFramework/import-macos-build-general.cmake b/Tests/RunCMake/XcFramework/import-macos-build-general.cmake new file mode 100644 index 0000000..08ef6db --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-build-general.cmake @@ -0,0 +1 @@ +include(import-common.cmake) diff --git a/Tests/RunCMake/XcFramework/import-macos-install-general-build-stdout.txt b/Tests/RunCMake/XcFramework/import-macos-install-general-build-stdout.txt new file mode 100644 index 0000000..1421246 --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-install-general-build-stdout.txt @@ -0,0 +1,2 @@ +mylib location: [^ +]*/Tests/RunCMake/XcFramework/export-install/lib/mylib\.xcframework/macos-(arm64|x86_64|arm64_x86_64)/libmylib\.a diff --git a/Tests/RunCMake/XcFramework/import-macos-install-general.cmake b/Tests/RunCMake/XcFramework/import-macos-install-general.cmake new file mode 100644 index 0000000..08ef6db --- /dev/null +++ b/Tests/RunCMake/XcFramework/import-macos-install-general.cmake @@ -0,0 +1 @@ +include(import-common.cmake) -- cgit v0.12