| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #include "cmExportCMakeConfigGenerator.h"
- #include <algorithm>
- #include <cassert>
- #include <sstream>
- #include <utility>
- #include <vector>
- #include <cm/optional>
- #include <cm/string_view>
- #include <cmext/string_view>
- #include "cmExportSet.h"
- #include "cmFileSet.h"
- #include "cmFindPackageStack.h"
- #include "cmGeneratedFileStream.h"
- #include "cmGeneratorTarget.h"
- #include "cmLinkItem.h"
- #include "cmLocalGenerator.h"
- #include "cmMakefile.h"
- #include "cmMessageType.h"
- #include "cmOutputConverter.h"
- #include "cmPolicies.h"
- #include "cmStateTypes.h"
- #include "cmStringAlgorithms.h"
- #include "cmSystemTools.h"
- #include "cmTarget.h"
- #include "cmValue.h"
- #include "cmVersion.h"
- static std::string cmExportFileGeneratorEscape(std::string const& str)
- {
- // Escape a property value for writing into a .cmake file.
- std::string result = cmOutputConverter::EscapeForCMake(str);
- // Un-escape variable references generated by our own export code.
- cmSystemTools::ReplaceString(result, "\\${_IMPORT_PREFIX}",
- "${_IMPORT_PREFIX}");
- cmSystemTools::ReplaceString(result, "\\${CMAKE_IMPORT_LIBRARY_SUFFIX}",
- "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
- return result;
- }
- cmExportCMakeConfigGenerator::cmExportCMakeConfigGenerator() = default;
- cm::string_view cmExportCMakeConfigGenerator::GetImportPrefixWithSlash() const
- {
- return "${_IMPORT_PREFIX}/"_s;
- }
- bool cmExportCMakeConfigGenerator::GenerateImportFile(std::ostream& os)
- {
- std::stringstream mainFileWithHeadersAndFootersBuffer;
- // Start with the import file header.
- this->GenerateImportHeaderCode(mainFileWithHeadersAndFootersBuffer);
- // Create all the imported targets.
- std::stringstream mainFileBuffer;
- bool result = this->GenerateMainFile(mainFileBuffer);
- // Export find_dependency() calls. Must be done after GenerateMainFile(),
- // because that's when target dependencies are gathered, which we need for
- // the find_dependency() calls.
- if (!this->AppendMode && this->GetExportSet() &&
- this->ExportPackageDependencies) {
- this->SetRequiredCMakeVersion(3, 9, 0);
- this->GenerateFindDependencyCalls(mainFileWithHeadersAndFootersBuffer);
- }
- // Write cached import code.
- mainFileWithHeadersAndFootersBuffer << mainFileBuffer.rdbuf();
- // End with the import file footer.
- this->GenerateImportFooterCode(mainFileWithHeadersAndFootersBuffer);
- this->GeneratePolicyFooterCode(mainFileWithHeadersAndFootersBuffer);
- // This has to be done last, after the minimum CMake version has been
- // determined.
- this->GeneratePolicyHeaderCode(os);
- os << mainFileWithHeadersAndFootersBuffer.rdbuf();
- return result;
- }
- void cmExportCMakeConfigGenerator::GenerateInterfaceProperties(
- cmGeneratorTarget const* target, std::ostream& os,
- ImportPropertyMap const& properties)
- {
- if (!properties.empty()) {
- std::string targetName =
- cmStrCat(this->Namespace, target->GetExportName());
- os << "set_target_properties(" << targetName << " PROPERTIES\n";
- for (auto const& property : properties) {
- os << " " << property.first << " "
- << cmExportFileGeneratorEscape(property.second) << "\n";
- }
- os << ")\n\n";
- }
- }
- void cmExportCMakeConfigGenerator::SetImportLinkInterface(
- std::string const& config, std::string const& suffix,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- cmGeneratorTarget const* target, ImportPropertyMap& properties)
- {
- // Add the transitive link dependencies for this configuration.
- cmLinkInterface const* iface = target->GetLinkInterface(config, target);
- if (!iface) {
- return;
- }
- if (iface->ImplementationIsInterface) {
- // Policy CMP0022 must not be NEW.
- this->SetImportLinkProperty(
- suffix, target, "IMPORTED_LINK_INTERFACE_LIBRARIES", iface->Libraries,
- properties, ImportLinkPropertyTargetNames::Yes);
- return;
- }
- cmValue propContent;
- if (cmValue prop_suffixed =
- target->GetProperty("LINK_INTERFACE_LIBRARIES" + suffix)) {
- propContent = prop_suffixed;
- } else if (cmValue prop = target->GetProperty("LINK_INTERFACE_LIBRARIES")) {
- propContent = prop;
- } else {
- return;
- }
- bool const newCMP0022Behavior =
- target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
- target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
- if (newCMP0022Behavior && !this->ExportOld) {
- cmLocalGenerator* lg = target->GetLocalGenerator();
- std::ostringstream e;
- e << "Target \"" << target->GetName()
- << "\" has policy CMP0022 enabled, "
- "but also has old-style LINK_INTERFACE_LIBRARIES properties "
- "populated, but it was exported without the "
- "EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties";
- lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return;
- }
- if (propContent->empty()) {
- properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix].clear();
- return;
- }
- std::string prepro =
- cmGeneratorExpression::Preprocess(*propContent, preprocessRule);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, target,
- ReplaceFreeTargets);
- properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro;
- }
- }
- void cmExportCMakeConfigGenerator::GeneratePolicyHeaderCode(std::ostream& os)
- {
- // Protect that file against use with older CMake versions.
- /* clang-format off */
- os << "# Generated by CMake\n\n";
- os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.8)\n"
- << " message(FATAL_ERROR \"CMake >= "
- << this->RequiredCMakeVersionMajor << '.'
- << this->RequiredCMakeVersionMinor << '.'
- << this->RequiredCMakeVersionPatch << " required\")\n"
- << "endif()\n"
- << "if(CMAKE_VERSION VERSION_LESS \""
- << this->RequiredCMakeVersionMajor << '.'
- << this->RequiredCMakeVersionMinor << '.'
- << this->RequiredCMakeVersionPatch << "\")\n"
- << " message(FATAL_ERROR \"CMake >= "
- << this->RequiredCMakeVersionMajor << '.'
- << this->RequiredCMakeVersionMinor << '.'
- << this->RequiredCMakeVersionPatch << " required\")\n"
- << "endif()\n";
- /* clang-format on */
- // Isolate the file policy level.
- // Support CMake versions as far back as the
- // RequiredCMakeVersion{Major,Minor,Patch}, but also support using NEW
- // policy settings for up to CMake 3.29 (this upper limit may be reviewed
- // and increased from time to time). This reduces the opportunity for CMake
- // warnings when an older export file is later used with newer CMake
- // versions.
- /* clang-format off */
- os << "cmake_policy(PUSH)\n"
- << "cmake_policy(VERSION "
- << this->RequiredCMakeVersionMajor << '.'
- << this->RequiredCMakeVersionMinor << '.'
- << this->RequiredCMakeVersionPatch << "...3.29)\n";
- /* clang-format on */
- }
- void cmExportCMakeConfigGenerator::GeneratePolicyFooterCode(std::ostream& os)
- {
- os << "cmake_policy(POP)\n";
- }
- void cmExportCMakeConfigGenerator::GenerateImportHeaderCode(
- std::ostream& os, std::string const& config)
- {
- os << "#----------------------------------------------------------------\n"
- << "# Generated CMake target import file";
- if (!config.empty()) {
- os << " for configuration \"" << config << "\".\n";
- } else {
- os << ".\n";
- }
- os << "#----------------------------------------------------------------\n"
- << "\n";
- this->GenerateImportVersionCode(os);
- }
- void cmExportCMakeConfigGenerator::GenerateImportFooterCode(std::ostream& os)
- {
- os << "# Commands beyond this point should not need to know the version.\n"
- << "set(CMAKE_IMPORT_FILE_VERSION)\n";
- }
- void cmExportCMakeConfigGenerator::GenerateImportVersionCode(std::ostream& os)
- {
- // Store an import file format version. This will let us change the
- // format later while still allowing old import files to work.
- /* clang-format off */
- os << "# Commands may need to know the format version.\n"
- << "set(CMAKE_IMPORT_FILE_VERSION 1)\n"
- << "\n";
- /* clang-format on */
- }
- void cmExportCMakeConfigGenerator::GenerateExpectedTargetsCode(
- std::ostream& os, std::string const& expectedTargets)
- {
- /* clang-format off */
- os << "# Protect against multiple inclusion, which would fail when already "
- "imported targets are added once more.\n"
- "set(_cmake_targets_defined \"\")\n"
- "set(_cmake_targets_not_defined \"\")\n"
- "set(_cmake_expected_targets \"\")\n"
- "foreach(_cmake_expected_target IN ITEMS " << expectedTargets << ")\n"
- " list(APPEND _cmake_expected_targets \"${_cmake_expected_target}\")\n"
- " if(TARGET \"${_cmake_expected_target}\")\n"
- " list(APPEND _cmake_targets_defined \"${_cmake_expected_target}\")\n"
- " else()\n"
- " list(APPEND _cmake_targets_not_defined \"${_cmake_expected_target}\")\n"
- " endif()\n"
- "endforeach()\n"
- "unset(_cmake_expected_target)\n"
- "if(_cmake_targets_defined STREQUAL _cmake_expected_targets)\n"
- " unset(_cmake_targets_defined)\n"
- " unset(_cmake_targets_not_defined)\n"
- " unset(_cmake_expected_targets)\n"
- " unset(CMAKE_IMPORT_FILE_VERSION)\n"
- " cmake_policy(POP)\n"
- " return()\n"
- "endif()\n"
- "if(NOT _cmake_targets_defined STREQUAL \"\")\n"
- " string(REPLACE \";\" \", \" _cmake_targets_defined_text \"${_cmake_targets_defined}\")\n"
- " string(REPLACE \";\" \", \" _cmake_targets_not_defined_text \"${_cmake_targets_not_defined}\")\n"
- " message(FATAL_ERROR \"Some (but not all) targets in this export "
- "set were already defined.\\nTargets Defined: ${_cmake_targets_defined_text}\\n"
- "Targets not yet defined: ${_cmake_targets_not_defined_text}\\n\")\n"
- "endif()\n"
- "unset(_cmake_targets_defined)\n"
- "unset(_cmake_targets_not_defined)\n"
- "unset(_cmake_expected_targets)\n"
- "\n\n";
- /* clang-format on */
- }
- void cmExportCMakeConfigGenerator::GenerateImportTargetCode(
- std::ostream& os, cmGeneratorTarget const* target,
- cmStateEnums::TargetType targetType)
- {
- // Construct the imported target name.
- std::string targetName = this->Namespace;
- targetName += target->GetExportName();
- // Create the imported target.
- os << "# Create imported target " << targetName << "\n";
- switch (targetType) {
- case cmStateEnums::EXECUTABLE:
- os << "add_executable(" << targetName << " IMPORTED)\n";
- break;
- case cmStateEnums::STATIC_LIBRARY:
- os << "add_library(" << targetName << " STATIC IMPORTED)\n";
- break;
- case cmStateEnums::SHARED_LIBRARY:
- os << "add_library(" << targetName << " SHARED IMPORTED)\n";
- break;
- case cmStateEnums::MODULE_LIBRARY:
- os << "add_library(" << targetName << " MODULE IMPORTED)\n";
- break;
- case cmStateEnums::UNKNOWN_LIBRARY:
- os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n";
- break;
- case cmStateEnums::OBJECT_LIBRARY:
- os << "add_library(" << targetName << " OBJECT IMPORTED)\n";
- break;
- case cmStateEnums::INTERFACE_LIBRARY:
- os << "add_library(" << targetName << " INTERFACE IMPORTED)\n";
- break;
- default: // should never happen
- break;
- }
- // Mark the imported executable if it has exports.
- if (target->IsExecutableWithExports() ||
- (target->IsSharedLibraryWithExports() && target->HasImportLibrary(""))) {
- os << "set_property(TARGET " << targetName
- << " PROPERTY ENABLE_EXPORTS 1)\n";
- }
- // Mark the imported library if it is a framework.
- if (target->IsFrameworkOnApple()) {
- os << "set_property(TARGET " << targetName << " PROPERTY FRAMEWORK 1)\n";
- }
- // Mark the imported executable if it is an application bundle.
- if (target->IsAppBundleOnApple()) {
- os << "set_property(TARGET " << targetName
- << " PROPERTY MACOSX_BUNDLE 1)\n";
- }
- if (target->IsCFBundleOnApple()) {
- os << "set_property(TARGET " << targetName << " PROPERTY BUNDLE 1)\n";
- }
- // generate DEPRECATION
- if (target->IsDeprecated()) {
- os << "set_property(TARGET " << targetName << " PROPERTY DEPRECATION "
- << cmExportFileGeneratorEscape(target->GetDeprecation()) << ")\n";
- }
- if (target->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) {
- os << "set_property(TARGET " << targetName
- << " PROPERTY IMPORTED_NO_SYSTEM 1)\n";
- }
- if (target->GetPropertyAsBool("EXPORT_NO_SYSTEM")) {
- os << "set_property(TARGET " << targetName << " PROPERTY SYSTEM 0)\n";
- }
- os << "\n";
- }
- void cmExportCMakeConfigGenerator::GenerateImportPropertyCode(
- std::ostream& os, std::string const& config, std::string const& suffix,
- cmGeneratorTarget const* target, ImportPropertyMap const& properties,
- std::string const& importedXcFrameworkLocation)
- {
- // Construct the imported target name.
- std::string targetName = this->Namespace;
- targetName += target->GetExportName();
- // Set the import properties.
- os << "# Import target \"" << targetName << "\" for configuration \""
- << config << "\"\n";
- os << "set_property(TARGET " << targetName
- << " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
- if (!config.empty()) {
- os << cmSystemTools::UpperCase(config);
- } else {
- os << "NOCONFIG";
- }
- os << ")\n";
- os << "set_target_properties(" << targetName << " PROPERTIES\n";
- std::string importedLocationProp = cmStrCat("IMPORTED_LOCATION", suffix);
- for (auto const& property : properties) {
- if (importedXcFrameworkLocation.empty() ||
- property.first != importedLocationProp) {
- os << " " << property.first << " "
- << cmExportFileGeneratorEscape(property.second) << "\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 cmExportCMakeConfigGenerator::GenerateFindDependencyCalls(
- std::ostream& os)
- {
- os << "include(CMakeFindDependencyMacro)\n";
- std::map<std::string, cmExportSet::PackageDependency> packageDependencies;
- auto* exportSet = this->GetExportSet();
- if (exportSet) {
- packageDependencies = exportSet->GetPackageDependencies();
- }
- for (cmGeneratorTarget const* gt : this->ExternalTargets) {
- std::string findPackageName;
- auto exportFindPackageName = gt->GetProperty("EXPORT_FIND_PACKAGE_NAME");
- cmFindPackageStack pkgStack = gt->Target->GetFindPackageStack();
- if (!exportFindPackageName.IsEmpty()) {
- findPackageName = *exportFindPackageName;
- } else {
- if (!pkgStack.Empty()) {
- cmFindPackageCall const& fpc = pkgStack.Top();
- findPackageName = fpc.Name;
- }
- }
- if (!findPackageName.empty()) {
- auto& dep = packageDependencies[findPackageName];
- if (!pkgStack.Empty()) {
- dep.FindPackageIndex = pkgStack.Top().Index;
- }
- if (dep.Enabled == cmExportSet::PackageDependencyExportEnabled::Auto) {
- dep.Enabled = cmExportSet::PackageDependencyExportEnabled::On;
- }
- }
- }
- std::vector<std::pair<std::string, cmExportSet::PackageDependency>>
- packageDependenciesSorted(packageDependencies.begin(),
- packageDependencies.end());
- std::sort(
- packageDependenciesSorted.begin(), packageDependenciesSorted.end(),
- [](std::pair<std::string, cmExportSet::PackageDependency> const& lhs,
- std::pair<std::string, cmExportSet::PackageDependency> const& rhs)
- -> bool {
- if (lhs.second.SpecifiedIndex) {
- if (rhs.second.SpecifiedIndex) {
- return lhs.second.SpecifiedIndex < rhs.second.SpecifiedIndex;
- }
- assert(rhs.second.FindPackageIndex);
- return true;
- }
- assert(lhs.second.FindPackageIndex);
- if (rhs.second.SpecifiedIndex) {
- return false;
- }
- assert(rhs.second.FindPackageIndex);
- return lhs.second.FindPackageIndex < rhs.second.FindPackageIndex;
- });
- for (auto const& it : packageDependenciesSorted) {
- if (it.second.Enabled == cmExportSet::PackageDependencyExportEnabled::On) {
- os << "find_dependency(" << it.first;
- for (auto const& arg : it.second.ExtraArguments) {
- os << " " << cmOutputConverter::EscapeForCMake(arg);
- }
- os << ")\n";
- }
- }
- os << "\n\n";
- }
- void cmExportCMakeConfigGenerator::GenerateMissingTargetsCheckCode(
- std::ostream& os)
- {
- if (this->MissingTargets.empty()) {
- /* clang-format off */
- os << "# This file does not depend on other imported targets which have\n"
- "# been exported from the same project but in a separate "
- "export set.\n\n";
- /* clang-format on */
- return;
- }
- /* clang-format off */
- os << "# Make sure the targets which have been exported in some other\n"
- "# export set exist.\n"
- "unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
- "foreach(_target ";
- /* clang-format on */
- std::set<std::string> emitted;
- for (std::string const& missingTarget : this->MissingTargets) {
- if (emitted.insert(missingTarget).second) {
- os << "\"" << missingTarget << "\" ";
- }
- }
- /* clang-format off */
- os << ")\n"
- " if(NOT TARGET \"${_target}\" )\n"
- " set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets \""
- "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets} ${_target}\")"
- "\n"
- " endif()\n"
- "endforeach()\n"
- "\n"
- "if(DEFINED ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
- " if(CMAKE_FIND_PACKAGE_NAME)\n"
- " set( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
- " set( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
- "\"The following imported targets are "
- "referenced, but are missing: "
- "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}\")\n"
- " else()\n"
- " message(FATAL_ERROR \"The following imported targets are "
- "referenced, but are missing: "
- "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}\")\n"
- " endif()\n"
- "endif()\n"
- "unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
- "\n";
- /* clang-format on */
- }
- void cmExportCMakeConfigGenerator::GenerateImportedFileCheckLoop(
- std::ostream& os)
- {
- // Add code which verifies at cmake time that the file which is being
- // imported actually exists on disk. This should in theory always be theory
- // case, but still when packages are split into normal and development
- // packages this might get broken (e.g. the Config.cmake could be part of
- // the non-development package, something similar happened to me without
- // on SUSE with a mysql pkg-config file, which claimed everything is fine,
- // but the development package was not installed.).
- /* 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"
- " 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"
- "* An install or uninstall procedure did not complete successfully.\n"
- "* The installation package was faulty and contained\n"
- " \\\"${CMAKE_CURRENT_LIST_FILE}\\\"\n"
- "but not all the files it references.\n"
- "\")\n"
- " endif()\n"
- " endforeach()\n"
- " endif()\n"
- " unset(_cmake_file)\n"
- " unset(\"_cmake_import_check_files_for_${_cmake_target}\")\n"
- "endforeach()\n"
- "unset(_cmake_target)\n"
- "unset(_cmake_import_check_targets)\n"
- "\n";
- /* clang-format on */
- }
- void cmExportCMakeConfigGenerator::GenerateImportedFileChecksCode(
- std::ostream& os, cmGeneratorTarget const* target,
- ImportPropertyMap const& properties,
- std::set<std::string> const& importedLocations,
- std::string const& importedXcFrameworkLocation)
- {
- // Construct the imported target name.
- std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
- 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);
- if (pi != properties.end()) {
- os << cmExportFileGeneratorEscape(pi->second) << " ";
- }
- }
- os << ")\n\n";
- }
- void cmExportCMakeConfigGenerator::GenerateTargetFileSets(
- cmGeneratorTarget* gte, std::ostream& os, cmTargetExport const* te)
- {
- auto interfaceFileSets = gte->Target->GetAllInterfaceFileSets();
- if (!interfaceFileSets.empty()) {
- std::string targetName = cmStrCat(this->Namespace, gte->GetExportName());
- os << "if(NOT CMAKE_VERSION VERSION_LESS \"3.23.0\")\n"
- " target_sources("
- << targetName << "\n";
- for (auto const& name : interfaceFileSets) {
- auto* fileSet = gte->Target->GetFileSet(name);
- if (!fileSet) {
- gte->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("File set \"", name,
- "\" is listed in interface file sets of ", gte->GetName(),
- " but has not been created"));
- return;
- }
- os << " INTERFACE"
- << "\n FILE_SET " << cmOutputConverter::EscapeForCMake(name)
- << "\n TYPE "
- << cmOutputConverter::EscapeForCMake(fileSet->GetType())
- << "\n BASE_DIRS "
- << this->GetFileSetDirectories(gte, fileSet, te) << "\n FILES "
- << this->GetFileSetFiles(gte, fileSet, te) << "\n";
- }
- os << " )\nelse()\n set_property(TARGET " << targetName
- << "\n APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES";
- for (auto const& name : interfaceFileSets) {
- auto* fileSet = gte->Target->GetFileSet(name);
- if (!fileSet) {
- gte->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("File set \"", name,
- "\" is listed in interface file sets of ", gte->GetName(),
- " but has not been created"));
- return;
- }
- if (fileSet->GetType() == "HEADERS"_s) {
- os << "\n " << this->GetFileSetDirectories(gte, fileSet, te);
- }
- }
- os << "\n )\nendif()\n\n";
- }
- }
- std::string cmExportCMakeConfigGenerator::GetCxxModuleFile(
- std::string const& name) const
- {
- auto const& cxxModuleDirname = this->GetCxxModulesDirectory();
- if (cxxModuleDirname.empty()) {
- return {};
- }
- return cmStrCat(cmSystemTools::GetFilenamePath(this->MainImportFile), '/',
- cxxModuleDirname, "/cxx-modules-", name, ".cmake");
- }
- void cmExportCMakeConfigGenerator::GenerateCxxModuleInformation(
- std::string const& name, std::ostream& os)
- {
- auto const cxx_module_dirname = this->GetCxxModulesDirectory();
- if (cxx_module_dirname.empty()) {
- return;
- }
- // Write the include.
- os << "# Include C++ module properties\n"
- << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << cxx_module_dirname
- << "/cxx-modules-" << name << ".cmake\")\n\n";
- // Include all configuration-specific include files.
- cmGeneratedFileStream ap(this->GetCxxModuleFile(name), true);
- ap.SetCopyIfDifferent(true);
- this->GenerateCxxModuleConfigInformation(name, ap);
- }
- void cmExportCMakeConfigGenerator::SetRequiredCMakeVersion(unsigned int major,
- unsigned int minor,
- unsigned int patch)
- {
- if (CMake_VERSION_ENCODE(major, minor, patch) >
- CMake_VERSION_ENCODE(this->RequiredCMakeVersionMajor,
- this->RequiredCMakeVersionMinor,
- this->RequiredCMakeVersionPatch)) {
- this->RequiredCMakeVersionMajor = major;
- this->RequiredCMakeVersionMinor = minor;
- this->RequiredCMakeVersionPatch = patch;
- }
- }
|