| 497 | #endif |
| 498 | |
| 499 | std::string cmLocalNinjaGenerator::BuildCommandLine( |
| 500 | std::vector<std::string> const& cmdLines, std::string const& outputConfig, |
| 501 | std::string const& commandConfig, std::string const& customStep, |
| 502 | cmGeneratorTarget const* target) const |
| 503 | { |
| 504 | // If we have no commands but we need to build a command anyway, use noop. |
| 505 | // This happens when building a POST_BUILD value for link targets that |
| 506 | // don't use POST_BUILD. |
| 507 | if (cmdLines.empty()) { |
| 508 | return cmGlobalNinjaGenerator::SHELL_NOOP; |
| 509 | } |
| 510 | |
| 511 | // If this is a custom step then we will have no '$VAR' ninja placeholders. |
| 512 | // This means we can deal with long command sequences by writing to a script. |
| 513 | // Do this if the command lines are on the scale of the OS limit. |
| 514 | if (!customStep.empty()) { |
| 515 | size_t cmdLinesTotal = 0; |
| 516 | for (std::string const& cmd : cmdLines) { |
| 517 | cmdLinesTotal += cmd.length() + 6; |
| 518 | } |
| 519 | if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) { |
| 520 | std::string const scriptPath = this->WriteCommandScript( |
| 521 | cmdLines, outputConfig, commandConfig, customStep, target); |
| 522 | std::string cmd |
| 523 | #ifndef _WIN32 |
| 524 | = "/bin/sh " |
| 525 | #endif |
| 526 | ; |
| 527 | cmd += this->ConvertToOutputFormat( |
| 528 | this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(scriptPath), |
| 529 | cmOutputConverter::SHELL); |
| 530 | |
| 531 | // Add an unused argument based on script content so that Ninja |
| 532 | // knows when the command lines change. |
| 533 | cmd += " "; |
| 534 | cmCryptoHash hash(cmCryptoHash::AlgoSHA256); |
| 535 | cmd += hash.HashFile(scriptPath).substr(0, 16); |
| 536 | return cmd; |
| 537 | } |
| 538 | } |
| 539 | |
| 540 | std::ostringstream cmd; |
| 541 | #ifdef _WIN32 |
| 542 | cmGlobalNinjaGenerator const* gg = this->GetGlobalNinjaGenerator(); |
| 543 | bool const needCMD = |
| 544 | cmdLines.size() > 1 || (customStep.empty() && RuleNeedsCMD(cmdLines[0])); |
| 545 | for (auto li = cmdLines.begin(); li != cmdLines.end(); ++li) { |
| 546 | if (li != cmdLines.begin()) { |
| 547 | cmd << " && "; |
| 548 | } else if (needCMD) { |
| 549 | cmd << gg->GetComspec() << " /C \""; |
| 550 | } |
| 551 | // Put current cmdLine in brackets if it contains "||" because it has |
| 552 | // higher precedence than "&&" in cmd.exe |
| 553 | if (li->find("||") != std::string::npos) { |
| 554 | cmd << "( " << *li << " )"; |
| 555 | } else { |
| 556 | cmd << *li; |
no test coverage detected