summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2019-09-27 13:23:35 (GMT)
committerBrad King <brad.king@kitware.com>2019-09-30 14:33:20 (GMT)
commitd713bcb6427381ab8743084726196a4eed96c135 (patch)
treedb9efe36c12ef50225a7e6d5361971f94063899c /Source
parenta75586c775eb8f663ca1372ff20f9a51e1ad420d (diff)
downloadCMake-d713bcb6427381ab8743084726196a4eed96c135.zip
CMake-d713bcb6427381ab8743084726196a4eed96c135.tar.gz
CMake-d713bcb6427381ab8743084726196a4eed96c135.tar.bz2
Ninja: Factor out per-dir "all" target computation into common generator
This will make it re-usable for the Makefile generator.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGlobalCommonGenerator.cxx66
-rw-r--r--Source/cmGlobalCommonGenerator.h24
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx80
3 files changed, 112 insertions, 58 deletions
diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx
index bf992b4..93ff00b 100644
--- a/Source/cmGlobalCommonGenerator.cxx
+++ b/Source/cmGlobalCommonGenerator.cxx
@@ -2,6 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalCommonGenerator.h"
+#include "cmGeneratorTarget.h"
+#include "cmLocalGenerator.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+
+#include <utility>
+
class cmake;
cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
@@ -10,3 +19,60 @@ cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
}
cmGlobalCommonGenerator::~cmGlobalCommonGenerator() = default;
+
+std::map<std::string, cmGlobalCommonGenerator::DirectoryTarget>
+cmGlobalCommonGenerator::ComputeDirectoryTargets() const
+{
+ std::map<std::string, DirectoryTarget> dirTargets;
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
+ std::string const& currentBinaryDir(
+ lg->GetStateSnapshot().GetDirectory().GetCurrentBinary());
+ DirectoryTarget& dirTarget = dirTargets[currentBinaryDir];
+ dirTarget.LG = lg;
+
+ // The directory-level rule should depend on the target-level rules
+ // for all targets in the directory.
+ for (auto gt : lg->GetGeneratorTargets()) {
+ cmStateEnums::TargetType const type = gt->GetType();
+ if (type != cmStateEnums::EXECUTABLE &&
+ type != cmStateEnums::STATIC_LIBRARY &&
+ type != cmStateEnums::SHARED_LIBRARY &&
+ type != cmStateEnums::MODULE_LIBRARY &&
+ type != cmStateEnums::OBJECT_LIBRARY &&
+ type != cmStateEnums::UTILITY) {
+ continue;
+ }
+ DirectoryTarget::Target t;
+ t.GT = gt;
+ if (const char* exclude = gt->GetProperty("EXCLUDE_FROM_ALL")) {
+ if (cmIsOn(exclude)) {
+ // This target has been explicitly excluded.
+ t.ExcludeFromAll = true;
+ } else {
+ // 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 const& 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;
+}
diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h
index e19118b..de81da7 100644
--- a/Source/cmGlobalCommonGenerator.h
+++ b/Source/cmGlobalCommonGenerator.h
@@ -7,7 +7,13 @@
#include "cmGlobalGenerator.h"
+#include <map>
+#include <string>
+#include <vector>
+
class cmake;
+class cmGeneratorTarget;
+class cmLocalGenerator;
/** \class cmGlobalCommonGenerator
* \brief Common infrastructure for Makefile and Ninja global generators.
@@ -17,6 +23,24 @@ class cmGlobalCommonGenerator : public cmGlobalGenerator
public:
cmGlobalCommonGenerator(cmake* cm);
~cmGlobalCommonGenerator() override;
+
+ struct DirectoryTarget
+ {
+ cmLocalGenerator* LG = nullptr;
+ struct Target
+ {
+ cmGeneratorTarget const* GT = nullptr;
+ bool ExcludeFromAll = false;
+ };
+ std::vector<Target> Targets;
+ struct Dir
+ {
+ std::string Path;
+ bool ExcludeFromAll = false;
+ };
+ std::vector<Dir> Children;
+ };
+ std::map<std::string, DirectoryTarget> ComputeDirectoryTargets() const;
};
#endif
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 3497828..d8fe258 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -1087,68 +1087,32 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
cmGlobalNinjaGenerator::WriteDivider(os);
os << "# Folder targets.\n\n";
- std::map<std::string, cmNinjaDeps> targetsPerFolder;
- for (cmLocalGenerator const* lg : this->LocalGenerators) {
- std::string const& currentBinaryFolder(
- lg->GetStateSnapshot().GetDirectory().GetCurrentBinary());
-
- // The directory-level rule should depend on the target-level rules
- // for all targets in the directory.
- cmNinjaDeps& folderTargets = targetsPerFolder[currentBinaryFolder];
- for (auto gt : lg->GetGeneratorTargets()) {
- cmStateEnums::TargetType const type = gt->GetType();
- if ((type == cmStateEnums::EXECUTABLE ||
- type == cmStateEnums::STATIC_LIBRARY ||
- type == cmStateEnums::SHARED_LIBRARY ||
- type == cmStateEnums::MODULE_LIBRARY ||
- type == cmStateEnums::OBJECT_LIBRARY ||
- type == cmStateEnums::UTILITY)) {
- if (const char* exclude = gt->GetProperty("EXCLUDE_FROM_ALL")) {
- if (cmIsOn(exclude)) {
- // This target has been explicitly excluded.
- continue;
- }
- // 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 const& folder = dir.GetDirectory().GetCurrentBinary();
- this->AppendTargetOutputs(gt, targetsPerFolder[folder]);
- }
- }
- this->AppendTargetOutputs(gt, folderTargets);
- }
- }
+ std::map<std::string, DirectoryTarget> dirTargets =
+ this->ComputeDirectoryTargets();
- // The directory-level rule should depend on the directory-level
- // rules of the subdirectories.
- for (cmStateSnapshot const& state : lg->GetStateSnapshot().GetChildren()) {
- if (state.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
- continue;
+ for (auto const& it : dirTargets) {
+ cmNinjaBuild build("phony");
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ std::string const& currentBinaryDir = it.first;
+ DirectoryTarget const& dt = it.second;
+
+ // Setup target
+ build.Comment = "Folder: " + currentBinaryDir;
+ build.Outputs.emplace_back(
+ this->ConvertToNinjaPath(currentBinaryDir + "/all"));
+ for (DirectoryTarget::Target const& t : dt.Targets) {
+ if (!t.ExcludeFromAll) {
+ this->AppendTargetOutputs(t.GT, build.ExplicitDeps);
}
- std::string const& currentBinaryDir =
- state.GetDirectory().GetCurrentBinary();
- folderTargets.push_back(
- this->ConvertToNinjaPath(currentBinaryDir + "/all"));
}
- }
-
- if (!targetsPerFolder.empty()) {
- cmNinjaBuild build("phony");
- build.Outputs.emplace_back("");
- for (auto& it : targetsPerFolder) {
- cmGlobalNinjaGenerator::WriteDivider(os);
- std::string const& currentBinaryDir = it.first;
-
- // Setup target
- build.Comment = "Folder: " + currentBinaryDir;
- build.Outputs[0] = this->ConvertToNinjaPath(currentBinaryDir + "/all");
- build.ExplicitDeps = std::move(it.second);
- // Write target
- this->WriteBuild(os, build);
+ for (DirectoryTarget::Dir const& d : dt.Children) {
+ if (!d.ExcludeFromAll) {
+ build.ExplicitDeps.emplace_back(
+ this->ConvertToNinjaPath(d.Path + "/all"));
+ }
}
+ // Write target
+ this->WriteBuild(os, build);
}
}