diff options
Diffstat (limited to 'Source/cmGlobalGenerator.cxx')
-rw-r--r-- | Source/cmGlobalGenerator.cxx | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index aeebc6f..a38208c 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -32,6 +32,7 @@ #include "cmCryptoHash.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" +#include "cmCustomCommandTypes.h" #include "cmDuration.h" #include "cmExportBuildFileGenerator.h" #include "cmExternalMakefileProjectGenerator.h" @@ -68,6 +69,8 @@ # include "cmQtAutoGenGlobalInitializer.h" #endif +class cmListFileBacktrace; + const std::string kCMAKE_PLATFORM_INFO_INITIALIZED = "CMAKE_PLATFORM_INFO_INITIALIZED"; @@ -1569,6 +1572,10 @@ bool cmGlobalGenerator::Compute() } this->FinalizeTargetConfiguration(); + if (!this->AddBuildDatabaseTargets()) { + return false; + } + this->CreateGenerationObjects(); // at this point this->LocalGenerators has been filled, @@ -2834,6 +2841,20 @@ bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName, reason); } +bool cmGlobalGenerator::CheckCMP0037Prefix(std::string const& targetPrefix, + std::string const& reason) const +{ + bool ret = true; + for (auto const& tgtPair : this->TargetSearchIndex) { + if (cmHasPrefix(tgtPair.first, targetPrefix) && + !RaiseCMP0037Message(this->GetCMakeInstance(), tgtPair.second, + tgtPair.first, reason)) { + ret = false; + } + } + return ret; +} + void cmGlobalGenerator::CreateDefaultGlobalTargets( std::vector<GlobalTargetInfo>& targets) { @@ -3186,6 +3207,201 @@ void cmGlobalGenerator::AddGlobalTarget_Install( } } +class ModuleCompilationDatabaseCommandAction +{ +public: + ModuleCompilationDatabaseCommandAction( + std::string output, std::function<std::vector<std::string>()> inputs) + : Output(std::move(output)) + , Inputs(std::move(inputs)) + { + } + void operator()(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + std::unique_ptr<cmCustomCommand> cc); + +private: + std::string const Output; + std::function<std::vector<std::string>()> const Inputs; +}; + +void ModuleCompilationDatabaseCommandAction::operator()( + cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + std::unique_ptr<cmCustomCommand> cc) +{ + auto inputs = this->Inputs(); + + cmCustomCommandLines command_lines; + cmCustomCommandLine command_line; + { + command_line.emplace_back(cmSystemTools::GetCMakeCommand()); + command_line.emplace_back("-E"); + command_line.emplace_back("cmake_module_compile_db"); + command_line.emplace_back("merge"); + command_line.emplace_back("-o"); + command_line.emplace_back(this->Output); + for (auto const& input : inputs) { + command_line.emplace_back(input); + } + } + command_lines.emplace_back(std::move(command_line)); + + cc->SetBacktrace(lfbt); + cc->SetCommandLines(command_lines); + cc->SetWorkingDirectory(lg.GetBinaryDirectory().c_str()); + cc->SetDependsExplicitOnly(true); + cc->SetOutputs(this->Output); + if (!inputs.empty()) { + cc->SetMainDependency(inputs[0]); + } + cc->SetDepends(inputs); + detail::AddCustomCommandToOutput(lg, cmCommandOrigin::Generator, + std::move(cc), false); +} + +class ModuleCompilationDatabaseTargetAction +{ +public: + ModuleCompilationDatabaseTargetAction(std::string output, cmTarget* target) + : Output(std::move(output)) + , Target(target) + { + } + void operator()(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + std::unique_ptr<cmCustomCommand> cc); + +private: + std::string const Output; + cmTarget* const Target; +}; + +void ModuleCompilationDatabaseTargetAction::operator()( + cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + std::unique_ptr<cmCustomCommand> cc) +{ + cc->SetBacktrace(lfbt); + cc->SetWorkingDirectory(lg.GetBinaryDirectory().c_str()); + std::vector<std::string> target_inputs; + target_inputs.emplace_back(this->Output); + cc->SetDepends(target_inputs); + detail::AddUtilityCommand(lg, cmCommandOrigin::Generator, this->Target, + std::move(cc)); +} + +void cmGlobalGenerator::AddBuildDatabaseFile(std::string const& lang, + std::string const& config, + std::string const& path) +{ + if (!config.empty()) { + this->PerConfigModuleDbs[config][lang].push_back(path); + } + this->PerLanguageModuleDbs[lang].push_back(path); +} + +bool cmGlobalGenerator::AddBuildDatabaseTargets() +{ + auto& mf = this->Makefiles[0]; + if (!mf->IsOn("CMAKE_EXPORT_BUILD_DATABASE")) { + return true; + } + + static const auto reservedTargets = { "cmake_build_database" }; + for (auto const& target : reservedTargets) { + if (!this->CheckCMP0037(target, + "when exporting build databases are enabled")) { + return false; + } + } + static const auto reservedPrefixes = { "cmake_build_database-" }; + for (auto const& prefix : reservedPrefixes) { + if (!this->CheckCMP0037Prefix( + prefix, "when exporting build databases are enabled")) { + return false; + } + } + + if (!this->SupportsBuildDatabase()) { + return true; + } + + auto configs = mf->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig); + + static cm::static_string_view TargetPrefix = "cmake_build_database"_s; + auto AddMergeTarget = + [&mf](std::string const& name, const char* comment, + std::string const& output, + std::function<std::vector<std::string>()> inputs) { + // Add the custom command. + { + ModuleCompilationDatabaseCommandAction action{ output, + std::move(inputs) }; + auto cc = cm::make_unique<cmCustomCommand>(); + cc->SetComment(comment); + mf->AddGeneratorAction( + std::move(cc), action, + cmMakefile::GeneratorActionWhen::AfterGeneratorTargets); + } + + // Add a custom target with the given name. + { + cmTarget* target = mf->AddNewUtilityTarget(name, true); + ModuleCompilationDatabaseTargetAction action{ output, target }; + auto cc = cm::make_unique<cmCustomCommand>(); + mf->AddGeneratorAction(std::move(cc), action); + } + }; + + std::string module_languages[] = { "CXX" }; + + // Add per-configuration targets. + for (auto const& config : configs) { + // Add per-language targets. + std::vector<std::string> all_config_paths; + for (auto const& lang : module_languages) { + auto comment = cmStrCat("Combining module command databases for ", lang, + " and ", config); + auto output = cmStrCat(mf->GetHomeOutputDirectory(), "/build_database_", + lang, '_', config, ".json"); + mf->GetOrCreateGeneratedSource(output); + AddMergeTarget(cmStrCat(TargetPrefix, '-', lang, '-', config), + comment.c_str(), output, [this, config, lang]() { + return this->PerConfigModuleDbs[config][lang]; + }); + all_config_paths.emplace_back(std::move(output)); + } + + // Add the overall target. + auto comment = cmStrCat("Combining module command databases for ", config); + auto output = cmStrCat(mf->GetHomeOutputDirectory(), "/build_database_", + config, ".json"); + mf->GetOrCreateGeneratedSource(output); + AddMergeTarget(cmStrCat(TargetPrefix, '-', config), comment.c_str(), + output, [all_config_paths]() { return all_config_paths; }); + } + + // NMC considerations + // Add per-language targets. + std::vector<std::string> all_config_paths; + for (auto const& lang : module_languages) { + auto comment = cmStrCat("Combining module command databases for ", lang); + auto output = cmStrCat(mf->GetHomeOutputDirectory(), "/build_database_", + lang, ".json"); + mf->GetOrCreateGeneratedSource(output); + AddMergeTarget( + cmStrCat(TargetPrefix, '-', lang), comment.c_str(), output, + [this, lang]() { return this->PerLanguageModuleDbs[lang]; }); + all_config_paths.emplace_back(std::move(output)); + } + + // Add the overall target. + auto const* comment = "Combining all module command databases"; + auto output = cmStrCat(mf->GetHomeOutputDirectory(), "/build_database.json"); + mf->GetOrCreateGeneratedSource(output); + AddMergeTarget(std::string(TargetPrefix), comment, output, + [all_config_paths]() { return all_config_paths; }); + + return true; +} + std::string cmGlobalGenerator::GetPredefinedTargetsFolder() const { cmValue prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty( |