/*============================================================================ CMake - Cross Platform Makefile Generator Copyright 2011 Peter Collingbourne Copyright 2011 Nicolas Despres Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ #include "cmNinjaUtilityTargetGenerator.h" #include "cmCustomCommand.h" #include "cmGeneratedFileStream.h" #include "cmGlobalNinjaGenerator.h" #include "cmMakefile.h" #include "cmSourceFile.h" #include "cmCustomCommandGenerator.h" cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator( cmGeneratorTarget *target) : cmNinjaTargetGenerator(target) {} cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() {} void cmNinjaUtilityTargetGenerator::Generate() { std::string utilCommandName = cmake::GetCMakeFilesDirectoryPostSlash(); utilCommandName += this->GetTargetName() + ".util"; std::vector commands; cmNinjaDeps deps, outputs, util_outputs(1, utilCommandName); const std::vector *cmdLists[2] = { &this->GetGeneratorTarget()->GetPreBuildCommands(), &this->GetGeneratorTarget()->GetPostBuildCommands() }; bool uses_terminal = false; for (unsigned i = 0; i != 2; ++i) { for (std::vector::const_iterator ci = cmdLists[i]->begin(); ci != cmdLists[i]->end(); ++ci) { cmCustomCommandGenerator ccg(*ci, this->GetConfigName(), this->GetLocalGenerator()); this->GetLocalGenerator()->AppendCustomCommandDeps(ccg, deps); this->GetLocalGenerator()->AppendCustomCommandLines(ccg, commands); std::vector const& ccByproducts = ccg.GetByproducts(); std::transform(ccByproducts.begin(), ccByproducts.end(), std::back_inserter(util_outputs), MapToNinjaPath()); if (ci->GetUsesTerminal()) uses_terminal = true; } } std::vector sources; std::string config = this->GetMakefile() ->GetSafeDefinition("CMAKE_BUILD_TYPE"); this->GetGeneratorTarget()->GetSourceFiles(sources, config); for(std::vector::const_iterator source = sources.begin(); source != sources.end(); ++source) { if(cmCustomCommand* cc = (*source)->GetCustomCommand()) { cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->GetLocalGenerator()); this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetGeneratorTarget()); // Depend on all custom command outputs. const std::vector& ccOutputs = ccg.GetOutputs(); const std::vector& ccByproducts = ccg.GetByproducts(); std::transform(ccOutputs.begin(), ccOutputs.end(), std::back_inserter(deps), MapToNinjaPath()); std::transform(ccByproducts.begin(), ccByproducts.end(), std::back_inserter(deps), MapToNinjaPath()); } } this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(), outputs); this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(), deps); if (commands.empty()) { this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(), "Utility command for " + this->GetTargetName(), outputs, deps); } else { std::string command = this->GetLocalGenerator()->BuildCommandLine(commands); const char *echoStr = this->GetGeneratorTarget()->GetProperty("EchoString"); std::string desc; if (echoStr) desc = echoStr; else desc = "Running utility command for " + this->GetTargetName(); // TODO: fix problematic global targets. For now, search and replace the // makefile vars. cmSystemTools::ReplaceString( command, "$(CMAKE_SOURCE_DIR)", this->GetLocalGenerator()->ConvertToOutputFormat( this->GetLocalGenerator()->GetSourceDirectory(), cmLocalGenerator::SHELL).c_str()); cmSystemTools::ReplaceString( command, "$(CMAKE_BINARY_DIR)", this->GetLocalGenerator()->ConvertToOutputFormat( this->GetLocalGenerator()->GetBinaryDirectory(), cmLocalGenerator::SHELL).c_str()); cmSystemTools::ReplaceString(command, "$(ARGS)", ""); if (command.find('$') != std::string::npos) return; for (cmNinjaDeps::const_iterator oi = util_outputs.begin(), oe = util_outputs.end(); oi != oe; ++oi) { this->GetGlobalGenerator()->SeenCustomCommandOutput(*oi); } this->GetGlobalGenerator()->WriteCustomCommandBuild( command, desc, "Utility command for " + this->GetTargetName(), uses_terminal, /*restat*/true, util_outputs, deps); this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(), "", outputs, cmNinjaDeps(1, utilCommandName) ); } this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(), this->GetGeneratorTarget()); }