diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 32595ee4b2..fd5a4328f2 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -135,7 +135,8 @@ cmExportBuildFileGenerator void cmExportBuildFileGenerator ::ComplainAboutMissingTarget(cmTarget* depender, - cmTarget* dependee) + cmTarget* dependee, + int occurrences) { if(!this->ExportCommand || !this->ExportCommand->ErrorMessage.empty()) { @@ -143,10 +144,20 @@ cmExportBuildFileGenerator } cmOStringStream e; - e << "called with target \"" << depender->GetName() - << "\" which requires target \"" << dependee->GetName() - << "\" that is not in the export list.\n" - << "If the required target is not easy to reference in this call, " - << "consider using the APPEND option with multiple separate calls."; + if (occurrences == 0) + { + e << "called with target \"" << depender->GetName() + << "\" which requires target \"" << dependee->GetName() + << "\" that is not in the export list.\n" + << "If the required target is not easy to reference in this call, " + << "consider using the APPEND option with multiple separate calls."; + } + else + { + e << "called with target \"" << depender->GetName() + << "\" which requires target \"" << dependee->GetName() + << "\" that is exported " << occurrences << " times in other " + << "export ""lists.\n"; + } this->ExportCommand->ErrorMessage = e.str(); } diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 0f37626cc7..69f8407682 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -46,7 +46,8 @@ protected: const char* config, std::string const& suffix); virtual void ComplainAboutMissingTarget(cmTarget* depender, - cmTarget* dependee); + cmTarget* dependee, + int occurrences); /** Fill in properties indicating built file locations. */ void SetImportLocationProperty(const char* config, diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index eb19df5e28..fa6cc9f373 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -11,10 +11,15 @@ ============================================================================*/ #include "cmExportFileGenerator.h" +#include "cmExportSet.h" #include "cmGeneratedFileStream.h" +#include "cmGlobalGenerator.h" +#include "cmInstallExportGenerator.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmTargetExport.h" #include "cmVersion.h" #include @@ -224,17 +229,28 @@ cmExportFileGenerator } else { - // The target is not in the export. - if(!this->AppendMode) + std::vector namespaces = this->FindNamespaces(mf, *li); + int targetOccurrences = (int)namespaces.size(); + + if (targetOccurrences == 1) { - // We are not appending, so all exported targets should be - // known here. This is probably user-error. - this->ComplainAboutMissingTarget(target, tgt); + link_libs += namespaces[0]; + link_libs += *li; + } + else + { + // The target is not in the export. + if(!this->AppendMode) + { + // We are not appending, so all exported targets should be + // known here. This is probably user-error. + this->ComplainAboutMissingTarget(target, tgt, targetOccurrences); + } + // Assume the target will be exported by another command. + // Append it with the export namespace. + link_libs += this->Namespace; + link_libs += *li; } - // Assume the target will be exported by another command. - // Append it with the export namespace. - link_libs += this->Namespace; - link_libs += *li; } } else @@ -250,6 +266,48 @@ cmExportFileGenerator properties[prop] = link_libs; } + +//---------------------------------------------------------------------------- +std::vector cmExportFileGenerator::FindNamespaces(cmMakefile* mf, + const std::string& name) +{ + std::vector namespaces; + cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator(); + const cmExportSetMap& exportSets = gg->GetExportSets(); + + for(cmExportSetMap::const_iterator expIt = exportSets.begin(); + expIt != exportSets.end(); + ++expIt) + { + const cmExportSet* exportSet = expIt->second; + std::vector const* targets = + exportSet->GetTargetExports(); + + bool containsTarget = false; + for(unsigned int i=0; isize(); i++) + { + if (name == (*targets)[i]->Target->GetName()) + { + containsTarget = true; + break; + } + } + + if (containsTarget) + { + std::vector const* installs = + exportSet->GetInstallations(); + for(unsigned int i=0; isize(); i++) + { + namespaces.push_back((*installs)[i]->GetNamespace()); + } + } + } + + return namespaces; +} + + //---------------------------------------------------------------------------- void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os, const char* config) diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index f271e5570e..c9feffdd51 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -83,7 +83,12 @@ protected: /** Each subclass knows how to complain about a target that is missing from an export set. */ virtual void ComplainAboutMissingTarget(cmTarget* depender, - cmTarget* dependee) = 0; + cmTarget* dependee, + int occurrences) = 0; + + std::vector FindNamespaces(cmMakefile* mf, + const std::string& name); + // The namespace in which the exports are placed in the generated file. std::string Namespace; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index d4f7fd5e64..ba048b527a 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -327,14 +327,24 @@ cmExportInstallFileGenerator //---------------------------------------------------------------------------- void cmExportInstallFileGenerator -::ComplainAboutMissingTarget(cmTarget* depender, cmTarget* dependee) +::ComplainAboutMissingTarget(cmTarget* depender, + cmTarget* dependee, + int occurrences) { cmOStringStream e; e << "INSTALL(EXPORT \"" << this->IEGen->GetExportSet()->GetName() << "\" ...) " << "includes target \"" << depender->GetName() - << "\" which requires target \"" << dependee->GetName() - << "\" that is not in the export set."; + << "\" which requires target \"" << dependee->GetName() << "\" "; + if (occurrences == 0) + { + e << "that is not in the export set."; + } + else + { + e << "that is not in this export set, but " << occurrences + << " times in others."; + } cmSystemTools::Error(e.str().c_str()); } diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 77b55c887f..f6f397e871 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -58,7 +58,8 @@ protected: const char* config, std::string const& suffix); virtual void ComplainAboutMissingTarget(cmTarget* depender, - cmTarget* dependee); + cmTarget* dependee, + int occurrences); /** Generate a per-configuration file for the targets. */ bool GenerateImportFileConfig(const char* config); diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index 8ae271b7eb..ee92906fe8 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -34,7 +34,10 @@ public: cmMakefile* mf); ~cmInstallExportGenerator(); - cmExportSet* GetExportSet() {return ExportSet;} + cmExportSet* GetExportSet() {return this->ExportSet;} + + const std::string& GetNamespace() const { return this->Namespace; } + protected: virtual void GenerateScript(std::ostream& os); virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);