| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| #include "cmGlobalCommonGenerator.h" |
| |
| #include <algorithm> |
| #include <memory> |
| #include <utility> |
| |
| #include <cmext/algorithm> |
| |
| #include <cmsys/Glob.hxx> |
| |
| #include "cmGeneratorExpression.h" |
| #include "cmGeneratorTarget.h" |
| #include "cmLocalCommonGenerator.h" |
| #include "cmLocalGenerator.h" |
| #include "cmStateDirectory.h" |
| #include "cmStateSnapshot.h" |
| #include "cmStateTypes.h" |
| #include "cmStringAlgorithms.h" |
| #include "cmSystemTools.h" |
| #include "cmValue.h" |
| #include "cmake.h" |
| |
| cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm) |
| : cmGlobalGenerator(cm) |
| { |
| } |
| |
| cmGlobalCommonGenerator::~cmGlobalCommonGenerator() = default; |
| |
| std::map<std::string, cmGlobalCommonGenerator::DirectoryTarget> |
| cmGlobalCommonGenerator::ComputeDirectoryTargets() const |
| { |
| std::map<std::string, DirectoryTarget> dirTargets; |
| for (const auto& lg : this->LocalGenerators) { |
| std::string currentBinaryDir = |
| lg->GetStateSnapshot().GetDirectory().GetCurrentBinary(); |
| DirectoryTarget& dirTarget = dirTargets[currentBinaryDir]; |
| dirTarget.LG = lg.get(); |
| std::vector<std::string> const& configs = |
| static_cast<cmLocalCommonGenerator const*>(lg.get())->GetConfigNames(); |
| |
| // The directory-level rule should depend on the target-level rules |
| // for all targets in the directory. |
| for (const auto& gt : lg->GetGeneratorTargets()) { |
| cmStateEnums::TargetType const type = gt->GetType(); |
| if (type == cmStateEnums::GLOBAL_TARGET || !gt->IsInBuildSystem()) { |
| continue; |
| } |
| DirectoryTarget::Target t; |
| t.GT = gt.get(); |
| const std::string EXCLUDE_FROM_ALL("EXCLUDE_FROM_ALL"); |
| if (cmValue exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) { |
| for (const std::string& config : configs) { |
| cmGeneratorExpressionInterpreter genexInterpreter(lg.get(), config, |
| gt.get()); |
| if (cmIsOn(genexInterpreter.Evaluate(*exclude, EXCLUDE_FROM_ALL))) { |
| // This target has been explicitly excluded. |
| t.ExcludedFromAllInConfigs.push_back(config); |
| } |
| } |
| |
| if (t.ExcludedFromAllInConfigs.empty()) { |
| // This target has been explicitly un-excluded. The directory-level |
| // rule for every directory between this and the root should depend |
| // on the target-level rule for this target. |
| for (cmStateSnapshot dir = |
| lg->GetStateSnapshot().GetBuildsystemDirectoryParent(); |
| dir.IsValid(); dir = dir.GetBuildsystemDirectoryParent()) { |
| std::string d = dir.GetDirectory().GetCurrentBinary(); |
| dirTargets[d].Targets.emplace_back(t); |
| } |
| } |
| } |
| dirTarget.Targets.emplace_back(t); |
| } |
| |
| // The directory-level rule should depend on the directory-level |
| // rules of the subdirectories. |
| for (cmStateSnapshot const& state : lg->GetStateSnapshot().GetChildren()) { |
| DirectoryTarget::Dir d; |
| d.Path = state.GetDirectory().GetCurrentBinary(); |
| d.ExcludeFromAll = |
| state.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL"); |
| dirTarget.Children.emplace_back(std::move(d)); |
| } |
| } |
| |
| return dirTargets; |
| } |
| |
| bool cmGlobalCommonGenerator::IsExcludedFromAllInConfig( |
| const DirectoryTarget::Target& t, const std::string& config) |
| { |
| if (this->IsMultiConfig()) { |
| return cm::contains(t.ExcludedFromAllInConfigs, config); |
| } |
| return !t.ExcludedFromAllInConfigs.empty(); |
| } |
| |
| std::string cmGlobalCommonGenerator::GetEditCacheCommand() const |
| { |
| // If generating for an extra IDE, the edit_cache target cannot |
| // launch a terminal-interactive tool, so always use cmake-gui. |
| if (!this->GetExtraGeneratorName().empty()) { |
| return cmSystemTools::GetCMakeGUICommand(); |
| } |
| |
| // Use an internal cache entry to track the latest dialog used |
| // to edit the cache, and use that for the edit_cache target. |
| cmake* cm = this->GetCMakeInstance(); |
| std::string editCacheCommand = cm->GetCMakeEditCommand(); |
| if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") || |
| !editCacheCommand.empty()) { |
| if (this->SupportsDirectConsole() && editCacheCommand.empty()) { |
| editCacheCommand = cmSystemTools::GetCMakeCursesCommand(); |
| } |
| if (editCacheCommand.empty()) { |
| editCacheCommand = cmSystemTools::GetCMakeGUICommand(); |
| } |
| if (!editCacheCommand.empty()) { |
| cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand, |
| "Path to cache edit program executable.", |
| cmStateEnums::INTERNAL); |
| } |
| } |
| cmValue edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND"); |
| return edit_cmd ? *edit_cmd : std::string(); |
| } |
| |
| void cmGlobalCommonGenerator::RemoveUnknownClangTidyExportFixesFiles() const |
| { |
| for (auto const& dir : this->ClangTidyExportFixesDirs) { |
| cmsys::Glob g; |
| g.SetRecurse(true); |
| g.SetListDirs(false); |
| g.FindFiles(cmStrCat(dir, "/*.yaml")); |
| for (auto const& file : g.GetFiles()) { |
| if (!this->ClangTidyExportFixesFiles.count(file) && |
| !std::any_of(this->ClangTidyExportFixesFiles.begin(), |
| this->ClangTidyExportFixesFiles.end(), |
| [&file](const std::string& knownFile) -> bool { |
| return cmSystemTools::SameFile(file, knownFile); |
| })) { |
| cmSystemTools::RemoveFile(file); |
| } |
| } |
| } |
| } |