diff options
-rw-r--r-- | Help/generator/Ninja.rst | 4 | ||||
-rw-r--r-- | Source/cmGlobalNinjaGenerator.cxx | 82 | ||||
-rw-r--r-- | Source/cmGlobalNinjaGenerator.h | 3 |
3 files changed, 89 insertions, 0 deletions
diff --git a/Help/generator/Ninja.rst b/Help/generator/Ninja.rst index 920abcb..d94e5f6 100644 --- a/Help/generator/Ninja.rst +++ b/Help/generator/Ninja.rst @@ -6,3 +6,7 @@ Generates build.ninja files. A build.ninja file is generated into the build tree. Recent versions of the ninja program can build the project through the "all" target. 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. diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 83422b7..f12396f 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -577,6 +577,7 @@ void cmGlobalNinjaGenerator::Generate() this->WriteAssumedSourceDependencies(); this->WriteTargetAliases(*this->BuildFileStream); + this->WriteFolderTargets(*this->BuildFileStream); this->WriteUnknownExplicitDependencies(*this->BuildFileStream); this->WriteBuiltinTargets(*this->BuildFileStream); @@ -848,6 +849,18 @@ std::string cmGlobalNinjaGenerator::ConvertToNinjaPath(const std::string& path) 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( const std::string &commandLine, 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) { if (!this->ComputingUnknownDependencies) diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 8656590..3023a95 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -228,6 +228,8 @@ public: return this->RulesFileStream; } std::string ConvertToNinjaPath(const std::string& path); + std::string ConvertToNinjaFolderRule(const std::string& path); + struct MapToNinjaPathImpl { cmGlobalNinjaGenerator* GG; @@ -342,6 +344,7 @@ private: void WriteAssumedSourceDependencies(); void WriteTargetAliases(std::ostream& os); + void WriteFolderTargets(std::ostream& os); void WriteUnknownExplicitDependencies(std::ostream& os); void WriteBuiltinTargets(std::ostream& os); |