diff options
author | Brad King <brad.king@kitware.com> | 2006-04-11 15:06:19 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2006-04-11 15:06:19 (GMT) |
commit | d5719f22c1dca3e100f1e3b5dfaa4fe7d26796a0 (patch) | |
tree | 714a99bed97290f96ff8f846fa6864cebbdc0a28 /Source/cmGlobalXCodeGenerator.cxx | |
parent | b613cf0be806cc1d37d2b590f1a5ba7898236ae8 (diff) | |
download | CMake-d5719f22c1dca3e100f1e3b5dfaa4fe7d26796a0.zip CMake-d5719f22c1dca3e100f1e3b5dfaa4fe7d26796a0.tar.gz CMake-d5719f22c1dca3e100f1e3b5dfaa4fe7d26796a0.tar.bz2 |
ENH: Added support for multiple outputs generated by a single custom command. For Visual Studio generators the native tool provides support. For Xcode and Makefile generators a simple trick is used. The first output is considered primary and has the build rule attached. Other outputs simply depend on the first output with no build rule. During cmake_check_build_system CMake detects when a secondary output is missing and removes the primary output to make sure all outputs are regenerated. This approach always builds the custom command at the right time and only once even during parallel builds.
Diffstat (limited to 'Source/cmGlobalXCodeGenerator.cxx')
-rw-r--r-- | Source/cmGlobalXCodeGenerator.cxx | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index ffef321..d86bf2d 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -887,6 +887,8 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, this->CreateString(makecmd.c_str())); return; } + + std::map<cmStdString, cmStdString> multipleOutputPairs; std::string dir = this->CurrentMakefile->GetCurrentOutputDirectory(); dir += "/CMakeScripts"; @@ -916,10 +918,15 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, cmCustomCommand const& cc = *i; if(!cc.GetCommandLines().empty()) { - if(cc.GetOutput()[0]) + const std::vector<std::string>& outputs = cc.GetOutputs(); + if(!outputs.empty()) { - makefileStream << "\\\n\t" << this-> - ConvertToRelativeForMake(cc.GetOutput()); + for(std::vector<std::string>::const_iterator o = outputs.begin(); + o != outputs.end(); ++o) + { + makefileStream + << "\\\n\t" << this->ConvertToRelativeForMake(o->c_str()); + } } else { @@ -940,13 +947,29 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, makefileStream << "\n#" << "Custom command rule: " << cc.GetComment() << "\n"; - if(cc.GetOutput()[0]) + const std::vector<std::string>& outputs = cc.GetOutputs(); + if(!outputs.empty()) { - makefileStream << this - ->ConvertToRelativeForMake(cc.GetOutput()) << ": "; + // There is at least one output. If there is more than one treat the + // first as the primary output and make the rest depend on it. + std::vector<std::string>::const_iterator o = outputs.begin(); + std::string primary_output = + this->ConvertToRelativeForMake(o->c_str()); + for(++o; o != outputs.end(); ++o) + { + std::string current_output = + this->ConvertToRelativeForMake(o->c_str()); + makefileStream << current_output << ": " + << primary_output << "\n"; + multipleOutputPairs[current_output] = primary_output; + } + + // Start the rule for the primary output. + makefileStream << primary_output << ": "; } else { + // There are no outputs. Use the generated force rule name. makefileStream << tname[&cc] << ": "; } for(std::vector<std::string>::const_iterator d = cc.GetDepends().begin(); @@ -1001,12 +1024,33 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, } } } + + // Add a rule to deal with multiple outputs of custom commands. + if(!multipleOutputPairs.empty()) + { + makefileStream << + "\n" + "cmake_check_multiple_outputs:\n"; + for(std::map<cmStdString, cmStdString>::const_iterator o = + multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o) + { + makefileStream << "\t@if [ ! -f " + << o->first << " ]; then rm -f " + << o->second << "; fi\n"; + } + } + std::string cdir = this->CurrentMakefile->GetCurrentOutputDirectory(); cdir = this->ConvertToRelativeForXCode(cdir.c_str()); std::string makecmd = "make -C "; makecmd += cdir; makecmd += " -f "; makecmd += this->ConvertToRelativeForMake(makefile.c_str()); + if(!multipleOutputPairs.empty()) + { + makecmd += " cmake_check_multiple_outputs"; + } + makecmd += " all"; cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ "); buildphase->AddAttribute("shellScript", this->CreateString(makecmd.c_str())); } |