diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index e2ad74f06d..e593e0c5bb 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -21,20 +21,19 @@ cmExportBuildFileGenerator::cmExportBuildFileGenerator() //---------------------------------------------------------------------------- bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) { - std::vector allTargets; { std::string expectedTargets; std::string sep; - for(std::vector::const_iterator - tei = this->Exports->begin(); - tei != this->Exports->end(); ++tei) + for(std::vector::const_iterator + tei = this->Targets.begin(); + tei != this->Targets.end(); ++tei) { - expectedTargets += sep + this->Namespace + (*tei)->GetExportName(); + cmTarget *te = this->Makefile->FindTargetToUse(tei->c_str()); + expectedTargets += sep + this->Namespace + te->GetExportName(); sep = " "; - cmTarget* te = *tei; if(this->ExportedTargets.insert(te).second) { - allTargets.push_back(te); + this->Exports.push_back(te); } else { @@ -57,8 +56,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) // Create all the imported targets. for(std::vector::const_iterator - tei = allTargets.begin(); - tei != allTargets.end(); ++tei) + tei = this->Exports.begin(); + tei != this->Exports.end(); ++tei) { cmTarget* te = *tei; this->GenerateImportTargetCode(os, te); @@ -113,8 +112,8 @@ cmExportBuildFileGenerator std::vector &missingTargets) { for(std::vector::const_iterator - tei = this->Exports->begin(); - tei != this->Exports->end(); ++tei) + tei = this->Exports.begin(); + tei != this->Exports.end(); ++tei) { // Collect import properties for this target. cmTarget* target = *tei; diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 4436896107..0392d80266 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -30,8 +30,13 @@ public: cmExportBuildFileGenerator(); /** Set the list of targets to export. */ - void SetExports(std::vector const* exports) - { this->Exports = exports; } + void SetTargets(std::vector const& targets) + { this->Targets = targets; } + std::vector const& GetTargets() const + { return this->Targets; } + void AppendTargets(std::vector const& targets) + { this->Targets.insert(this->Targets.end(), + targets.begin(), targets.end()); } /** Set whether to append generated code to the output file. */ void SetAppendMode(bool append) { this->AppendMode = append; } @@ -65,7 +70,8 @@ protected: std::string InstallNameDir(cmTarget* target, const std::string& config); - std::vector const* Exports; + std::vector Targets; + std::vector Exports; cmMakefile* Makefile; cmListFileBacktrace Backtrace; }; diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 9d0d478707..86ddc3f44f 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -108,8 +108,6 @@ bool cmExportCommand fname += this->Filename.GetString(); } - // Collect the targets to be exported. - std::vector targets; for(std::vector::const_iterator currentTarget = this->Targets.GetVector().begin(); currentTarget != this->Targets.GetVector().end(); @@ -128,15 +126,7 @@ bool cmExportCommand this->Makefile->GetLocalGenerator()-> GetGlobalGenerator()->FindTarget(0, currentTarget->c_str())) { - if((target->GetType() == cmTarget::EXECUTABLE) || - (target->GetType() == cmTarget::STATIC_LIBRARY) || - (target->GetType() == cmTarget::SHARED_LIBRARY) || - (target->GetType() == cmTarget::MODULE_LIBRARY) || - (target->GetType() == cmTarget::INTERFACE_LIBRARY)) - { - targets.push_back(target); - } - else if(target->GetType() == cmTarget::OBJECT_LIBRARY) + if(target->GetType() == cmTarget::OBJECT_LIBRARY) { cmOStringStream e; e << "given OBJECT library \"" << *currentTarget @@ -144,37 +134,28 @@ bool cmExportCommand this->SetError(e.str().c_str()); return false; } - else - { - cmOStringStream e; - e << "given target \"" << *currentTarget - << "\" which is not an executable or library."; - this->SetError(e.str().c_str()); - return false; - } } - else + } + + cmGlobalGenerator *gg = this->Makefile->GetLocalGenerator() + ->GetGlobalGenerator(); + if (this->Append.IsEnabled()) + { + if (cmExportBuildFileGenerator *ebfg = gg->GetExportedTargetsFile(fname)) { - cmOStringStream e; - e << "given target \"" << *currentTarget - << "\" which is not built by this project."; - this->SetError(e.str().c_str()); - return false; + ebfg->AppendTargets(this->Targets.GetVector()); + return true; } } // Setup export file generation. - cmExportBuildFileGenerator ebfg; - ebfg.SetExportFile(fname.c_str()); - ebfg.SetNamespace(this->Namespace.GetCString()); - ebfg.SetAppendMode(this->Append.IsEnabled()); - ebfg.SetExports(&targets); - ebfg.SetMakefile(this->Makefile); - ebfg.SetExportOld(this->ExportOld.IsEnabled()); - - cmGlobalGenerator *gg = this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator(); - gg->AddExportedTargetsFile(fname); + cmExportBuildFileGenerator *ebfg = new cmExportBuildFileGenerator; + ebfg->SetExportFile(fname.c_str()); + ebfg->SetNamespace(this->Namespace.GetCString()); + ebfg->SetAppendMode(this->Append.IsEnabled()); + ebfg->SetTargets(this->Targets.GetVector()); + ebfg->SetMakefile(this->Makefile); + ebfg->SetExportOld(this->ExportOld.IsEnabled()); // Compute the set of configurations exported. std::vector configurationTypes; @@ -185,27 +166,15 @@ bool cmExportCommand ci = configurationTypes.begin(); ci != configurationTypes.end(); ++ci) { - ebfg.AddConfiguration(ci->c_str()); + ebfg->AddConfiguration(ci->c_str()); } } else { - ebfg.AddConfiguration(""); + ebfg->AddConfiguration(""); } - // Generate the import file. - if(!ebfg.GenerateImportFile() && this->ErrorMessage.empty()) - { - this->SetError("could not write export file."); - return false; - } - - // Report generated error message if any. - if(!this->ErrorMessage.empty()) - { - this->SetError(this->ErrorMessage.c_str()); - return false; - } + gg->AddBuildExportSet(ebfg); return true; } diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h index 87c3452843..38e8d9a6d0 100644 --- a/Source/cmExportCommand.h +++ b/Source/cmExportCommand.h @@ -85,7 +85,9 @@ public: "should never be installed. " "See the install(EXPORT) command to export targets from an " "installation tree." - CM_LOCATION_UNDEFINED_BEHAVIOR("passing it to this command") + "\n" + "The properties set on the generated IMPORTED targets will have the " + "same values as the final values of the input TARGETS." "\n" " export(PACKAGE )\n" "Store the current build directory in the CMake user package registry " diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 25c57100cd..b01e4998f3 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -51,6 +51,12 @@ void cmExportFileGenerator::SetExportFile(const char* mainFile) cmSystemTools::GetFilenameLastExtension(this->MainImportFile); } +//---------------------------------------------------------------------------- +const char* cmExportFileGenerator::GetMainExportFileName() const +{ + return this->MainImportFile.c_str(); +} + //---------------------------------------------------------------------------- bool cmExportFileGenerator::GenerateImportFile() { diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 9628b96817..f3d08070f8 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -33,9 +33,11 @@ public: /** Set the full path to the export file to generate. */ void SetExportFile(const char* mainFile); + const char *GetMainExportFileName() const; /** Set the namespace in which to place exported target names. */ void SetNamespace(const char* ns) { this->Namespace = ns; } + std::string GetNamespace() const { return this->Namespace; } void SetExportOld(bool exportOld) { this->ExportOld = exportOld; } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index eacf85ba29..fb205bece5 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -27,6 +27,7 @@ #include "cmGeneratorTarget.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionEvaluationFile.h" +#include "cmExportBuildFileGenerator.h" #include @@ -77,6 +78,12 @@ cmGlobalGenerator::~cmGlobalGenerator() { delete *li; } + for(std::map::iterator + i = this->BuildExportSets.begin(); + i != this->BuildExportSets.end(); ++i) + { + delete i->second; + } this->LocalGenerators.clear(); if (this->ExtraGenerator) @@ -183,6 +190,34 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang, doc.c_str(), cmCacheManager::FILEPATH); } +void cmGlobalGenerator::AddBuildExportSet(cmExportBuildFileGenerator* gen) +{ + this->BuildExportSets[gen->GetMainExportFileName()] = gen; +} + +bool cmGlobalGenerator::GenerateImportFile(const std::string &file) +{ + std::map::iterator it + = this->BuildExportSets.find(file); + if (it != this->BuildExportSets.end()) + { + bool result = it->second->GenerateImportFile(); + delete it->second; + it->second = 0; + this->BuildExportSets.erase(it); + return result; + } + return false; +} + +bool +cmGlobalGenerator::IsExportedTargetsFile(const std::string &filename) const +{ + const std::map::const_iterator it + = this->BuildExportSets.find(filename); + return it != this->BuildExportSets.end(); +} + // Find the make program for the generator, required for try compiles void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) { @@ -966,6 +1001,14 @@ void cmGlobalGenerator::Configure() } } +cmExportBuildFileGenerator* +cmGlobalGenerator::GetExportedTargetsFile(const std::string &filename) const +{ + std::map::const_iterator it + = this->BuildExportSets.find(filename); + return it == this->BuildExportSets.end() ? 0 : it->second; +} + bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() { // If the property is not enabled then okay. @@ -1091,6 +1134,19 @@ void cmGlobalGenerator::Generate() } this->SetCurrentLocalGenerator(0); + for (std::map::iterator + it = this->BuildExportSets.begin(); it != this->BuildExportSets.end(); + ++it) + { + if (!it->second->GenerateImportFile() + && !cmSystemTools::GetErrorOccuredFlag()) + { + this->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, "Could not write export file.", + cmListFileBacktrace()); + return; + } + } // Update rule hashes. this->CheckRuleHashes(); diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index b8860f1f23..c930b2b6e1 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -31,6 +31,7 @@ class cmExternalMakefileProjectGenerator; class cmTarget; class cmInstallTargetGenerator; class cmInstallFilesGenerator; +class cmExportBuildFileGenerator; /** \class cmGlobalGenerator * \brief Responable for overseeing the generation process for the entire tree @@ -293,18 +294,13 @@ public: void ProcessEvaluationFiles(); - void AddExportedTargetsFile(const std::string &filename) - { - this->ExportedTargetsFiles.insert(filename); - } - - bool IsExportedTargetsFile(const std::string &filename) const - { - const std::set::const_iterator it - = this->ExportedTargetsFiles.find(filename); - return it != this->ExportedTargetsFiles.end(); - } - + std::map& GetBuildExportSets() + {return this->BuildExportSets;} + void AddBuildExportSet(cmExportBuildFileGenerator*); + bool IsExportedTargetsFile(const std::string &filename) const; + bool GenerateImportFile(const std::string &file); + cmExportBuildFileGenerator* + GetExportedTargetsFile(const std::string &filename) const; protected: typedef std::vector GeneratorVector; // for a project collect all its targets by following depend @@ -356,6 +352,7 @@ protected: bool InstallTargetEnabled; // Sets of named target exports cmExportSetMap ExportSets; + std::map BuildExportSets; // Manifest of all targets that will be built for each configuration. // This is computed just before local generators generate. @@ -384,7 +381,6 @@ private: std::map ExtensionToLanguage; std::map LanguageToLinkerPreference; std::map LanguageToOriginalSharedLibFlags; - std::set ExportedTargetsFiles; // Record hashes for rules and outputs. struct RuleHash { char Data[32]; }; diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx index 39d4993eba..5b931713cb 100644 --- a/Source/cmIncludeCommand.cxx +++ b/Source/cmIncludeCommand.cxx @@ -127,6 +127,7 @@ bool cmIncludeCommand return false; } } + gg->GenerateImportFile(fname_abs); } std::string fullFilePath; diff --git a/Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt index ae7627e1e8..405dd8dc8a 100644 --- a/Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt +++ b/Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at CMP0022-export.cmake:11 \(export\): +CMake Error in CMakeLists.txt: Target "cmp0022NEW" 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 diff --git a/Tests/RunCMake/ExportWithoutLanguage/NoLanguage-stderr.txt b/Tests/RunCMake/ExportWithoutLanguage/NoLanguage-stderr.txt index 67a0ae37cd..5658d85d49 100644 --- a/Tests/RunCMake/ExportWithoutLanguage/NoLanguage-stderr.txt +++ b/Tests/RunCMake/ExportWithoutLanguage/NoLanguage-stderr.txt @@ -1,6 +1,4 @@ CMake Error: CMake can not determine linker language for target: NoLanguage -CMake Error at NoLanguage.cmake:2 \(export\): +CMake Error in CMakeLists.txt: Exporting the target "NoLanguage" is not allowed since its linker language cannot be determined -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ExportWithoutLanguage/header.h b/Tests/RunCMake/ExportWithoutLanguage/header.h new file mode 100644 index 0000000000..0c803ed036 --- /dev/null +++ b/Tests/RunCMake/ExportWithoutLanguage/header.h @@ -0,0 +1,2 @@ + +enum some_compilers { need_more_than_nothing };