summaryrefslogtreecommitdiff
path: root/Source/cmExportBuildFileGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmExportBuildFileGenerator.cxx')
-rw-r--r--Source/cmExportBuildFileGenerator.cxx184
1 files changed, 106 insertions, 78 deletions
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index a1c424aca..7e9a98738 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -2,32 +2,32 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportBuildFileGenerator.h"
-#include "cmAlgorithms.h"
+#include <map>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <utility>
+
#include "cmExportSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmake.h"
-#include <algorithm>
-#include <map>
-#include <set>
-#include <sstream>
-#include <utility>
-
class cmSourceFile;
cmExportBuildFileGenerator::cmExportBuildFileGenerator()
{
- this->LG = CM_NULLPTR;
- this->ExportSet = CM_NULLPTR;
+ this->LG = nullptr;
+ this->ExportSet = nullptr;
}
void cmExportBuildFileGenerator::Compute(cmLocalGenerator* lg)
@@ -44,10 +44,10 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
std::string expectedTargets;
std::string sep;
std::vector<std::string> targets;
+ bool generatedInterfaceRequired = false;
this->GetTargets(targets);
- for (std::vector<std::string>::const_iterator tei = targets.begin();
- tei != targets.end(); ++tei) {
- cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(*tei);
+ for (std::string const& tei : targets) {
+ cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(tei);
expectedTargets += sep + this->Namespace + te->GetExportName();
sep = " ";
if (this->ExportedTargets.insert(te).second) {
@@ -56,26 +56,25 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
std::ostringstream e;
e << "given target \"" << te->GetName() << "\" more than once.";
this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR, e.str(),
+ MessageType::FATAL_ERROR, e.str(),
this->LG->GetMakefile()->GetBacktrace());
return false;
}
- if (te->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- this->GenerateRequiredCMakeVersion(os, "3.0.0");
- }
+ generatedInterfaceRequired |=
+ this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY;
}
+ if (generatedInterfaceRequired) {
+ this->GenerateRequiredCMakeVersion(os, "3.0.0");
+ }
this->GenerateExpectedTargetsCode(os, expectedTargets);
}
std::vector<std::string> missingTargets;
// Create all the imported targets.
- for (std::vector<cmGeneratorTarget*>::const_iterator tei =
- this->Exports.begin();
- tei != this->Exports.end(); ++tei) {
- cmGeneratorTarget* gte = *tei;
- this->GenerateImportTargetCode(os, gte);
+ for (cmGeneratorTarget* gte : this->Exports) {
+ this->GenerateImportTargetCode(os, gte, this->GetExportTargetType(gte));
gte->Target->AppendBuildInterfaceIncludes();
@@ -93,14 +92,35 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_DIRECTORIES", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_DEPENDS", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte,
properties);
+
+ std::string errorMessage;
+ if (!this->PopulateExportProperties(gte, properties, errorMessage)) {
+ this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR, errorMessage,
+ this->LG->GetMakefile()->GetBacktrace());
+ return false;
+ }
+
const bool newCMP0022Behavior =
gte->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
gte->GetPolicyStatusCMP0022() != cmPolicies::OLD;
@@ -115,10 +135,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
}
// Generate import file content for each configuration.
- for (std::vector<std::string>::const_iterator ci =
- this->Configurations.begin();
- ci != this->Configurations.end(); ++ci) {
- this->GenerateImportConfig(os, *ci, missingTargets);
+ for (std::string const& c : this->Configurations) {
+ this->GenerateImportConfig(os, c, missingTargets);
}
this->GenerateMissingTargetsCheckCode(os, missingTargets);
@@ -130,19 +148,17 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
std::ostream& os, const std::string& config, std::string const& suffix,
std::vector<std::string>& missingTargets)
{
- for (std::vector<cmGeneratorTarget*>::const_iterator tei =
- this->Exports.begin();
- tei != this->Exports.end(); ++tei) {
+ for (cmGeneratorTarget* target : this->Exports) {
// Collect import properties for this target.
- cmGeneratorTarget* target = *tei;
ImportPropertyMap properties;
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(target) != cmStateEnums::INTERFACE_LIBRARY) {
this->SetImportLocationProperty(config, suffix, target, properties);
}
if (!properties.empty()) {
// Get the rest of the target details.
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(target) !=
+ cmStateEnums::INTERFACE_LIBRARY) {
this->SetImportDetailProperties(config, suffix, target, properties,
missingTargets);
this->SetImportLinkInterface(config, suffix,
@@ -150,7 +166,7 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
target, properties, missingTargets);
}
- // TOOD: PUBLIC_HEADER_LOCATION
+ // 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,
@@ -162,6 +178,21 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
}
}
+cmStateEnums::TargetType cmExportBuildFileGenerator::GetExportTargetType(
+ cmGeneratorTarget const* target) const
+{
+ cmStateEnums::TargetType targetType = target->GetType();
+ // An object library exports as an interface library if we cannot
+ // tell clients where to find the objects. This is sufficient
+ // to support transitive usage requirements on other targets that
+ // use the object library.
+ if (targetType == cmStateEnums::OBJECT_LIBRARY &&
+ !this->LG->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) {
+ targetType = cmStateEnums::INTERFACE_LIBRARY;
+ }
+ return targetType;
+}
+
void cmExportBuildFileGenerator::SetExportSet(cmExportSet* exportSet)
{
this->ExportSet = exportSet;
@@ -175,8 +206,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
cmMakefile* mf = target->Makefile;
if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string prop = "IMPORTED_OBJECTS";
- prop += suffix;
+ std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);
// Compute all the object files inside this target and setup
// IMPORTED_OBJECTS as a list of object files
@@ -184,10 +214,8 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
target->GetObjectSources(objectSources, config);
std::string const obj_dir = target->GetObjectDirectory(config);
std::vector<std::string> objects;
- for (std::vector<cmSourceFile const*>::const_iterator si =
- objectSources.begin();
- si != objectSources.end(); ++si) {
- const std::string& obj = target->GetObjectName(*si);
+ for (cmSourceFile const* sf : objectSources) {
+ const std::string& obj = target->GetObjectName(sf);
objects.push_back(obj_dir + obj);
}
@@ -196,8 +224,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
} else {
// Add the main target file.
{
- std::string prop = "IMPORTED_LOCATION";
- prop += suffix;
+ std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);
std::string value;
if (target->IsAppBundleOnApple()) {
value =
@@ -210,13 +237,14 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
}
// Add the import library for windows DLLs.
- if (target->HasImportLibrary() &&
- mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
- std::string prop = "IMPORTED_IMPLIB";
- prop += suffix;
+ if (target->HasImportLibrary(config)) {
+ std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
std::string value =
target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact);
- target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
+ if (mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
+ target->GetImplibGNUtoMS(config, value, value,
+ "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
+ }
properties[prop] = value;
}
}
@@ -231,20 +259,20 @@ void cmExportBuildFileGenerator::HandleMissingTarget(
const std::string name = dependee->GetName();
cmGlobalGenerator* gg =
dependee->GetLocalGenerator()->GetGlobalGenerator();
- std::vector<std::string> namespaces = this->FindNamespaces(gg, name);
+ auto exportInfo = this->FindBuildExportInfo(gg, name);
+ std::vector<std::string> const& exportFiles = exportInfo.first;
- int targetOccurrences = (int)namespaces.size();
- if (targetOccurrences == 1) {
- std::string missingTarget = namespaces[0];
+ if (exportFiles.size() == 1) {
+ std::string missingTarget = exportInfo.second;
missingTarget += dependee->GetExportName();
link_libs += missingTarget;
- missingTargets.push_back(missingTarget);
+ missingTargets.push_back(std::move(missingTarget));
return;
}
// We are not appending, so all exported targets should be
// known here. This is probably user-error.
- this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences);
+ this->ComplainAboutMissingTarget(depender, dependee, exportFiles);
}
// Assume the target will be exported by another command.
// Append it with the export namespace.
@@ -256,59 +284,59 @@ void cmExportBuildFileGenerator::GetTargets(
std::vector<std::string>& targets) const
{
if (this->ExportSet) {
- for (std::vector<cmTargetExport*>::const_iterator tei =
- this->ExportSet->GetTargetExports()->begin();
- tei != this->ExportSet->GetTargetExports()->end(); ++tei) {
- targets.push_back((*tei)->TargetName);
+ for (std::unique_ptr<cmTargetExport> const& te :
+ this->ExportSet->GetTargetExports()) {
+ targets.push_back(te->TargetName);
}
return;
}
targets = this->Targets;
}
-std::vector<std::string> cmExportBuildFileGenerator::FindNamespaces(
- cmGlobalGenerator* gg, const std::string& name)
+std::pair<std::vector<std::string>, std::string>
+cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg,
+ const std::string& name)
{
- std::vector<std::string> namespaces;
+ std::vector<std::string> exportFiles;
+ std::string ns;
std::map<std::string, cmExportBuildFileGenerator*>& exportSets =
gg->GetBuildExportSets();
- for (std::map<std::string, cmExportBuildFileGenerator*>::const_iterator
- expIt = exportSets.begin();
- expIt != exportSets.end(); ++expIt) {
- const cmExportBuildFileGenerator* exportSet = expIt->second;
+ for (auto const& exp : exportSets) {
+ const cmExportBuildFileGenerator* exportSet = exp.second;
std::vector<std::string> targets;
exportSet->GetTargets(targets);
- if (std::find(targets.begin(), targets.end(), name) != targets.end()) {
- namespaces.push_back(exportSet->GetNamespace());
+ if (cmContains(targets, name)) {
+ exportFiles.push_back(exp.first);
+ ns = exportSet->GetNamespace();
}
}
- return namespaces;
+ return { exportFiles, ns };
}
void cmExportBuildFileGenerator::ComplainAboutMissingTarget(
- cmGeneratorTarget* depender, cmGeneratorTarget* dependee, int occurrences)
+ cmGeneratorTarget* depender, cmGeneratorTarget* dependee,
+ std::vector<std::string> const& exportFiles)
{
- if (cmSystemTools::GetErrorOccuredFlag()) {
- return;
- }
-
std::ostringstream e;
e << "export called with target \"" << depender->GetName()
<< "\" which requires target \"" << dependee->GetName() << "\" ";
- if (occurrences == 0) {
- e << "that is not in the export set.\n";
+ if (exportFiles.empty()) {
+ e << "that is not in any export set.";
} else {
- e << "that is not in this export set, but " << occurrences
- << " times in others.\n";
+ e << "that is not in this export set, but in multiple other export sets: "
+ << cmJoin(exportFiles, ", ") << ".\n";
+ e << "An exported target cannot depend upon another target which is "
+ "exported multiple times. Consider consolidating the exports of the "
+ "\""
+ << dependee->GetName() << "\" target to a single export.";
}
- e << "If the required target is not easy to reference in this call, "
- << "consider using the APPEND option with multiple separate calls.";
this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR, e.str(), this->LG->GetMakefile()->GetBacktrace());
+ MessageType::FATAL_ERROR, e.str(),
+ this->LG->GetMakefile()->GetBacktrace());
}
std::string cmExportBuildFileGenerator::InstallNameDir(