|
@@ -3,29 +3,21 @@
|
|
#include "cmExportInstallFileGenerator.h"
|
|
#include "cmExportInstallFileGenerator.h"
|
|
|
|
|
|
#include <algorithm>
|
|
#include <algorithm>
|
|
|
|
+#include <cassert>
|
|
|
|
+#include <cstddef>
|
|
#include <memory>
|
|
#include <memory>
|
|
|
|
+#include <set>
|
|
#include <sstream>
|
|
#include <sstream>
|
|
-#include <utility>
|
|
|
|
-
|
|
|
|
-#include <cm/string_view>
|
|
|
|
-#include <cmext/string_view>
|
|
|
|
|
|
|
|
#include "cmExportSet.h"
|
|
#include "cmExportSet.h"
|
|
-#include "cmFileSet.h"
|
|
|
|
-#include "cmGeneratedFileStream.h"
|
|
|
|
-#include "cmGeneratorExpression.h"
|
|
|
|
#include "cmGeneratorTarget.h"
|
|
#include "cmGeneratorTarget.h"
|
|
#include "cmGlobalGenerator.h"
|
|
#include "cmGlobalGenerator.h"
|
|
-#include "cmInstallExportGenerator.h"
|
|
|
|
-#include "cmInstallFileSetGenerator.h"
|
|
|
|
#include "cmInstallTargetGenerator.h"
|
|
#include "cmInstallTargetGenerator.h"
|
|
#include "cmList.h"
|
|
#include "cmList.h"
|
|
#include "cmLocalGenerator.h"
|
|
#include "cmLocalGenerator.h"
|
|
#include "cmMakefile.h"
|
|
#include "cmMakefile.h"
|
|
#include "cmMessageType.h"
|
|
#include "cmMessageType.h"
|
|
-#include "cmOutputConverter.h"
|
|
|
|
#include "cmPolicies.h"
|
|
#include "cmPolicies.h"
|
|
-#include "cmStateTypes.h"
|
|
|
|
#include "cmStringAlgorithms.h"
|
|
#include "cmStringAlgorithms.h"
|
|
#include "cmSystemTools.h"
|
|
#include "cmSystemTools.h"
|
|
#include "cmTarget.h"
|
|
#include "cmTarget.h"
|
|
@@ -38,373 +30,75 @@ cmExportInstallFileGenerator::cmExportInstallFileGenerator(
|
|
{
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
-std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
|
|
|
|
|
|
+void cmExportInstallFileGenerator::ReplaceInstallPrefix(
|
|
|
|
+ std::string& input) const
|
|
{
|
|
{
|
|
- std::string glob = cmStrCat(this->FileBase, "-*", this->FileExt);
|
|
|
|
- return glob;
|
|
|
|
|
|
+ cmGeneratorExpression::ReplaceInstallPrefix(input, this->GetInstallPrefix());
|
|
}
|
|
}
|
|
|
|
|
|
-bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
|
|
|
|
|
|
+void cmExportInstallFileGenerator::PopulateImportProperties(
|
|
|
|
+ std::string const& config, std::string const& suffix,
|
|
|
|
+ cmTargetExport const* targetExport, ImportPropertyMap& properties,
|
|
|
|
+ std::set<std::string>& importedLocations)
|
|
{
|
|
{
|
|
- std::vector<cmTargetExport*> allTargets;
|
|
|
|
- {
|
|
|
|
- std::string expectedTargets;
|
|
|
|
- std::string sep;
|
|
|
|
- for (std::unique_ptr<cmTargetExport> const& te :
|
|
|
|
- this->IEGen->GetExportSet()->GetTargetExports()) {
|
|
|
|
- if (te->NamelinkOnly) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- expectedTargets += sep + this->Namespace + te->Target->GetExportName();
|
|
|
|
- sep = " ";
|
|
|
|
- if (this->ExportedTargets.insert(te->Target).second) {
|
|
|
|
- allTargets.push_back(te.get());
|
|
|
|
- } else {
|
|
|
|
- std::ostringstream e;
|
|
|
|
- e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName()
|
|
|
|
- << "\" ...) "
|
|
|
|
- << "includes target \"" << te->Target->GetName()
|
|
|
|
- << "\" more than once in the export set.";
|
|
|
|
- cmSystemTools::Error(e.str());
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- this->GenerateExpectedTargetsCode(os, expectedTargets);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Compute the relative import prefix for the file
|
|
|
|
- this->GenerateImportPrefix(os);
|
|
|
|
-
|
|
|
|
- bool requiresConfigFiles = false;
|
|
|
|
- // Create all the imported targets.
|
|
|
|
- for (cmTargetExport* te : allTargets) {
|
|
|
|
- cmGeneratorTarget* gt = te->Target;
|
|
|
|
- cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
|
|
|
|
-
|
|
|
|
- requiresConfigFiles =
|
|
|
|
- requiresConfigFiles || targetType != cmStateEnums::INTERFACE_LIBRARY;
|
|
|
|
-
|
|
|
|
- this->GenerateImportTargetCode(os, gt, targetType);
|
|
|
|
-
|
|
|
|
- ImportPropertyMap properties;
|
|
|
|
-
|
|
|
|
- std::string includesDestinationDirs;
|
|
|
|
- this->PopulateIncludeDirectoriesInterface(
|
|
|
|
- gt, cmGeneratorExpression::InstallInterface, properties, *te,
|
|
|
|
- includesDestinationDirs);
|
|
|
|
- this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
|
|
|
|
- properties);
|
|
|
|
- this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt,
|
|
|
|
- cmGeneratorExpression::InstallInterface,
|
|
|
|
- properties);
|
|
|
|
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", gt,
|
|
|
|
- cmGeneratorExpression::InstallInterface,
|
|
|
|
- properties);
|
|
|
|
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gt,
|
|
|
|
- cmGeneratorExpression::InstallInterface,
|
|
|
|
- properties);
|
|
|
|
- this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gt,
|
|
|
|
- cmGeneratorExpression::InstallInterface,
|
|
|
|
- properties);
|
|
|
|
- this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gt,
|
|
|
|
- cmGeneratorExpression::InstallInterface,
|
|
|
|
- properties);
|
|
|
|
- this->PopulateInterfaceProperty("INTERFACE_AUTOMOC_MACRO_NAMES", gt,
|
|
|
|
- cmGeneratorExpression::InstallInterface,
|
|
|
|
- properties);
|
|
|
|
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gt,
|
|
|
|
- cmGeneratorExpression::InstallInterface,
|
|
|
|
- properties);
|
|
|
|
- this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gt,
|
|
|
|
- cmGeneratorExpression::InstallInterface,
|
|
|
|
- properties);
|
|
|
|
- this->PopulateLinkDirectoriesInterface(
|
|
|
|
- gt, cmGeneratorExpression::InstallInterface, properties);
|
|
|
|
- this->PopulateLinkDependsInterface(
|
|
|
|
- gt, cmGeneratorExpression::InstallInterface, properties);
|
|
|
|
-
|
|
|
|
- std::string errorMessage;
|
|
|
|
- if (!this->PopulateCxxModuleExportProperties(
|
|
|
|
- gt, properties, cmGeneratorExpression::InstallInterface,
|
|
|
|
- includesDestinationDirs, errorMessage)) {
|
|
|
|
- cmSystemTools::Error(errorMessage);
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!this->PopulateExportProperties(gt, properties, errorMessage)) {
|
|
|
|
- cmSystemTools::Error(errorMessage);
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- const bool newCMP0022Behavior =
|
|
|
|
- gt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
|
|
|
|
- gt->GetPolicyStatusCMP0022() != cmPolicies::OLD;
|
|
|
|
- if (newCMP0022Behavior) {
|
|
|
|
- if (this->PopulateInterfaceLinkLibrariesProperty(
|
|
|
|
- gt, cmGeneratorExpression::InstallInterface, properties) &&
|
|
|
|
- !this->ExportOld) {
|
|
|
|
- this->SetRequiredCMakeVersion(2, 8, 12);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (targetType == cmStateEnums::INTERFACE_LIBRARY) {
|
|
|
|
- this->SetRequiredCMakeVersion(3, 0, 0);
|
|
|
|
- }
|
|
|
|
- if (gt->GetProperty("INTERFACE_SOURCES")) {
|
|
|
|
- // We can only generate INTERFACE_SOURCES in CMake 3.3, but CMake 3.1
|
|
|
|
- // can consume them.
|
|
|
|
- this->SetRequiredCMakeVersion(3, 1, 0);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gt,
|
|
|
|
- properties);
|
|
|
|
-
|
|
|
|
- this->PopulateCompatibleInterfaceProperties(gt, properties);
|
|
|
|
- this->PopulateCustomTransitiveInterfaceProperties(
|
|
|
|
- gt, cmGeneratorExpression::InstallInterface, properties);
|
|
|
|
-
|
|
|
|
- this->GenerateInterfaceProperties(gt, os, properties);
|
|
|
|
-
|
|
|
|
- this->GenerateTargetFileSets(gt, os, te);
|
|
|
|
|
|
+ this->SetImportLocationProperty(config, suffix,
|
|
|
|
+ targetExport->ArchiveGenerator, properties,
|
|
|
|
+ importedLocations);
|
|
|
|
+ this->SetImportLocationProperty(config, suffix,
|
|
|
|
+ targetExport->LibraryGenerator, properties,
|
|
|
|
+ importedLocations);
|
|
|
|
+ this->SetImportLocationProperty(config, suffix,
|
|
|
|
+ targetExport->RuntimeGenerator, properties,
|
|
|
|
+ importedLocations);
|
|
|
|
+ this->SetImportLocationProperty(config, suffix,
|
|
|
|
+ targetExport->ObjectsGenerator, properties,
|
|
|
|
+ importedLocations);
|
|
|
|
+ this->SetImportLocationProperty(config, suffix,
|
|
|
|
+ targetExport->FrameworkGenerator, properties,
|
|
|
|
+ importedLocations);
|
|
|
|
+ this->SetImportLocationProperty(config, suffix,
|
|
|
|
+ targetExport->BundleGenerator, properties,
|
|
|
|
+ importedLocations);
|
|
|
|
+
|
|
|
|
+ // If any file location was set for the target add it to the
|
|
|
|
+ // import file.
|
|
|
|
+ if (!properties.empty()) {
|
|
|
|
+ // Get the rest of the target details.
|
|
|
|
+ cmGeneratorTarget const* const gtgt = targetExport->Target;
|
|
|
|
+ this->SetImportDetailProperties(config, suffix, gtgt, properties);
|
|
|
|
+
|
|
|
|
+ // TODO: PUBLIC_HEADER_LOCATION
|
|
|
|
+ // This should wait until the build feature propagation stuff is done.
|
|
|
|
+ // Then this can be a propagated include directory.
|
|
|
|
+ // this->GenerateImportProperty(config, te->HeaderGenerator, properties);
|
|
}
|
|
}
|
|
-
|
|
|
|
- this->LoadConfigFiles(os);
|
|
|
|
-
|
|
|
|
- bool result = true;
|
|
|
|
-
|
|
|
|
- std::string cxx_modules_name = this->IEGen->GetExportSet()->GetName();
|
|
|
|
- this->GenerateCxxModuleInformation(cxx_modules_name, os);
|
|
|
|
- if (requiresConfigFiles) {
|
|
|
|
- for (std::string const& c : this->Configurations) {
|
|
|
|
- if (!this->GenerateImportCxxModuleConfigTargetInclusion(cxx_modules_name,
|
|
|
|
- c)) {
|
|
|
|
- result = false;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- this->CleanupTemporaryVariables(os);
|
|
|
|
- this->GenerateImportedFileCheckLoop(os);
|
|
|
|
-
|
|
|
|
- // Generate an import file for each configuration.
|
|
|
|
- // Don't do this if we only export INTERFACE_LIBRARY targets.
|
|
|
|
- if (requiresConfigFiles) {
|
|
|
|
- for (std::string const& c : this->Configurations) {
|
|
|
|
- if (!this->GenerateImportFileConfig(c)) {
|
|
|
|
- result = false;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- this->GenerateMissingTargetsCheckCode(os);
|
|
|
|
-
|
|
|
|
- return result;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-void cmExportInstallFileGenerator::GenerateImportPrefix(std::ostream& os)
|
|
|
|
|
|
+std::string cmExportInstallFileGenerator::GetImportXcFrameworkLocation(
|
|
|
|
+ std::string const& config, cmTargetExport const* targetExport) const
|
|
{
|
|
{
|
|
- // Set an _IMPORT_PREFIX variable for import location properties
|
|
|
|
- // to reference if they are relative to the install prefix.
|
|
|
|
- std::string installPrefix =
|
|
|
|
- this->IEGen->GetLocalGenerator()->GetMakefile()->GetSafeDefinition(
|
|
|
|
- "CMAKE_INSTALL_PREFIX");
|
|
|
|
- std::string const& expDest = this->IEGen->GetDestination();
|
|
|
|
- if (cmSystemTools::FileIsFullPath(expDest)) {
|
|
|
|
- // The export file is being installed to an absolute path so the
|
|
|
|
- // package is not relocatable. Use the configured install prefix.
|
|
|
|
- /* clang-format off */
|
|
|
|
- os <<
|
|
|
|
- "# The installation prefix configured by this project.\n"
|
|
|
|
- "set(_IMPORT_PREFIX \"" << installPrefix << "\")\n"
|
|
|
|
- "\n";
|
|
|
|
- /* clang-format on */
|
|
|
|
- } else {
|
|
|
|
- // Add code to compute the installation prefix relative to the
|
|
|
|
- // import file location.
|
|
|
|
- std::string absDest = installPrefix + "/" + expDest;
|
|
|
|
- std::string absDestS = absDest + "/";
|
|
|
|
- os << "# Compute the installation prefix relative to this file.\n"
|
|
|
|
- << "get_filename_component(_IMPORT_PREFIX"
|
|
|
|
- << " \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
|
|
|
|
- if (cmHasLiteralPrefix(absDestS, "/lib/") ||
|
|
|
|
- cmHasLiteralPrefix(absDestS, "/lib64/") ||
|
|
|
|
- cmHasLiteralPrefix(absDestS, "/libx32/") ||
|
|
|
|
- cmHasLiteralPrefix(absDestS, "/usr/lib/") ||
|
|
|
|
- cmHasLiteralPrefix(absDestS, "/usr/lib64/") ||
|
|
|
|
- cmHasLiteralPrefix(absDestS, "/usr/libx32/")) {
|
|
|
|
- // Handle "/usr move" symlinks created by some Linux distros.
|
|
|
|
- /* clang-format off */
|
|
|
|
- os <<
|
|
|
|
- "# Use original install prefix when loaded through a\n"
|
|
|
|
- "# cross-prefix symbolic link such as /lib -> /usr/lib.\n"
|
|
|
|
- "get_filename_component(_realCurr \"${_IMPORT_PREFIX}\" REALPATH)\n"
|
|
|
|
- "get_filename_component(_realOrig \"" << absDest << "\" REALPATH)\n"
|
|
|
|
- "if(_realCurr STREQUAL _realOrig)\n"
|
|
|
|
- " set(_IMPORT_PREFIX \"" << absDest << "\")\n"
|
|
|
|
- "endif()\n"
|
|
|
|
- "unset(_realOrig)\n"
|
|
|
|
- "unset(_realCurr)\n";
|
|
|
|
- /* clang-format on */
|
|
|
|
- }
|
|
|
|
- std::string dest = expDest;
|
|
|
|
- while (!dest.empty()) {
|
|
|
|
- os << "get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" "
|
|
|
|
- "PATH)\n";
|
|
|
|
- dest = cmSystemTools::GetFilenamePath(dest);
|
|
|
|
|
|
+ std::string importedXcFrameworkLocation = targetExport->XcFrameworkLocation;
|
|
|
|
+ if (!importedXcFrameworkLocation.empty()) {
|
|
|
|
+ importedXcFrameworkLocation = cmGeneratorExpression::Preprocess(
|
|
|
|
+ importedXcFrameworkLocation,
|
|
|
|
+ cmGeneratorExpression::PreprocessContext::InstallInterface, true);
|
|
|
|
+ importedXcFrameworkLocation = cmGeneratorExpression::Evaluate(
|
|
|
|
+ importedXcFrameworkLocation, targetExport->Target->GetLocalGenerator(),
|
|
|
|
+ config, targetExport->Target, nullptr, targetExport->Target);
|
|
|
|
+ if (!importedXcFrameworkLocation.empty() &&
|
|
|
|
+ !cmSystemTools::FileIsFullPath(importedXcFrameworkLocation) &&
|
|
|
|
+ !cmHasPrefix(importedXcFrameworkLocation,
|
|
|
|
+ this->GetImportPrefixWithSlash())) {
|
|
|
|
+ return cmStrCat(this->GetImportPrefixWithSlash(),
|
|
|
|
+ importedXcFrameworkLocation);
|
|
}
|
|
}
|
|
- os << "if(_IMPORT_PREFIX STREQUAL \"/\")\n"
|
|
|
|
- << " set(_IMPORT_PREFIX \"\")\n"
|
|
|
|
- << "endif()\n"
|
|
|
|
- << "\n";
|
|
|
|
}
|
|
}
|
|
-}
|
|
|
|
|
|
|
|
-void cmExportInstallFileGenerator::CleanupTemporaryVariables(std::ostream& os)
|
|
|
|
-{
|
|
|
|
- /* clang-format off */
|
|
|
|
- os << "# Cleanup temporary variables.\n"
|
|
|
|
- << "set(_IMPORT_PREFIX)\n"
|
|
|
|
- << "\n";
|
|
|
|
- /* clang-format on */
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void cmExportInstallFileGenerator::LoadConfigFiles(std::ostream& os)
|
|
|
|
-{
|
|
|
|
- // Now load per-configuration properties for them.
|
|
|
|
- /* clang-format off */
|
|
|
|
- os << "# Load information for each installed configuration.\n"
|
|
|
|
- << "file(GLOB _cmake_config_files \"${CMAKE_CURRENT_LIST_DIR}/"
|
|
|
|
- << this->GetConfigImportFileGlob() << "\")\n"
|
|
|
|
- << "foreach(_cmake_config_file IN LISTS _cmake_config_files)\n"
|
|
|
|
- << " include(\"${_cmake_config_file}\")\n"
|
|
|
|
- << "endforeach()\n"
|
|
|
|
- << "unset(_cmake_config_file)\n"
|
|
|
|
- << "unset(_cmake_config_files)\n"
|
|
|
|
- << "\n";
|
|
|
|
- /* clang-format on */
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string& input)
|
|
|
|
-{
|
|
|
|
- cmGeneratorExpression::ReplaceInstallPrefix(input, "${_IMPORT_PREFIX}");
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-bool cmExportInstallFileGenerator::GenerateImportFileConfig(
|
|
|
|
- const std::string& config)
|
|
|
|
-{
|
|
|
|
- // Skip configurations not enabled for this export.
|
|
|
|
- if (!this->IEGen->InstallsForConfig(config)) {
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Construct the name of the file to generate.
|
|
|
|
- std::string fileName = cmStrCat(this->FileDir, '/', this->FileBase, '-');
|
|
|
|
- if (!config.empty()) {
|
|
|
|
- fileName += cmSystemTools::LowerCase(config);
|
|
|
|
- } else {
|
|
|
|
- fileName += "noconfig";
|
|
|
|
- }
|
|
|
|
- fileName += this->FileExt;
|
|
|
|
-
|
|
|
|
- // Open the output file to generate it.
|
|
|
|
- cmGeneratedFileStream exportFileStream(fileName, true);
|
|
|
|
- if (!exportFileStream) {
|
|
|
|
- std::string se = cmSystemTools::GetLastSystemError();
|
|
|
|
- std::ostringstream e;
|
|
|
|
- e << "cannot write to file \"" << fileName << "\": " << se;
|
|
|
|
- cmSystemTools::Error(e.str());
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
- exportFileStream.SetCopyIfDifferent(true);
|
|
|
|
- std::ostream& os = exportFileStream;
|
|
|
|
-
|
|
|
|
- // Start with the import file header.
|
|
|
|
- this->GenerateImportHeaderCode(os, config);
|
|
|
|
-
|
|
|
|
- // Generate the per-config target information.
|
|
|
|
- this->GenerateImportConfig(os, config);
|
|
|
|
-
|
|
|
|
- // End with the import file footer.
|
|
|
|
- this->GenerateImportFooterCode(os);
|
|
|
|
-
|
|
|
|
- // Record this per-config import file.
|
|
|
|
- this->ConfigImportFiles[config] = fileName;
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
|
|
|
|
- std::ostream& os, const std::string& config, std::string const& suffix)
|
|
|
|
-{
|
|
|
|
- // Add each target in the set to the export.
|
|
|
|
- for (std::unique_ptr<cmTargetExport> const& te :
|
|
|
|
- this->IEGen->GetExportSet()->GetTargetExports()) {
|
|
|
|
- // Collect import properties for this target.
|
|
|
|
- if (this->GetExportTargetType(te.get()) ==
|
|
|
|
- cmStateEnums::INTERFACE_LIBRARY) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- ImportPropertyMap properties;
|
|
|
|
- std::set<std::string> importedLocations;
|
|
|
|
-
|
|
|
|
- this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
|
|
|
|
- properties, importedLocations);
|
|
|
|
- this->SetImportLocationProperty(config, suffix, te->LibraryGenerator,
|
|
|
|
- properties, importedLocations);
|
|
|
|
- this->SetImportLocationProperty(config, suffix, te->RuntimeGenerator,
|
|
|
|
- properties, importedLocations);
|
|
|
|
- this->SetImportLocationProperty(config, suffix, te->ObjectsGenerator,
|
|
|
|
- properties, importedLocations);
|
|
|
|
- this->SetImportLocationProperty(config, suffix, te->FrameworkGenerator,
|
|
|
|
- properties, importedLocations);
|
|
|
|
- this->SetImportLocationProperty(config, suffix, te->BundleGenerator,
|
|
|
|
- properties, importedLocations);
|
|
|
|
-
|
|
|
|
- // If any file location was set for the target add it to the
|
|
|
|
- // import file.
|
|
|
|
- if (!properties.empty()) {
|
|
|
|
- // Get the rest of the target details.
|
|
|
|
- cmGeneratorTarget* gtgt = te->Target;
|
|
|
|
- this->SetImportDetailProperties(config, suffix, gtgt, properties);
|
|
|
|
-
|
|
|
|
- this->SetImportLinkInterface(config, suffix,
|
|
|
|
- cmGeneratorExpression::InstallInterface,
|
|
|
|
- gtgt, properties);
|
|
|
|
-
|
|
|
|
- // TODO: PUBLIC_HEADER_LOCATION
|
|
|
|
- // This should wait until the build feature propagation stuff
|
|
|
|
- // is done. Then this can be a propagated include directory.
|
|
|
|
- // this->GenerateImportProperty(config, te->HeaderGenerator,
|
|
|
|
- // properties);
|
|
|
|
-
|
|
|
|
- // Generate code in the export file.
|
|
|
|
- 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);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ return importedXcFrameworkLocation;
|
|
}
|
|
}
|
|
|
|
|
|
void cmExportInstallFileGenerator::SetImportLocationProperty(
|
|
void cmExportInstallFileGenerator::SetImportLocationProperty(
|
|
- const std::string& config, std::string const& suffix,
|
|
|
|
|
|
+ std::string const& config, std::string const& suffix,
|
|
cmInstallTargetGenerator* itgen, ImportPropertyMap& properties,
|
|
cmInstallTargetGenerator* itgen, ImportPropertyMap& properties,
|
|
std::set<std::string>& importedLocations)
|
|
std::set<std::string>& importedLocations)
|
|
{
|
|
{
|
|
@@ -501,11 +195,16 @@ cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
|
|
return targetType;
|
|
return targetType;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+std::string const& cmExportInstallFileGenerator::GetExportName() const
|
|
|
|
+{
|
|
|
|
+ return this->GetExportSet()->GetName();
|
|
|
|
+}
|
|
|
|
+
|
|
void cmExportInstallFileGenerator::HandleMissingTarget(
|
|
void cmExportInstallFileGenerator::HandleMissingTarget(
|
|
std::string& link_libs, cmGeneratorTarget const* depender,
|
|
std::string& link_libs, cmGeneratorTarget const* depender,
|
|
cmGeneratorTarget* dependee)
|
|
cmGeneratorTarget* dependee)
|
|
{
|
|
{
|
|
- const std::string name = dependee->GetName();
|
|
|
|
|
|
+ std::string const& name = dependee->GetName();
|
|
cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator();
|
|
cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator();
|
|
auto exportInfo = this->FindNamespaces(gg, name);
|
|
auto exportInfo = this->FindNamespaces(gg, name);
|
|
std::vector<std::string> const& exportFiles = exportInfo.first;
|
|
std::vector<std::string> const& exportFiles = exportInfo.first;
|
|
@@ -524,14 +223,14 @@ void cmExportInstallFileGenerator::HandleMissingTarget(
|
|
|
|
|
|
std::pair<std::vector<std::string>, std::string>
|
|
std::pair<std::vector<std::string>, std::string>
|
|
cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg,
|
|
cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg,
|
|
- const std::string& name)
|
|
|
|
|
|
+ std::string const& name) const
|
|
{
|
|
{
|
|
std::vector<std::string> exportFiles;
|
|
std::vector<std::string> exportFiles;
|
|
std::string ns;
|
|
std::string ns;
|
|
- const cmExportSetMap& exportSets = gg->GetExportSets();
|
|
|
|
|
|
+ cmExportSetMap const& exportSets = gg->GetExportSets();
|
|
|
|
|
|
for (auto const& expIt : exportSets) {
|
|
for (auto const& expIt : exportSets) {
|
|
- const cmExportSet& exportSet = expIt.second;
|
|
|
|
|
|
+ cmExportSet const& exportSet = expIt.second;
|
|
|
|
|
|
bool containsTarget = false;
|
|
bool containsTarget = false;
|
|
for (auto const& target : exportSet.GetTargetExports()) {
|
|
for (auto const& target : exportSet.GetTargetExports()) {
|
|
@@ -556,11 +255,11 @@ cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg,
|
|
|
|
|
|
void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
|
|
void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
|
|
cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
|
|
cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
|
|
- std::vector<std::string> const& exportFiles)
|
|
|
|
|
|
+ std::vector<std::string> const& exportFiles) const
|
|
{
|
|
{
|
|
std::ostringstream e;
|
|
std::ostringstream e;
|
|
- e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName()
|
|
|
|
- << "\" ...) "
|
|
|
|
|
|
+ e << "install(" << this->IEGen->InstallSubcommand() << " \""
|
|
|
|
+ << this->GetExportName() << "\" ...) "
|
|
<< "includes target \"" << depender->GetName()
|
|
<< "includes target \"" << depender->GetName()
|
|
<< "\" which requires target \"" << dependee->GetName() << "\" ";
|
|
<< "\" which requires target \"" << dependee->GetName() << "\" ";
|
|
if (exportFiles.empty()) {
|
|
if (exportFiles.empty()) {
|
|
@@ -573,220 +272,371 @@ void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
|
|
"\""
|
|
"\""
|
|
<< dependee->GetName() << "\" target to a single export.";
|
|
<< dependee->GetName() << "\" target to a single export.";
|
|
}
|
|
}
|
|
- cmSystemTools::Error(e.str());
|
|
|
|
|
|
+ this->ReportError(e.str());
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void cmExportInstallFileGenerator::ComplainAboutDuplicateTarget(
|
|
|
|
+ std::string const& targetName) const
|
|
|
|
+{
|
|
|
|
+ std::ostringstream e;
|
|
|
|
+ e << "install(" << this->IEGen->InstallSubcommand() << " \""
|
|
|
|
+ << this->GetExportName() << "\" ...) "
|
|
|
|
+ << "includes target \"" << targetName
|
|
|
|
+ << "\" more than once in the export set.";
|
|
|
|
+ this->ReportError(e.str());
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void cmExportInstallFileGenerator::ReportError(
|
|
|
|
+ std::string const& errorMessage) const
|
|
|
|
+{
|
|
|
|
+ cmSystemTools::Error(errorMessage);
|
|
}
|
|
}
|
|
|
|
|
|
std::string cmExportInstallFileGenerator::InstallNameDir(
|
|
std::string cmExportInstallFileGenerator::InstallNameDir(
|
|
- cmGeneratorTarget const* target, const std::string& config)
|
|
|
|
|
|
+ cmGeneratorTarget const* target, std::string const& config)
|
|
{
|
|
{
|
|
std::string install_name_dir;
|
|
std::string install_name_dir;
|
|
|
|
|
|
cmMakefile* mf = target->Target->GetMakefile();
|
|
cmMakefile* mf = target->Target->GetMakefile();
|
|
if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
|
|
if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
|
|
- install_name_dir =
|
|
|
|
- target->GetInstallNameDirForInstallTree(config, "${_IMPORT_PREFIX}");
|
|
|
|
|
|
+ auto const& prefix = this->GetInstallPrefix();
|
|
|
|
+ install_name_dir = target->GetInstallNameDirForInstallTree(config, prefix);
|
|
}
|
|
}
|
|
|
|
|
|
return install_name_dir;
|
|
return install_name_dir;
|
|
}
|
|
}
|
|
|
|
|
|
-namespace {
|
|
|
|
-bool EntryIsContextSensitive(
|
|
|
|
- const std::unique_ptr<cmCompiledGeneratorExpression>& cge)
|
|
|
|
|
|
+std::string cmExportInstallFileGenerator::GetCxxModuleFile() const
|
|
{
|
|
{
|
|
- return cge->GetHadContextSensitiveCondition();
|
|
|
|
-}
|
|
|
|
|
|
+ return this->GetCxxModuleFile(this->GetExportSet()->GetName());
|
|
}
|
|
}
|
|
|
|
|
|
-std::string cmExportInstallFileGenerator::GetFileSetDirectories(
|
|
|
|
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te)
|
|
|
|
|
|
+bool cmExportInstallFileGenerator::CollectExports(
|
|
|
|
+ std::function<void(cmTargetExport const*)> const& visitor)
|
|
{
|
|
{
|
|
- std::vector<std::string> resultVector;
|
|
|
|
-
|
|
|
|
- auto configs =
|
|
|
|
- gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
|
|
|
-
|
|
|
|
- cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance());
|
|
|
|
- auto cge = ge.Parse(te->FileSetGenerators.at(fileSet)->GetDestination());
|
|
|
|
-
|
|
|
|
- for (auto const& config : configs) {
|
|
|
|
- auto unescapedDest = cge->Evaluate(gte->LocalGenerator, config, gte);
|
|
|
|
- auto dest = cmOutputConverter::EscapeForCMake(
|
|
|
|
- unescapedDest, cmOutputConverter::WrapQuotes::NoWrap);
|
|
|
|
- if (!cmSystemTools::FileIsFullPath(unescapedDest)) {
|
|
|
|
- dest = cmStrCat("${_IMPORT_PREFIX}/", dest);
|
|
|
|
|
|
+ auto pred = [&](std::unique_ptr<cmTargetExport> const& te) -> bool {
|
|
|
|
+ if (te->NamelinkOnly) {
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
-
|
|
|
|
- auto const& type = fileSet->GetType();
|
|
|
|
- // C++ modules do not support interface file sets which are dependent upon
|
|
|
|
- // the configuration.
|
|
|
|
- if (cge->GetHadContextSensitiveCondition() && type == "CXX_MODULES"_s) {
|
|
|
|
- auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
|
|
|
|
- std::ostringstream e;
|
|
|
|
- e << "The \"" << gte->GetName() << "\" target's interface file set \""
|
|
|
|
- << fileSet->GetName() << "\" of type \"" << type
|
|
|
|
- << "\" contains context-sensitive base file entries which is not "
|
|
|
|
- "supported.";
|
|
|
|
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
|
|
|
|
- return std::string{};
|
|
|
|
|
|
+ if (this->ExportedTargets.insert(te->Target).second) {
|
|
|
|
+ visitor(te.get());
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
- if (cge->GetHadContextSensitiveCondition() && configs.size() != 1) {
|
|
|
|
- resultVector.push_back(
|
|
|
|
- cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\""));
|
|
|
|
- } else {
|
|
|
|
- resultVector.emplace_back(cmStrCat('"', dest, '"'));
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ this->ComplainAboutDuplicateTarget(te->Target->GetName());
|
|
|
|
+ return false;
|
|
|
|
+ };
|
|
|
|
|
|
- return cmJoin(resultVector, " ");
|
|
|
|
|
|
+ auto const& targets = this->GetExportSet()->GetTargetExports();
|
|
|
|
+ return std::all_of(targets.begin(), targets.end(), pred);
|
|
}
|
|
}
|
|
|
|
|
|
-std::string cmExportInstallFileGenerator::GetFileSetFiles(
|
|
|
|
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te)
|
|
|
|
|
|
+bool cmExportInstallFileGenerator::PopulateInterfaceProperties(
|
|
|
|
+ cmTargetExport const* targetExport, ImportPropertyMap& properties)
|
|
{
|
|
{
|
|
- std::vector<std::string> resultVector;
|
|
|
|
|
|
+ cmGeneratorTarget const* const gt = targetExport->Target;
|
|
|
|
+
|
|
|
|
+ std::string includesDestinationDirs;
|
|
|
|
+ this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt,
|
|
|
|
+ cmGeneratorExpression::InstallInterface,
|
|
|
|
+ properties);
|
|
|
|
+ this->PopulateIncludeDirectoriesInterface(
|
|
|
|
+ gt, cmGeneratorExpression::InstallInterface, properties, *targetExport,
|
|
|
|
+ includesDestinationDirs);
|
|
|
|
+ this->PopulateLinkDirectoriesInterface(
|
|
|
|
+ gt, cmGeneratorExpression::InstallInterface, properties);
|
|
|
|
+ this->PopulateLinkDependsInterface(
|
|
|
|
+ gt, cmGeneratorExpression::InstallInterface, properties);
|
|
|
|
+ this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
|
|
|
|
+ properties);
|
|
|
|
+
|
|
|
|
+ return this->PopulateInterfaceProperties(
|
|
|
|
+ gt, includesDestinationDirs, cmGeneratorExpression::InstallInterface,
|
|
|
|
+ properties);
|
|
|
|
+}
|
|
|
|
|
|
- auto configs =
|
|
|
|
- gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
|
|
|
|
|
+namespace {
|
|
|
|
+bool isSubDirectory(std::string const& a, std::string const& b)
|
|
|
|
+{
|
|
|
|
+ return (cmSystemTools::ComparePath(a, b) ||
|
|
|
|
+ cmSystemTools::IsSubDirectory(a, b));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool checkInterfaceDirs(std::string const& prepro,
|
|
|
|
+ cmGeneratorTarget const* target,
|
|
|
|
+ std::string const& prop)
|
|
|
|
+{
|
|
|
|
+ std::string const& installDir =
|
|
|
|
+ target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
|
|
|
|
+ std::string const& topSourceDir =
|
|
|
|
+ target->GetLocalGenerator()->GetSourceDirectory();
|
|
|
|
+ std::string const& topBinaryDir =
|
|
|
|
+ target->GetLocalGenerator()->GetBinaryDirectory();
|
|
|
|
|
|
- auto fileEntries = fileSet->CompileFileEntries();
|
|
|
|
- auto directoryEntries = fileSet->CompileDirectoryEntries();
|
|
|
|
|
|
+ std::vector<std::string> parts;
|
|
|
|
+ cmGeneratorExpression::Split(prepro, parts);
|
|
|
|
|
|
- cmGeneratorExpression destGe(*gte->Makefile->GetCMakeInstance());
|
|
|
|
- auto destCge =
|
|
|
|
- destGe.Parse(te->FileSetGenerators.at(fileSet)->GetDestination());
|
|
|
|
|
|
+ bool const inSourceBuild = topSourceDir == topBinaryDir;
|
|
|
|
|
|
- for (auto const& config : configs) {
|
|
|
|
- auto directories = fileSet->EvaluateDirectoryEntries(
|
|
|
|
- directoryEntries, gte->LocalGenerator, config, gte);
|
|
|
|
|
|
+ bool hadFatalError = false;
|
|
|
|
|
|
- std::map<std::string, std::vector<std::string>> files;
|
|
|
|
- for (auto const& entry : fileEntries) {
|
|
|
|
- fileSet->EvaluateFileEntry(directories, files, entry,
|
|
|
|
- gte->LocalGenerator, config, gte);
|
|
|
|
|
|
+ for (std::string const& li : parts) {
|
|
|
|
+ size_t genexPos = cmGeneratorExpression::Find(li);
|
|
|
|
+ if (genexPos == 0) {
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
- auto unescapedDest = destCge->Evaluate(gte->LocalGenerator, config, gte);
|
|
|
|
- auto dest =
|
|
|
|
- cmStrCat(cmOutputConverter::EscapeForCMake(
|
|
|
|
- unescapedDest, cmOutputConverter::WrapQuotes::NoWrap),
|
|
|
|
- '/');
|
|
|
|
- if (!cmSystemTools::FileIsFullPath(unescapedDest)) {
|
|
|
|
- dest = cmStrCat("${_IMPORT_PREFIX}/", dest);
|
|
|
|
|
|
+ if (cmHasLiteralPrefix(li, "${_IMPORT_PREFIX}")) {
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
-
|
|
|
|
- bool const contextSensitive = destCge->GetHadContextSensitiveCondition() ||
|
|
|
|
- std::any_of(directoryEntries.begin(), directoryEntries.end(),
|
|
|
|
- EntryIsContextSensitive) ||
|
|
|
|
- std::any_of(fileEntries.begin(), fileEntries.end(),
|
|
|
|
- EntryIsContextSensitive);
|
|
|
|
-
|
|
|
|
- auto const& type = fileSet->GetType();
|
|
|
|
- // C++ modules do not support interface file sets which are dependent upon
|
|
|
|
- // the configuration.
|
|
|
|
- if (contextSensitive && type == "CXX_MODULES"_s) {
|
|
|
|
- auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
|
|
|
|
- std::ostringstream e;
|
|
|
|
- e << "The \"" << gte->GetName() << "\" target's interface file set \""
|
|
|
|
- << fileSet->GetName() << "\" of type \"" << type
|
|
|
|
- << "\" contains context-sensitive base file entries which is not "
|
|
|
|
- "supported.";
|
|
|
|
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
|
|
|
|
- return std::string{};
|
|
|
|
|
|
+ MessageType messageType = MessageType::FATAL_ERROR;
|
|
|
|
+ std::ostringstream e;
|
|
|
|
+ if (genexPos != std::string::npos) {
|
|
|
|
+ if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
|
|
|
|
+ switch (target->GetPolicyStatusCMP0041()) {
|
|
|
|
+ case cmPolicies::WARN:
|
|
|
|
+ messageType = MessageType::WARNING;
|
|
|
|
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0041) << "\n";
|
|
|
|
+ break;
|
|
|
|
+ case cmPolicies::OLD:
|
|
|
|
+ continue;
|
|
|
|
+ case cmPolicies::REQUIRED_IF_USED:
|
|
|
|
+ case cmPolicies::REQUIRED_ALWAYS:
|
|
|
|
+ case cmPolicies::NEW:
|
|
|
|
+ hadFatalError = true;
|
|
|
|
+ break; // Issue fatal message.
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ hadFatalError = true;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
- for (auto const& it : files) {
|
|
|
|
- auto prefix = it.first.empty() ? "" : cmStrCat(it.first, '/');
|
|
|
|
- for (auto const& filename : it.second) {
|
|
|
|
- auto relFile =
|
|
|
|
- cmStrCat(prefix, cmSystemTools::GetFilenameName(filename));
|
|
|
|
- auto escapedFile =
|
|
|
|
- cmStrCat(dest,
|
|
|
|
- cmOutputConverter::EscapeForCMake(
|
|
|
|
- relFile, cmOutputConverter::WrapQuotes::NoWrap));
|
|
|
|
- if (contextSensitive && configs.size() != 1) {
|
|
|
|
- resultVector.push_back(
|
|
|
|
- cmStrCat("\"$<$<CONFIG:", config, ">:", escapedFile, ">\""));
|
|
|
|
- } else {
|
|
|
|
- resultVector.emplace_back(cmStrCat('"', escapedFile, '"'));
|
|
|
|
|
|
+ if (!cmSystemTools::FileIsFullPath(li)) {
|
|
|
|
+ /* clang-format off */
|
|
|
|
+ e << "Target \"" << target->GetName() << "\" " << prop <<
|
|
|
|
+ " property contains relative path:\n"
|
|
|
|
+ " \"" << li << "\"";
|
|
|
|
+ /* clang-format on */
|
|
|
|
+ target->GetLocalGenerator()->IssueMessage(messageType, e.str());
|
|
|
|
+ }
|
|
|
|
+ bool inBinary = isSubDirectory(li, topBinaryDir);
|
|
|
|
+ bool inSource = isSubDirectory(li, topSourceDir);
|
|
|
|
+ if (isSubDirectory(li, installDir)) {
|
|
|
|
+ // The include directory is inside the install tree. If the
|
|
|
|
+ // install tree is not inside the source tree or build tree then
|
|
|
|
+ // fall through to the checks below that the include directory is not
|
|
|
|
+ // also inside the source tree or build tree.
|
|
|
|
+ bool shouldContinue =
|
|
|
|
+ (!inBinary || isSubDirectory(installDir, topBinaryDir)) &&
|
|
|
|
+ (!inSource || isSubDirectory(installDir, topSourceDir));
|
|
|
|
+
|
|
|
|
+ if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
|
|
|
|
+ if (!shouldContinue) {
|
|
|
|
+ switch (target->GetPolicyStatusCMP0052()) {
|
|
|
|
+ case cmPolicies::WARN: {
|
|
|
|
+ std::ostringstream s;
|
|
|
|
+ s << cmPolicies::GetPolicyWarning(cmPolicies::CMP0052) << "\n";
|
|
|
|
+ s << "Directory:\n \"" << li
|
|
|
|
+ << "\"\nin "
|
|
|
|
+ "INTERFACE_INCLUDE_DIRECTORIES of target \""
|
|
|
|
+ << target->GetName()
|
|
|
|
+ << "\" is a subdirectory of the install "
|
|
|
|
+ "directory:\n \""
|
|
|
|
+ << installDir
|
|
|
|
+ << "\"\nhowever it is also "
|
|
|
|
+ "a subdirectory of the "
|
|
|
|
+ << (inBinary ? "build" : "source") << " tree:\n \""
|
|
|
|
+ << (inBinary ? topBinaryDir : topSourceDir) << "\"\n";
|
|
|
|
+ target->GetLocalGenerator()->IssueMessage(
|
|
|
|
+ MessageType::AUTHOR_WARNING, s.str());
|
|
|
|
+ CM_FALLTHROUGH;
|
|
|
|
+ }
|
|
|
|
+ case cmPolicies::OLD:
|
|
|
|
+ shouldContinue = true;
|
|
|
|
+ break;
|
|
|
|
+ case cmPolicies::REQUIRED_ALWAYS:
|
|
|
|
+ case cmPolicies::REQUIRED_IF_USED:
|
|
|
|
+ case cmPolicies::NEW:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ if (shouldContinue) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
- if (!(contextSensitive && configs.size() != 1)) {
|
|
|
|
- break;
|
|
|
|
|
|
+ if (inBinary) {
|
|
|
|
+ /* clang-format off */
|
|
|
|
+ e << "Target \"" << target->GetName() << "\" " << prop <<
|
|
|
|
+ " property contains path:\n"
|
|
|
|
+ " \"" << li << "\"\nwhich is prefixed in the build directory.";
|
|
|
|
+ /* clang-format on */
|
|
|
|
+ target->GetLocalGenerator()->IssueMessage(messageType, e.str());
|
|
|
|
+ }
|
|
|
|
+ if (!inSourceBuild) {
|
|
|
|
+ if (inSource) {
|
|
|
|
+ e << "Target \"" << target->GetName() << "\" " << prop
|
|
|
|
+ << " property contains path:\n"
|
|
|
|
+ " \""
|
|
|
|
+ << li << "\"\nwhich is prefixed in the source directory.";
|
|
|
|
+ target->GetLocalGenerator()->IssueMessage(messageType, e.str());
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- return cmJoin(resultVector, " ");
|
|
|
|
|
|
+ return !hadFatalError;
|
|
|
|
+}
|
|
}
|
|
}
|
|
|
|
|
|
-std::string cmExportInstallFileGenerator::GetCxxModulesDirectory() const
|
|
|
|
|
|
+void cmExportInstallFileGenerator::PopulateSourcesInterface(
|
|
|
|
+ cmGeneratorTarget const* gt,
|
|
|
|
+ cmGeneratorExpression::PreprocessContext preprocessRule,
|
|
|
|
+ ImportPropertyMap& properties)
|
|
{
|
|
{
|
|
- return IEGen->GetCxxModuleDirectory();
|
|
|
|
|
|
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
|
|
|
|
+
|
|
|
|
+ char const* const propName = "INTERFACE_SOURCES";
|
|
|
|
+ cmValue input = gt->GetProperty(propName);
|
|
|
|
+
|
|
|
|
+ if (!input) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (input->empty()) {
|
|
|
|
+ properties[propName].clear();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ std::string prepro =
|
|
|
|
+ cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
|
|
|
|
+ if (!prepro.empty()) {
|
|
|
|
+ this->ResolveTargetsInGeneratorExpressions(prepro, gt);
|
|
|
|
+
|
|
|
|
+ if (!checkInterfaceDirs(prepro, gt, propName)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ properties[propName] = prepro;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-void cmExportInstallFileGenerator::GenerateCxxModuleConfigInformation(
|
|
|
|
- std::string const& name, std::ostream& os) const
|
|
|
|
|
|
+void cmExportInstallFileGenerator::PopulateIncludeDirectoriesInterface(
|
|
|
|
+ cmGeneratorTarget const* target,
|
|
|
|
+ cmGeneratorExpression::PreprocessContext preprocessRule,
|
|
|
|
+ ImportPropertyMap& properties, cmTargetExport const& te,
|
|
|
|
+ std::string& includesDestinationDirs)
|
|
{
|
|
{
|
|
- // Now load per-configuration properties for them.
|
|
|
|
- /* clang-format off */
|
|
|
|
- os << "# Load information for each installed configuration.\n"
|
|
|
|
- "file(GLOB _cmake_cxx_module_includes \"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << name << "-*.cmake\")\n"
|
|
|
|
- "foreach(_cmake_cxx_module_include IN LISTS _cmake_cxx_module_includes)\n"
|
|
|
|
- " include(\"${_cmake_cxx_module_include}\")\n"
|
|
|
|
- "endforeach()\n"
|
|
|
|
- "unset(_cmake_cxx_module_include)\n"
|
|
|
|
- "unset(_cmake_cxx_module_includes)\n";
|
|
|
|
- /* clang-format on */
|
|
|
|
|
|
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
|
|
|
|
+
|
|
|
|
+ includesDestinationDirs.clear();
|
|
|
|
+
|
|
|
|
+ char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
|
|
|
|
+ cmValue input = target->GetProperty(propName);
|
|
|
|
+
|
|
|
|
+ cmGeneratorExpression ge(*target->Makefile->GetCMakeInstance());
|
|
|
|
+
|
|
|
|
+ std::string dirs = cmGeneratorExpression::Preprocess(
|
|
|
|
+ cmList::to_string(target->Target->GetInstallIncludeDirectoriesEntries(te)),
|
|
|
|
+ preprocessRule, true);
|
|
|
|
+ this->ReplaceInstallPrefix(dirs);
|
|
|
|
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
|
|
|
|
+ std::string exportDirs =
|
|
|
|
+ cge->Evaluate(target->GetLocalGenerator(), "", target);
|
|
|
|
+
|
|
|
|
+ if (cge->GetHadContextSensitiveCondition()) {
|
|
|
|
+ cmLocalGenerator* lg = target->GetLocalGenerator();
|
|
|
|
+ std::ostringstream e;
|
|
|
|
+ e << "Target \"" << target->GetName()
|
|
|
|
+ << "\" is installed with "
|
|
|
|
+ "INCLUDES DESTINATION set to a context sensitive path. Paths which "
|
|
|
|
+ "depend on the configuration, policy values or the link interface "
|
|
|
|
+ "are "
|
|
|
|
+ "not supported. Consider using target_include_directories instead.";
|
|
|
|
+ lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!input && exportDirs.empty()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if ((input && input->empty()) && exportDirs.empty()) {
|
|
|
|
+ // Set to empty
|
|
|
|
+ properties[propName].clear();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this->AddImportPrefix(exportDirs);
|
|
|
|
+ includesDestinationDirs = exportDirs;
|
|
|
|
+
|
|
|
|
+ std::string includes = (input ? *input : "");
|
|
|
|
+ char const* const sep = input ? ";" : "";
|
|
|
|
+ includes += sep + exportDirs;
|
|
|
|
+ std::string prepro =
|
|
|
|
+ cmGeneratorExpression::Preprocess(includes, preprocessRule, true);
|
|
|
|
+ if (!prepro.empty()) {
|
|
|
|
+ this->ResolveTargetsInGeneratorExpressions(prepro, target);
|
|
|
|
+
|
|
|
|
+ if (!checkInterfaceDirs(prepro, target, propName)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ properties[propName] = prepro;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-bool cmExportInstallFileGenerator::
|
|
|
|
- GenerateImportCxxModuleConfigTargetInclusion(std::string const& name,
|
|
|
|
- std::string const& config)
|
|
|
|
|
|
+void cmExportInstallFileGenerator::PopulateLinkDependsInterface(
|
|
|
|
+ cmGeneratorTarget const* gt,
|
|
|
|
+ cmGeneratorExpression::PreprocessContext preprocessRule,
|
|
|
|
+ ImportPropertyMap& properties)
|
|
{
|
|
{
|
|
- auto cxx_modules_dirname = this->GetCxxModulesDirectory();
|
|
|
|
- if (cxx_modules_dirname.empty()) {
|
|
|
|
- return true;
|
|
|
|
|
|
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
|
|
|
|
+
|
|
|
|
+ char const* const propName = "INTERFACE_LINK_DEPENDS";
|
|
|
|
+ cmValue input = gt->GetProperty(propName);
|
|
|
|
+
|
|
|
|
+ if (!input) {
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
- std::string filename_config = config;
|
|
|
|
- if (filename_config.empty()) {
|
|
|
|
- filename_config = "noconfig";
|
|
|
|
|
|
+ if (input->empty()) {
|
|
|
|
+ properties[propName].clear();
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
- std::string const dest =
|
|
|
|
- cmStrCat(this->FileDir, '/', cxx_modules_dirname, '/');
|
|
|
|
- std::string fileName =
|
|
|
|
- cmStrCat(dest, "cxx-modules-", name, '-', filename_config, ".cmake");
|
|
|
|
|
|
+ std::string prepro =
|
|
|
|
+ cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
|
|
|
|
+ if (!prepro.empty()) {
|
|
|
|
+ this->ResolveTargetsInGeneratorExpressions(prepro, gt);
|
|
|
|
|
|
- cmGeneratedFileStream os(fileName, true);
|
|
|
|
- if (!os) {
|
|
|
|
- std::string se = cmSystemTools::GetLastSystemError();
|
|
|
|
- std::ostringstream e;
|
|
|
|
- e << "cannot write to file \"" << fileName << "\": " << se;
|
|
|
|
- cmSystemTools::Error(e.str());
|
|
|
|
- return false;
|
|
|
|
|
|
+ if (!checkInterfaceDirs(prepro, gt, propName)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ properties[propName] = prepro;
|
|
}
|
|
}
|
|
- os.SetCopyIfDifferent(true);
|
|
|
|
|
|
+}
|
|
|
|
|
|
- // Record this per-config import file.
|
|
|
|
- this->ConfigCxxModuleFiles[config] = fileName;
|
|
|
|
|
|
+void cmExportInstallFileGenerator::PopulateLinkDirectoriesInterface(
|
|
|
|
+ cmGeneratorTarget const* gt,
|
|
|
|
+ cmGeneratorExpression::PreprocessContext preprocessRule,
|
|
|
|
+ ImportPropertyMap& properties)
|
|
|
|
+{
|
|
|
|
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
|
|
|
|
|
|
- auto& prop_files = this->ConfigCxxModuleTargetFiles[config];
|
|
|
|
- for (auto const* tgt : this->ExportedTargets) {
|
|
|
|
- // Only targets with C++ module sources will have a
|
|
|
|
- // collator-generated install script.
|
|
|
|
- if (!tgt->HaveCxx20ModuleSources()) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
|
|
+ char const* const propName = "INTERFACE_LINK_DIRECTORIES";
|
|
|
|
+ cmValue input = gt->GetProperty(propName);
|
|
|
|
+
|
|
|
|
+ if (!input) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
|
|
- auto prop_filename = cmStrCat("target-", tgt->GetFilesystemExportName(),
|
|
|
|
- '-', filename_config, ".cmake");
|
|
|
|
- prop_files.emplace_back(cmStrCat(dest, prop_filename));
|
|
|
|
- os << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << prop_filename << "\")\n";
|
|
|
|
|
|
+ if (input->empty()) {
|
|
|
|
+ properties[propName].clear();
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
- return true;
|
|
|
|
|
|
+ std::string prepro =
|
|
|
|
+ cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
|
|
|
|
+ if (!prepro.empty()) {
|
|
|
|
+ this->ResolveTargetsInGeneratorExpressions(prepro, gt);
|
|
|
|
+
|
|
|
|
+ if (!checkInterfaceDirs(prepro, gt, propName)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ properties[propName] = prepro;
|
|
|
|
+ }
|
|
}
|
|
}
|