From 87f4c01910754199bcdcbc9d564de13d36ba2502 Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Sat, 15 Sep 2012 21:55:24 +0200 Subject: [PATCH] exports: accept a missing target if it is exported exactly once If a target is exported, and a library it depends on is not part of the same export set, before this patch cmake errored out. With this patch, it now checks whether the missing target is exported somewhere else exactly once, and accepts in this case (because then it can determine the namespace for the missing target and use this). Alex --- Source/cmExportBuildFileGenerator.cxx | 23 ++++++-- Source/cmExportBuildFileGenerator.h | 3 +- Source/cmExportFileGenerator.cxx | 76 ++++++++++++++++++++++--- Source/cmExportFileGenerator.h | 7 ++- Source/cmExportInstallFileGenerator.cxx | 16 +++++- Source/cmExportInstallFileGenerator.h | 3 +- Source/cmInstallExportGenerator.h | 5 +- 7 files changed, 111 insertions(+), 22 deletions(-) diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 32595ee4b..fd5a4328f 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 0f37626cc..69f840768 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 eb19df5e2..fa6cc9f37 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 f271e5570..c9feffdd5 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 d4f7fd5e6..ba048b527 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 77b55c887..f6f397e87 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 8ae271b7e..ee92906fe 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);