| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst 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 "cmTargetTypes.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 (auto const& 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 (auto const& gt : lg->GetGeneratorTargets()) { | |
| cm::TargetType const type = gt->GetType(); | |
| if (type == cm::TargetType::GLOBAL_TARGET || !gt->IsInBuildSystem()) { | |
| continue; | |
| } | |
| DirectoryTarget::Target t; | |
| t.GT = gt.get(); | |
| std::string const EXCLUDE_FROM_ALL("EXCLUDE_FROM_ALL"); | |
| if (cmValue exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) { | |
| for (std::string const& 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( | |
| DirectoryTarget::Target const& t, std::string const& 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](std::string const& knownFile) -> bool { | |
| return cmSystemTools::SameFile(file, knownFile); | |
| })) { | |
| cmSystemTools::RemoveFile(file); | |
| } | |
| } | |
| } | |
| } |