diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx index 1f44c73e8..959cbe863 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.cxx +++ b/Source/cmGlobalBorlandMakefileGenerator.cxx @@ -51,6 +51,7 @@ cmLocalGenerator *cmGlobalBorlandMakefileGenerator::CreateLocalGenerator() lg->SetGlobalGenerator(this); lg->SetUnixCD(false); lg->SetMakeCommandEscapeTargetTwice(true); + lg->SetBorlandMakeCurlyHack(true); return lg; } diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx index 30cb9483b..89a01d800 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.cxx +++ b/Source/cmGlobalMinGWMakefileGenerator.cxx @@ -61,6 +61,7 @@ cmLocalGenerator *cmGlobalMinGWMakefileGenerator::CreateLocalGenerator() lg->SetIgnoreLibPrefix(true); lg->SetPassMakeflags(false); lg->SetUnixCD(true); + lg->SetMinGWMake(true); // mingw32-make has trouble running code like // diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 90fcb7bbc..c7c727bbb 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -47,6 +47,7 @@ cmLocalGenerator::cmLocalGenerator() this->WindowsShell = false; this->WindowsVSIDE = false; this->WatcomWMake = false; + this->MinGWMake = false; this->MSYSShell = false; this->IgnoreLibPrefix = false; this->UseRelativePaths = false; @@ -2772,6 +2773,10 @@ std::string cmLocalGenerator::EscapeForShell(const char* str, bool makeVars, { flags |= cmsysSystem_Shell_Flag_WatcomWMake; } + if(this->MinGWMake) + { + flags |= cmsysSystem_Shell_Flag_MinGWMake; + } // Compute the buffer size needed. int size = (this->WindowsShell ? diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 38b4c0b4d..f767a692c 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -304,6 +304,7 @@ protected: bool WindowsShell; bool WindowsVSIDE; bool WatcomWMake; + bool MinGWMake; bool ForceUnixPath; bool MSYSShell; bool UseRelativePaths; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 3d893662c..425997bc9 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -55,6 +55,7 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3() this->NativeEchoWindows = true; this->MakeCommandEscapeTargetTwice = false; this->IsMakefileGenerator = true; + this->BorlandMakeCurlyHack = false; } //---------------------------------------------------------------------------- @@ -939,6 +940,27 @@ cmLocalUnixMakefileGenerator3 escapeAllowMakeVars); } } + if(this->BorlandMakeCurlyHack) + { + // Borland Make has a very strange bug. If the first curly + // brace anywhere in the command string is a left curly, it + // must be written {{} instead of just {. Otherwise some + // curly braces are removed. The hack can be skipped if the + // first curly brace is the last character. + std::string::size_type lcurly = cmd.find("{"); + if(lcurly != cmd.npos && lcurly < (cmd.size()-1)) + { + std::string::size_type rcurly = cmd.find("}"); + if(rcurly == cmd.npos || rcurly > lcurly) + { + // The first curly is a left curly. Use the hack. + std::string hack_cmd = cmd.substr(0, lcurly); + hack_cmd += "{{}"; + hack_cmd += cmd.substr(lcurly+1); + cmd = hack_cmd; + } + } + } commands1.push_back(cmd); } } diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 07d1f953e..4eeadd6e4 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -97,6 +97,11 @@ public: */ void SetWatcomWMake(bool v) {this->WatcomWMake = v;} + /** + * Set to true if the make tool being used is MinGW Make. + */ + void SetMinGWMake(bool v) {this->MinGWMake = v;} + /** * Set to true if the shell being used is the MSYS shell. * This controls if statements in the makefile and the SHELL variable. @@ -165,6 +170,13 @@ public: void SetMakeCommandEscapeTargetTwice(bool b) { this->MakeCommandEscapeTargetTwice = b; } + /** + * Set whether the Borland curly brace command line hack should be + * applied. + */ + void SetBorlandMakeCurlyHack(bool b) + { this->BorlandMakeCurlyHack = b; } + // used in writing out Cmake files such as WriteDirectoryInformation static void WriteCMakeArgument(std::ostream& os, const char* s); @@ -338,6 +350,7 @@ private: bool PassMakeflags; bool SilentNoColon; bool MakeCommandEscapeTargetTwice; + bool BorlandMakeCurlyHack; //========================================================================== std::string HomeRelativeOutputPath; diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt index fb7b714e7..a0dc01264 100644 --- a/Tests/CustomCommand/CMakeLists.txt +++ b/Tests/CustomCommand/CMakeLists.txt @@ -195,6 +195,7 @@ ADD_SUBDIRECTORY(GeneratorInExtraDir) ############################################################################## # Test non-trivial command line arguments in custom commands. SET(EXPECTED_ARGUMENTS) +# TODO: Check shell operators < > << >> | 2>&1 1>&2 &> ! & SET(CHECK_ARGS c:/posix/path c:\\windows\\path @@ -209,12 +210,43 @@ SET(CHECK_ARGS "(parens)" "(lparen" "rparen)" + {curly} + {lcurly} + rcurly} + + + [square] + [lsquare # these have funny behavior due to special cases for + rsquare] # windows registry value names in list expansion $dollar-signs$ dollar$sign &ersands& - amper&sand + one&ersand @two-ats@ one@at + ~two-tilda~ + one~tilda + ^two-carrots^ + one^carrot + %two-percents% + one%percent + !two-exclamations! + one!exclamation + ?two-questions? + one?question + *two-stars* + one*star + =two+equals= + one=equals + _two-underscores_ + one_underscore + ,two-commas, + one,comma + .two-periods. + one.period + |two-pipes| + one|pipe "#two-pounds#" "one#pound" "c:/posix/path/with space" @@ -230,14 +262,49 @@ SET(CHECK_ARGS "(parens) with space" "(lparen with space" "rparen) with space" + "{curly} with space" + "{lcurly with space" + "rcurly} with space" + " with space" + " with space" + "[square] with space" + "[lsquare with space" # these have funny behavior due to special cases for + "rsquare] with space" # windows registry value names in list expansion "$dollar-signs$ with space" "dollar$sign with space" "&ersands& with space" - "amper&sand with space" + "one&ersand with space" "@two-ats@ with space" "one@at with space" + "~two-tilda~ with space" + "one~tilda with space" + "^two-carrots^ with space" + "one^carrot with space" + "%two-percents% with space" + "one%percent with space" + "!two-exclamations! with space" + "one!exclamation with space" + "*two-stars* with space" + "one*star with space" + "=two+equals= with space" + "one=equals with space" + "_two-underscores_ with space" + "one_underscore with space" + "?two-questions? with space" + "one?question with space" + ",two-commas, with space" + "one,comma with space" + ".two-periods. with space" + "one.period with space" + "|two-pipes| with space" + "one|pipe with space" "#two-pounds# with space" "one#pound with space" +# ~ ` ! @ \# $ % ^ & * _ - + = | : \" ' < > , . ? / +# "(" ")" { } [] +# >> << &> 2>&1 1>&2 +# \\ \\; ) FOREACH(arg ${CHECK_ARGS}) SET(ARG "${arg}")