Просмотр исходного кода

Ninja: Add `$subdir/all` targets

With the Makefile generator one can use `cd $subdir; make all` to build
all targets associated with a given subdirectory.  This is not possible
to do with the Ninja generator since there is only one `build.ninja`
file at the top of the build tree.  However, we can approximate it by
allowing one to run `ninja $subdir/all` at the top of the tree to build
the targets in the corresponding subdirectory.

Port logic from cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2 to
cmGlobalNinjaGenerator in order to produce equivalent directory-level
targets.
Charles Huet 9 лет назад
Родитель
Сommit
ca575fe935
3 измененных файлов с 89 добавлено и 0 удалено
  1. 4 0
      Help/generator/Ninja.rst
  2. 82 0
      Source/cmGlobalNinjaGenerator.cxx
  3. 3 0
      Source/cmGlobalNinjaGenerator.h

+ 4 - 0
Help/generator/Ninja.rst

@@ -6,3 +6,7 @@ Generates build.ninja files.
 A build.ninja file is generated into the build tree.  Recent versions
 A build.ninja file is generated into the build tree.  Recent versions
 of the ninja program can build the project through the "all" target.
 of the ninja program can build the project through the "all" target.
 An "install" target is also provided.
 An "install" target is also provided.
+
+For each subdirectory ``sub/dir`` of the project an additional target
+named ``sub/dir/all`` is generated that depends on all targets required
+by that subdirectory.

+ 82 - 0
Source/cmGlobalNinjaGenerator.cxx

@@ -577,6 +577,7 @@ void cmGlobalNinjaGenerator::Generate()
 
 
   this->WriteAssumedSourceDependencies();
   this->WriteAssumedSourceDependencies();
   this->WriteTargetAliases(*this->BuildFileStream);
   this->WriteTargetAliases(*this->BuildFileStream);
+  this->WriteFolderTargets(*this->BuildFileStream);
   this->WriteUnknownExplicitDependencies(*this->BuildFileStream);
   this->WriteUnknownExplicitDependencies(*this->BuildFileStream);
   this->WriteBuiltinTargets(*this->BuildFileStream);
   this->WriteBuiltinTargets(*this->BuildFileStream);
 
 
@@ -848,6 +849,18 @@ std::string cmGlobalNinjaGenerator::ConvertToNinjaPath(const std::string& path)
   return convPath;
   return convPath;
 }
 }
 
 
+std::string
+cmGlobalNinjaGenerator::ConvertToNinjaFolderRule(const std::string& path)
+{
+  cmLocalNinjaGenerator *ng =
+    static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]);
+  std::string convPath = ng->Convert(path+"/all", cmOutputConverter::HOME);
+#ifdef _WIN32
+  cmSystemTools::ReplaceString(convPath, "/", "\\");
+#endif
+  return convPath;
+}
+
 void cmGlobalNinjaGenerator::AddCXXCompileCommand(
 void cmGlobalNinjaGenerator::AddCXXCompileCommand(
                                       const std::string &commandLine,
                                       const std::string &commandLine,
                                       const std::string &sourceFile)
                                       const std::string &sourceFile)
@@ -1044,6 +1057,75 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
   }
   }
 }
 }
 
 
+void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
+{
+  cmGlobalNinjaGenerator::WriteDivider(os);
+  os << "# Folder targets.\n\n";
+
+  std::map<std::string, cmNinjaDeps> targetsPerFolder;
+  for (std::vector<cmLocalGenerator *>::const_iterator
+       lgi = this->LocalGenerators.begin();
+       lgi != this->LocalGenerators.end(); ++lgi)
+    {
+    cmLocalGenerator const* lg = *lgi;
+    const std::string currentSourceFolder(
+      lg->GetStateSnapshot().GetDirectory().GetCurrentSource());
+    // The directory-level rule should depend on the target-level rules
+    // for all targets in the directory.
+    targetsPerFolder[currentSourceFolder] = cmNinjaDeps();
+    for (std::vector<cmGeneratorTarget*>::const_iterator
+         ti = lg->GetGeneratorTargets().begin();
+         ti != lg->GetGeneratorTargets().end(); ++ti)
+      {
+      cmGeneratorTarget const* gt = *ti;
+      cmState::TargetType const type = gt->GetType();
+      if((type == cmState::EXECUTABLE ||
+          type == cmState::STATIC_LIBRARY ||
+          type == cmState::SHARED_LIBRARY ||
+          type == cmState::MODULE_LIBRARY ||
+          type == cmState::OBJECT_LIBRARY ||
+          type == cmState::UTILITY) &&
+         !gt->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
+        {
+        targetsPerFolder[currentSourceFolder].push_back(gt->GetName());
+        }
+      }
+
+    // The directory-level rule should depend on the directory-level
+    // rules of the subdirectories.
+    std::vector<cmState::Snapshot> const& children =
+      lg->GetStateSnapshot().GetChildren();
+    for(std::vector<cmState::Snapshot>::const_iterator
+        stateIt = children.begin(); stateIt != children.end(); ++stateIt)
+      {
+      targetsPerFolder[currentSourceFolder].push_back(
+        this->ConvertToNinjaFolderRule(
+          stateIt->GetDirectory().GetCurrentSource()));
+      }
+    }
+
+  std::string const rootSourceDir =
+    this->LocalGenerators[0]->GetSourceDirectory();
+  for (std::map<std::string, cmNinjaDeps >::const_iterator it =
+       targetsPerFolder.begin(); it != targetsPerFolder.end(); ++it)
+    {
+    cmGlobalNinjaGenerator::WriteDivider( os );
+    std::string const& currentSourceDir = it->first;
+
+    // Do not generate a rule for the root source dir.
+    if (rootSourceDir.length() >= currentSourceDir.length())
+      {
+      continue;
+      }
+
+    std::string const comment = "Folder: " + currentSourceDir;
+    cmNinjaDeps output(1);
+    output.push_back(this->ConvertToNinjaFolderRule(currentSourceDir));
+
+    this->WritePhonyBuild(os, comment, output, it->second);
+    }
+}
+
 void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
 void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
 {
 {
   if (!this->ComputingUnknownDependencies)
   if (!this->ComputingUnknownDependencies)

+ 3 - 0
Source/cmGlobalNinjaGenerator.h

@@ -228,6 +228,8 @@ public:
     return this->RulesFileStream; }
     return this->RulesFileStream; }
 
 
   std::string ConvertToNinjaPath(const std::string& path);
   std::string ConvertToNinjaPath(const std::string& path);
+  std::string ConvertToNinjaFolderRule(const std::string& path);
+
 
 
   struct MapToNinjaPathImpl {
   struct MapToNinjaPathImpl {
     cmGlobalNinjaGenerator* GG;
     cmGlobalNinjaGenerator* GG;
@@ -342,6 +344,7 @@ private:
   void WriteAssumedSourceDependencies();
   void WriteAssumedSourceDependencies();
 
 
   void WriteTargetAliases(std::ostream& os);
   void WriteTargetAliases(std::ostream& os);
+  void WriteFolderTargets(std::ostream& os);
   void WriteUnknownExplicitDependencies(std::ostream& os);
   void WriteUnknownExplicitDependencies(std::ostream& os);
 
 
   void WriteBuiltinTargets(std::ostream& os);
   void WriteBuiltinTargets(std::ostream& os);