From 8a4c6d2d2e66d210e5c2d59c86b3f1bff2582867 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 5 Dec 2014 09:50:31 -0500 Subject: [PATCH 1/4] Xcode: Fix rebuild with multiple custom command outputs (#15116) The Xcode generator uses Makefiles under a run-script build-phase to drive custom commands. Fix the generated makefiles for custom commands with multiple outputs to list all the outputs on the left hand side of the build rule. This is much simpler and more reliable than the old multiple-output-pair infrastructure. --- Source/cmGlobalXCodeGenerator.cxx | 61 ++++++------------------------- Source/cmGlobalXCodeGenerator.h | 3 +- 2 files changed, 12 insertions(+), 52 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index d22228843..de6e91546 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1498,7 +1498,6 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, const & commands, const char* name) { - bool haveMultipleOutputPairs = false; std::string dir = this->CurrentMakefile->GetCurrentOutputDirectory(); dir += "/CMakeScripts"; cmSystemTools::MakeDirectory(dir.c_str()); @@ -1517,8 +1516,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, this->CreateCustomRulesMakefile(makefile.c_str(), target, commands, - currentConfig->c_str(), - haveMultipleOutputPairs); + currentConfig->c_str()); } std::string cdir = this->CurrentMakefile->GetCurrentOutputDirectory(); @@ -1528,10 +1526,6 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, makecmd += " -f "; makecmd += this->ConvertToRelativeForMake( (makefile+"$CONFIGURATION").c_str()); - if(haveMultipleOutputPairs) - { - makecmd += " cmake_check_multiple_outputs"; - } makecmd += " all"; cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ "); buildphase->AddAttribute("shellScript", @@ -1546,8 +1540,7 @@ void cmGlobalXCodeGenerator cmTarget& target, std::vector const & commands, - const std::string& configName, - bool& haveMultipleOutputPairs) + const std::string& configName) { std::string makefileName=makefileBasename; if(this->XcodeVersion > 20) @@ -1570,7 +1563,6 @@ void cmGlobalXCodeGenerator makefileStream << "all: "; std::map tname; int count = 0; - std::map multipleOutputPairs; for(std::vector::const_iterator i = commands.begin(); i != commands.end(); ++i) { @@ -1586,16 +1578,6 @@ void cmGlobalXCodeGenerator makefileStream << "\\\n\t" << this->ConvertToRelativeForMake(o->c_str()); } - - // If there is more than one output treat the first as the - // primary output and make the rest depend on it. - std::vector::const_iterator o = outputs.begin(); - std::string primaryOutput = this->ConvertToRelativeForMake(o->c_str()); - for(++o; o != outputs.end(); ++o) - { - std::string currentOutput=this->ConvertToRelativeForMake(o->c_str()); - multipleOutputPairs[currentOutput] = primaryOutput; - } } else { @@ -1618,9 +1600,15 @@ void cmGlobalXCodeGenerator if(!outputs.empty()) { // There is at least one output, start the rule for it - std::string primary_output = - this->ConvertToRelativeForMake(outputs.begin()->c_str()); - makefileStream << primary_output << ": "; + const char* sep = ""; + for(std::vector::const_iterator oi = outputs.begin(); + oi != outputs.end(); ++oi) + { + makefileStream << sep << + this->ConvertToRelativeForMake(oi->c_str()); + sep = " "; + } + makefileStream << ": "; } else { @@ -1670,33 +1658,6 @@ void cmGlobalXCodeGenerator } } } - - // Add rules to deal with multiple outputs of custom commands. - if(!multipleOutputPairs.empty()) - { - makefileStream << - "\n# Dependencies of multiple outputs to their primary outputs \n"; - - for(std::map::const_iterator o = - multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o) - { - makefileStream << o->first << ": " << o->second << "\n"; - } - - makefileStream << - "\n" - "cmake_check_multiple_outputs:\n"; - for(std::map::const_iterator o = - multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o) - { - makefileStream << "\t@if [ ! -f " - << o->first << " ]; then rm -f " - << o->second << "; fi\n"; - } - } - - haveMultipleOutputPairs = - haveMultipleOutputPairs || !multipleOutputPairs.empty(); } //---------------------------------------------------------------------------- diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index d2bc9d1ea..f38435eb1 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -118,8 +118,7 @@ private: void CreateCustomRulesMakefile(const char* makefileBasename, cmTarget& target, std::vector const & commands, - const std::string& configName, - bool& haveMultipleOutputPairs); + const std::string& configName); cmXCodeObject* FindXCodeTarget(cmTarget const*); std::string GetOrCreateId(const std::string& name, const std::string& id); From 644b4688d71cc52f8499d6103495de0909319557 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 5 Dec 2014 09:55:49 -0500 Subject: [PATCH 2/4] Makefile: Fix rebuild with multiple custom command outputs (#15116) Fix the generated makefiles for custom commands with multiple outputs to list all the outputs on the left hand side of the build rule. This is much simpler and more reliable than the old multiple-output-pair infrastructure. --- Source/cmLocalUnixMakefileGenerator3.cxx | 46 +++++++++- Source/cmLocalUnixMakefileGenerator3.h | 7 ++ Source/cmMakefileLibraryTargetGenerator.cxx | 21 ++--- Source/cmMakefileTargetGenerator.cxx | 93 ++------------------- Source/cmMakefileTargetGenerator.h | 12 --- 5 files changed, 68 insertions(+), 111 deletions(-) diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index ff8ba8be8..56b2b9709 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -618,6 +618,30 @@ cmLocalUnixMakefileGenerator3 comment); return; } + std::vector outputs(1, target); + this->WriteMakeRule(os, comment, + outputs, depends, commands, + symbolic, in_help); +} + +//---------------------------------------------------------------------------- +void +cmLocalUnixMakefileGenerator3 +::WriteMakeRule(std::ostream& os, + const char* comment, + const std::vector& outputs, + const std::vector& depends, + const std::vector& commands, + bool symbolic, + bool in_help) +{ + // Make sure there is an output. + if(outputs.empty()) + { + cmSystemTools::Error("No outputs for WriteMakeRule! called with comment: ", + comment); + return; + } std::string replace; @@ -636,8 +660,18 @@ cmLocalUnixMakefileGenerator3 } // Construct the left hand side of the rule. - replace = target; - std::string tgt = this->Convert(replace,HOME_OUTPUT,MAKERULE); + std::string tgt; + { + const char* sep = ""; + for (std::vector::const_iterator i = outputs.begin(); + i != outputs.end(); ++i) + { + tgt += sep; + tgt += this->Convert(*i,HOME_OUTPUT,MAKERULE); + sep = " "; + } + } + const char* space = ""; if(tgt.size() == 1) { @@ -690,7 +724,11 @@ cmLocalUnixMakefileGenerator3 // Add the output to the local help if requested. if(in_help) { - this->LocalHelp.push_back(target); + for (std::vector::const_iterator i = outputs.begin(); + i != outputs.end(); ++i) + { + this->LocalHelp.push_back(*i); + } } } @@ -1709,6 +1747,8 @@ cmLocalUnixMakefileGenerator3 //---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose) { + // Nothing populates multiple output pairs anymore, but we need to + // honor it when working in a build tree generated by an older CMake. cmMakefile* mf = this->Makefile; // Get the string listing the multiple output pairs. diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 4f2e4a035..65265ce08 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -61,6 +61,13 @@ public: const std::vector& commands, bool symbolic, bool in_help = false); + void WriteMakeRule(std::ostream& os, + const char* comment, + const std::vector& outputs, + const std::vector& depends, + const std::vector& commands, + bool symbolic, + bool in_help = false); // write the main variables used by the makefiles void WriteMakeVariables(std::ostream& makefileStream); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 80473f613..305d81d7b 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -752,26 +752,23 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules this->Target); } - // Write the build rule. - this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, - targetFullPathReal, - depends, commands, false); - - // Some targets have more than one output file. Create rules to - // drive the build if any extra outputs are missing. - std::vector extraOutputs; + // Compute the list of outputs. + std::vector outputs(1, targetFullPathReal); if(targetNameSO != targetNameReal) { - this->GenerateExtraOutput(targetFullPathSO.c_str(), - targetFullPathReal.c_str()); + outputs.push_back(targetFullPathSO); } if(targetName != targetNameSO && targetName != targetNameReal) { - this->GenerateExtraOutput(targetFullPath.c_str(), - targetFullPathReal.c_str()); + outputs.push_back(targetFullPath); } + // Write the build rule. + this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, + outputs, depends, commands, false); + + // Write the main driver rule to build everything in this target. this->WriteTargetDriverRule(targetFullPath, relink); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 8444dfb7a..067714ef9 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -754,30 +754,24 @@ cmMakefileTargetGenerator compileCommands.begin(), compileCommands.end()); } - // Write the rule. - this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, - relativeObj, - depends, commands, false); - // Check for extra outputs created by the compilation. + std::vector outputs(1, relativeObj); if(const char* extra_outputs_str = source.GetProperty("OBJECT_OUTPUTS")) { - std::vector extra_outputs; - cmSystemTools::ExpandListArgument(extra_outputs_str, extra_outputs); - for(std::vector::const_iterator eoi = extra_outputs.begin(); - eoi != extra_outputs.end(); ++eoi) + cmSystemTools::ExpandListArgument(extra_outputs_str, outputs); + for(std::vector::const_iterator eoi = outputs.begin()+1; + eoi != outputs.end(); ++eoi) { - // Register this as an extra output for the object file rule. - // This will cause the object file to be rebuilt if the extra - // output is missing. - this->GenerateExtraOutput(eoi->c_str(), relativeObj.c_str(), false); - // Register this as an extra file to clean. this->CleanFiles.push_back(*eoi); } } + // Write the rule. + this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, + outputs, depends, commands, false); + bool do_preprocess_rules = lang_has_preprocessor && this->LocalGenerator->GetCreatePreprocessedSourceRules(); bool do_assembly_rules = lang_has_assembly && @@ -1017,25 +1011,6 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() this->LocalGenerator-> WriteDependLanguageInfo(*this->InfoFileStream,*this->Target); - // Store multiple output pairs in the depend info file. - if(!this->MultipleOutputPairs.empty()) - { - *this->InfoFileStream - << "\n" - << "# Pairs of files generated by the same build rule.\n" - << "set(CMAKE_MULTIPLE_OUTPUT_PAIRS\n"; - for(MultipleOutputPairsType::const_iterator pi = - this->MultipleOutputPairs.begin(); - pi != this->MultipleOutputPairs.end(); ++pi) - { - *this->InfoFileStream - << " " << this->LocalGenerator->EscapeForCMake(pi->first) - << " " << this->LocalGenerator->EscapeForCMake(pi->second) - << "\n"; - } - *this->InfoFileStream << " )\n\n"; - } - // Store list of targets linked directly or transitively. { *this->InfoFileStream @@ -1273,7 +1248,7 @@ void cmMakefileTargetGenerator } } this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, - *o, depends, commands, + outputs, depends, commands, symbolic); // If the rule has changed make sure the output is rebuilt. @@ -1283,21 +1258,6 @@ void cmMakefileTargetGenerator } } - // Write rules to drive building any outputs beyond the first. - const char* in = o->c_str(); - for(++o; o != outputs.end(); ++o) - { - bool symbolic = false; - if(need_symbolic) - { - if(cmSourceFile* sf = this->Makefile->GetSource(*o)) - { - symbolic = sf->GetPropertyAsBool("SYMBOLIC"); - } - } - this->GenerateExtraOutput(o->c_str(), in, symbolic); - } - // Setup implicit dependency scanning. for(cmCustomCommand::ImplicitDependsList::const_iterator idi = ccg.GetCC().GetImplicitDepends().begin(); @@ -1314,32 +1274,6 @@ void cmMakefileTargetGenerator } } -//---------------------------------------------------------------------------- -void -cmMakefileTargetGenerator -::GenerateExtraOutput(const char* out, const char* in, bool symbolic) -{ - // Add a rule to build the primary output if the extra output needs - // to be created. - std::vector commands; - std::vector depends; - std::string emptyCommand = this->GlobalGenerator->GetEmptyRuleHackCommand(); - if(!emptyCommand.empty()) - { - commands.push_back(emptyCommand); - } - depends.push_back(in); - this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, - out, depends, commands, - symbolic); - - // Register the extra output as paired with the first output so that - // the check-build-system step will remove the primary output if any - // extra outputs are missing. This forces the rule to regenerate - // all outputs. - this->AddMultipleOutputPair(out, in); -} - //---------------------------------------------------------------------------- void cmMakefileTargetGenerator::AppendProgress(std::vector& commands) @@ -1767,15 +1701,6 @@ void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar, } } -//---------------------------------------------------------------------------- -void -cmMakefileTargetGenerator -::AddMultipleOutputPair(const char* depender, const char* dependee) -{ - MultipleOutputPairsType::value_type p(depender, dependee); - this->MultipleOutputPairs.insert(p); -} - //---------------------------------------------------------------------------- void cmMakefileTargetGenerator diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 9fac5746f..e31e0863a 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -142,15 +142,6 @@ protected: // Lookup the link rule for this target. std::string GetLinkRule(const std::string& linkRuleVar); - /** In order to support parallel builds for custom commands with - multiple outputs the outputs are given a serial order, and only - the first output actually has the build rule. Other outputs - just depend on the first one. The check-build-system step must - remove a dependee if the depender is missing to make sure both - are regenerated properly. This method is used by the local - makefile generators to register such pairs. */ - void AddMultipleOutputPair(const char* depender, const char* dependee); - /** Create a script to hold link rules and a command to invoke the script at build time. */ void CreateLinkScript(const char* name, @@ -231,9 +222,6 @@ protected: // Set of extra output files to be driven by the build. std::set ExtraFiles; - typedef std::map MultipleOutputPairsType; - MultipleOutputPairsType MultipleOutputPairs; - // Target name info. std::string TargetNameOut; std::string TargetNameSO; From 65ea5eb721d820551653bf6471e83ed5f4a5ba13 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 5 Dec 2014 09:56:26 -0500 Subject: [PATCH 3/4] Tests: Cover rebuild with multiple custom command outputs (#15116) Extend the BuildDepends test with a case covering multiple custom command outputs with the second one consumed by another rule. With the old "multiple output pair" infrastructure used in the Makefile and Xcode generators this did not work. Now that it is fixed, test the case explicitly. --- Tests/BuildDepends/CMakeLists.txt | 28 +++++++++++++++++++++++ Tests/BuildDepends/Project/CMakeLists.txt | 13 +++++++++++ 2 files changed, 41 insertions(+) diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt index 6209bb8fa..78e9e1738 100644 --- a/Tests/BuildDepends/CMakeLists.txt +++ b/Tests/BuildDepends/CMakeLists.txt @@ -65,6 +65,7 @@ file(WRITE ${BuildDepends_BINARY_DIR}/Project/link_depends_no_shared_exe.h set(link_depends_no_shared_check_txt ${BuildDepends_BINARY_DIR}/Project/link_depends_no_shared_check.txt) file(WRITE ${BuildDepends_BINARY_DIR}/Project/external.in "external original\n") +file(WRITE ${BuildDepends_BINARY_DIR}/Project/multi1-in.txt "multi1-in original\n") help_xcode_depends() @@ -177,6 +178,19 @@ else() "external.out is missing") endif() +if(EXISTS ${BuildDepends_BINARY_DIR}/Project/multi1-out2-copy.txt) + file(STRINGS ${BuildDepends_BINARY_DIR}/Project/multi1-out2-copy.txt multi1_out) + if("${multi1_out}" STREQUAL "multi1-in original") + message(STATUS "multi1-out2-copy.txt contains '${multi1_out}'") + else() + message(SEND_ERROR "Project did not initially build properly: " + "multi1-out2-copy.txt contains '${multi1_out}'") + endif() +else() + message(SEND_ERROR "Project did not initially build properly: " + "multi1-out2-copy.txt is missing") +endif() + message("Waiting 3 seconds...") execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 3) @@ -202,6 +216,7 @@ if(TEST_LINK_DEPENDS) endif() file(WRITE ${BuildDepends_BINARY_DIR}/Project/external.in "external changed\n") +file(WRITE ${BuildDepends_BINARY_DIR}/Project/multi1-in.txt "multi1-in changed\n") help_xcode_depends() @@ -319,3 +334,16 @@ else() message(SEND_ERROR "Project did not rebuild properly: " "external.out is missing") endif() + +if(EXISTS ${BuildDepends_BINARY_DIR}/Project/multi1-out2-copy.txt) + file(STRINGS ${BuildDepends_BINARY_DIR}/Project/multi1-out2-copy.txt multi1_out) + if("${multi1_out}" STREQUAL "multi1-in changed") + message(STATUS "multi1-out2-copy.txt contains '${multi1_out}'") + else() + message(SEND_ERROR "Project did not rebuild properly: " + "multi1-out2-copy.txt contains '${multi1_out}'") + endif() +else() + message(SEND_ERROR "Project did not rebuild properly: " + "multi1-out2-copy.txt is missing") +endif() diff --git a/Tests/BuildDepends/Project/CMakeLists.txt b/Tests/BuildDepends/Project/CMakeLists.txt index 9ee4a43aa..cb9fbf8cf 100644 --- a/Tests/BuildDepends/Project/CMakeLists.txt +++ b/Tests/BuildDepends/Project/CMakeLists.txt @@ -151,3 +151,16 @@ ExternalProject_Add(ExternalBuild -Dexternal_out=${CMAKE_CURRENT_BINARY_DIR}/external.out INSTALL_COMMAND "" ) + +add_custom_command( + OUTPUT multi1-out1.txt multi1-out2.txt + COMMAND ${CMAKE_COMMAND} -E copy multi1-in.txt multi1-out1.txt + COMMAND ${CMAKE_COMMAND} -E copy multi1-in.txt multi1-out2.txt + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/multi1-in.txt + ) +add_custom_command( + OUTPUT multi1-out2-copy.txt + COMMAND ${CMAKE_COMMAND} -E copy multi1-out2.txt multi1-out2-copy.txt + DEPENDS multi1-out2.txt + ) +add_custom_target(multi1 ALL DEPENDS multi1-out2-copy.txt) From 6c67b8168cd44e5900982ca3e36049792934d83d Mon Sep 17 00:00:00 2001 From: Brad King Date: Sat, 6 Dec 2014 07:36:52 -0500 Subject: [PATCH 4/4] Makefile: Workaround Borland Make bug with multiple outputs Given a rule of the form out1 out2: dep1 out1 out2: dep2 Borland Make complains that there are multiple rules for "out1" even though this works when there is only one output. Instead generate out1 out2: dep1 dep2 for Borland Make, but only when there are multiple outputs. --- Source/cmGlobalBorlandMakefileGenerator.cxx | 1 + Source/cmLocalUnixMakefileGenerator3.cxx | 14 ++++++++++++++ Source/cmLocalUnixMakefileGenerator3.h | 4 ++++ 3 files changed, 19 insertions(+) diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx index 6c209522d..950d44009 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.cxx +++ b/Source/cmGlobalBorlandMakefileGenerator.cxx @@ -49,6 +49,7 @@ cmLocalGenerator *cmGlobalBorlandMakefileGenerator::CreateLocalGenerator() lg->SetUnixCD(false); lg->SetMakeCommandEscapeTargetTwice(true); lg->SetBorlandMakeCurlyHack(true); + lg->SetNoMultiOutputMultiDepRules(true); return lg; } diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 56b2b9709..812ded32d 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -92,6 +92,7 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3() this->SkipAssemblySourceRules = false; this->MakeCommandEscapeTargetTwice = false; this->BorlandMakeCurlyHack = false; + this->NoMultiOutputMultiDepRules = false; } //---------------------------------------------------------------------------- @@ -696,6 +697,19 @@ cmLocalUnixMakefileGenerator3 // No dependencies. The commands will always run. os << cmMakeSafe(tgt) << space << ":\n"; } + else if(this->NoMultiOutputMultiDepRules && outputs.size() >= 2) + { + // Borland make does not understand multiple dependency rules when + // there are multiple outputs, so write them all on one line. + os << cmMakeSafe(tgt) << space << ":"; + for(std::vector::const_iterator dep = depends.begin(); + dep != depends.end(); ++dep) + { + replace = this->Convert(*dep, HOME_OUTPUT, MAKERULE); + os << " " << cmMakeSafe(replace); + } + os << "\n"; + } else { // Split dependencies into multiple rule lines. This allows for diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 65265ce08..7c8e27f49 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -161,6 +161,9 @@ public: void SetBorlandMakeCurlyHack(bool b) { this->BorlandMakeCurlyHack = b; } + void SetNoMultiOutputMultiDepRules(bool b) + { this->NoMultiOutputMultiDepRules = b; } + // used in writing out Cmake files such as WriteDirectoryInformation static void WriteCMakeArgument(std::ostream& os, const char* s); @@ -345,6 +348,7 @@ private: bool PassMakeflags; bool MakeCommandEscapeTargetTwice; bool BorlandMakeCurlyHack; + bool NoMultiOutputMultiDepRules; //========================================================================== std::string HomeRelativeOutputPath;