From 662756036e4f4983b00ab7740773a55bef808c64 Mon Sep 17 00:00:00 2001 From: David Cole Date: Tue, 25 Jan 2011 18:54:36 -0500 Subject: [PATCH 1/4] VS10: Escape double quote chars in defines for rc files (#11695) To get rc defines to work in the VS10 IDE requires \" when constructing PreprocessorDefinitions strings. This is different than defines for cl. Also, per-file rc defines were not being generated. Fix that, too. --- Source/cmLocalVisualStudio7Generator.cxx | 8 +++++--- Source/cmVisualStudio10TargetGenerator.cxx | 11 +++++++---- Source/cmVisualStudioGeneratorOptions.cxx | 8 +++++++- Source/cmVisualStudioGeneratorOptions.h | 3 ++- Tests/VSResource/CMakeLists.txt | 10 ++++++++-- Tests/VSResource/test.rc | 7 ++++++- 6 files changed, 35 insertions(+), 12 deletions(-) diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 21f6460b2..7d361532b 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -755,7 +755,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, } fout << "\"\n"; targetOptions.OutputFlagMap(fout, "\t\t\t\t"); - targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n"); + targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", "CXX"); fout << "\t\t\t\tAssemblerListingLocation=\"" << configName << "\"\n"; fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n"; if(targetBuilds) @@ -789,7 +789,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, } // add the -D flags to the RC tool fout << "\""; - targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", ""); + targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "", "RC"); fout << "/>\n"; tool = "VCMIDLTool"; if(this->FortranProject) @@ -1462,6 +1462,7 @@ void cmLocalVisualStudio7Generator else if(!fcinfo.FileConfigMap.empty()) { const char* aCompilerTool = "VCCLCompilerTool"; + const char* lang = "CXX"; if(this->FortranProject) { aCompilerTool = "VFFortranCompilerTool"; @@ -1479,6 +1480,7 @@ void cmLocalVisualStudio7Generator if(ext == "rc") { aCompilerTool = "VCResourceCompilerTool"; + lang = "RC"; if(this->FortranProject) { aCompilerTool = "VFResourceCompilerTool"; @@ -1520,7 +1522,7 @@ void cmLocalVisualStudio7Generator fileOptions.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n"); fileOptions.OutputFlagMap(fout, "\t\t\t\t\t"); fileOptions.OutputPreprocessorDefinitions(fout, - "\t\t\t\t\t", "\n"); + "\t\t\t\t\t", "\n", lang); } if(!fc.AdditionalDeps.empty()) { diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 2d55e1e52..4cb745e7e 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -717,6 +717,10 @@ void cmVisualStudio10TargetGenerator::WriteCLSources() // is ended on a new line this->WriteString("\n", 2); } + else if(!header && rc && this->OutputSourceSpecificFlags(*source)) + { + this->WriteString("\n", 2); + } else { (*this->BuildFileStream ) << " />\n"; @@ -853,8 +857,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); clOptions.OutputFlagMap(*this->BuildFileStream, " "); clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, - " ", "\n"); - + " ", "\n", lang); } } return hasFlags; @@ -1120,7 +1123,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( } clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", - "\n"); + "\n", "CXX"); this->WriteString("", 3); *this->BuildFileStream << configName << "\n"; @@ -1155,7 +1158,7 @@ WriteRCOptions(std::string const& configName, this->WriteString("\n", 2); Options& clOptions = *(this->ClOptions[configName]); clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", - "\n"); + "\n", "RC"); this->OutputIncludes(includes); this->WriteString("\n", 2); } diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 9acae0dae..ed0d60ced 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -204,7 +204,8 @@ void cmVisualStudioGeneratorOptions ::OutputPreprocessorDefinitions(std::ostream& fout, const char* prefix, - const char* suffix) + const char* suffix, + const char* lang) { if(this->Defines.empty()) { @@ -251,6 +252,11 @@ cmVisualStudioGeneratorOptions if(this->Version == 10) { define = cmVisualStudio10GeneratorOptionsEscapeForXML(define.c_str()); + + if(0 == strcmp(lang, "RC")) + { + cmSystemTools::ReplaceString(define, "\"", "\\\""); + } } else { diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index 8619ba0b2..fadc4b5e1 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -54,7 +54,8 @@ public: // Write options to output. void OutputPreprocessorDefinitions(std::ostream& fout, const char* prefix, - const char* suffix); + const char* suffix, + const char* lang); void OutputFlagMap(std::ostream& fout, const char* indent); void OutputAdditionalOptions(std::ostream& fout, const char* prefix, diff --git a/Tests/VSResource/CMakeLists.txt b/Tests/VSResource/CMakeLists.txt index e84295554..8c14f8db2 100644 --- a/Tests/VSResource/CMakeLists.txt +++ b/Tests/VSResource/CMakeLists.txt @@ -1,7 +1,13 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required(VERSION 2.8.3.20110118) project (VSResource) -add_definitions(/DCMAKE_RCDEFINE="test.txt") + string(REPLACE "/INCREMENTAL:YES" "" CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test.txt + "${CMAKE_CURRENT_BINARY_DIR}/test with spaces.txt" COPYONLY) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +add_definitions(/DCMAKE_RCDEFINE="test with spaces.txt") + add_executable(VSResource main.cpp test.rc) diff --git a/Tests/VSResource/test.rc b/Tests/VSResource/test.rc index 8aab8b7b8..2e87a6840 100644 --- a/Tests/VSResource/test.rc +++ b/Tests/VSResource/test.rc @@ -1,5 +1,10 @@ #ifdef CMAKE_RCDEFINE hello TEXT DISCARDABLE CMAKE_RCDEFINE + +STRINGTABLE +BEGIN + 1 CMAKE_RCDEFINE +END #else #error "resource compiler did not get defines from command line!" -#endif \ No newline at end of file +#endif From 78fe97f2ff4dbe66590ee79a342ac01a5566ef31 Mon Sep 17 00:00:00 2001 From: David Cole Date: Wed, 26 Jan 2011 08:25:25 -0500 Subject: [PATCH 2/4] Fix line too long KWStyle issue (#11695) --- Source/cmLocalVisualStudio7Generator.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 7d361532b..d880acec6 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1522,7 +1522,8 @@ void cmLocalVisualStudio7Generator fileOptions.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n"); fileOptions.OutputFlagMap(fout, "\t\t\t\t\t"); fileOptions.OutputPreprocessorDefinitions(fout, - "\t\t\t\t\t", "\n", lang); + "\t\t\t\t\t", "\n", + lang); } if(!fc.AdditionalDeps.empty()) { From 8f9919d93cad64de58775e4a7609b0ffb37d061e Mon Sep 17 00:00:00 2001 From: David Cole Date: Wed, 26 Jan 2011 08:26:31 -0500 Subject: [PATCH 3/4] Avoid space in rc /D values for VS6 and Cygwin (#11695) Change to the test only. Using a space in an rc /D value will not work at present with VS6 or Cygwin rc compilers. --- Tests/VSResource/CMakeLists.txt | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Tests/VSResource/CMakeLists.txt b/Tests/VSResource/CMakeLists.txt index 8c14f8db2..5fbd572b7 100644 --- a/Tests/VSResource/CMakeLists.txt +++ b/Tests/VSResource/CMakeLists.txt @@ -1,13 +1,18 @@ cmake_minimum_required(VERSION 2.8.3.20110118) -project (VSResource) +project(VSResource) string(REPLACE "/INCREMENTAL:YES" "" CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test.txt - "${CMAKE_CURRENT_BINARY_DIR}/test with spaces.txt" COPYONLY) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) -add_definitions(/DCMAKE_RCDEFINE="test with spaces.txt") +if(MSVC60 OR CYGWIN) + # VS6 and Cygwin rc compilers do not deal well with spaces in a "/D" value + add_definitions(/DCMAKE_RCDEFINE="test.txt") +else() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test.txt + "${CMAKE_CURRENT_BINARY_DIR}/test with spaces.txt" COPYONLY) + include_directories(${CMAKE_CURRENT_BINARY_DIR}) + add_definitions(/DCMAKE_RCDEFINE="test with spaces.txt") +endif() add_executable(VSResource main.cpp test.rc) From 008d116b1767cb93c043e399ab607bcc8db5c175 Mon Sep 17 00:00:00 2001 From: David Cole Date: Thu, 27 Jan 2011 15:45:25 -0500 Subject: [PATCH 4/4] VSResource: Avoid windres /D with quoted spaces (#11695) Improve test: print out what's happening along the way. --- Tests/VSResource/CMakeLists.txt | 25 ++++++++-- Tests/VSResource/main.cpp | 84 ++++++++++++++++++++++++++++++--- Tests/VSResource/test.rc | 11 ++++- Tests/VSResource/test.txt | 2 +- 4 files changed, 109 insertions(+), 13 deletions(-) diff --git a/Tests/VSResource/CMakeLists.txt b/Tests/VSResource/CMakeLists.txt index 5fbd572b7..5d7d14e5e 100644 --- a/Tests/VSResource/CMakeLists.txt +++ b/Tests/VSResource/CMakeLists.txt @@ -5,12 +5,31 @@ string(REPLACE "/INCREMENTAL:YES" "" CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") -if(MSVC60 OR CYGWIN) - # VS6 and Cygwin rc compilers do not deal well with spaces in a "/D" value +message(STATUS "CMAKE_RC_COMPILER='${CMAKE_RC_COMPILER}'") + +# Because of the following avoidance techniques required for windres and VS6, +# we recommend using a configured header file, and defining preprocessor +# symbols via #define code and including that header in the rc file. Using +# add_definitions is fine for simple definitions (with no spaces and no +# quoting), but requires avoidance or work-arounds beyond that... + +if(CMAKE_RC_COMPILER MATCHES windres) + # windres rc compiler does not properly define quoted /D values as strings + message(STATUS "CMAKE_RC_COMPILER MATCHES windres") + add_definitions(/DCMAKE_RCDEFINE=test.txt) + add_definitions(/DCMAKE_RCDEFINE_NO_QUOTED_STRINGS) +elseif(MSVC60) + # VS6 rc compiler does not deal well with spaces in a "/D" value, but it can + # handle the quoting + message(STATUS "MSVC60") add_definitions(/DCMAKE_RCDEFINE="test.txt") else() + # expected case -- rc compiler is "capable enough" + message(STATUS + "rc compiler handles quoted strings with spaces in values via /D") + set(TEXTFILE_FROM_SOURCE_DIR "textfile, spaces in name, from binary dir") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test.txt - "${CMAKE_CURRENT_BINARY_DIR}/test with spaces.txt" COPYONLY) + "${CMAKE_CURRENT_BINARY_DIR}/test with spaces.txt" @ONLY) include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_definitions(/DCMAKE_RCDEFINE="test with spaces.txt") endif() diff --git a/Tests/VSResource/main.cpp b/Tests/VSResource/main.cpp index 6f68df3eb..7ee0c74fa 100644 --- a/Tests/VSResource/main.cpp +++ b/Tests/VSResource/main.cpp @@ -1,10 +1,80 @@ #include +#include -int main(int argc, char** argv) { - HRSRC hello = ::FindResource(0, "hello", "TEXT"); - if(hello) { - return 0; - } else { - return 1; - } +struct x +{ + const char *txt; +}; + +int main(int argc, char** argv) +{ + int ret = 1; + + fprintf(stdout, "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)\n"); + +#ifdef CMAKE_RCDEFINE + fprintf(stdout, "CMAKE_RCDEFINE defined\n"); +#endif + +#ifdef CMAKE_RCDEFINE_NO_QUOTED_STRINGS + // Expect CMAKE_RCDEFINE to preprocess to exactly test.txt + x test; + test.txt = "*exactly* test.txt"; + fprintf(stdout, "CMAKE_RCDEFINE_NO_QUOTED_STRINGS defined\n"); + fprintf(stdout, "CMAKE_RCDEFINE is %s, and is *not* a string constant\n", + CMAKE_RCDEFINE); +#else + // Expect CMAKE_RCDEFINE to be a string: + fprintf(stdout, "CMAKE_RCDEFINE='%s', and is a string constant\n", + CMAKE_RCDEFINE); +#endif + + HRSRC hello = ::FindResource(NULL, MAKEINTRESOURCE(1025), "TEXTFILE"); + if(hello) + { + fprintf(stdout, "FindResource worked\n"); + HGLOBAL hgbl = ::LoadResource(NULL, hello); + int datasize = (int) ::SizeofResource(NULL, hello); + if(hgbl && datasize>0) + { + fprintf(stdout, "LoadResource worked\n"); + fprintf(stdout, "SizeofResource returned datasize='%d'\n", datasize); + void *data = ::LockResource(hgbl); + if (data) + { + fprintf(stdout, "LockResource worked\n"); + char *str = (char *) malloc(datasize+4); + if (str) + { + memcpy(str, data, datasize); + str[datasize] = 'E'; + str[datasize+1] = 'O'; + str[datasize+2] = 'R'; + str[datasize+3] = 0; + fprintf(stdout, "str='%s'\n", str); + free(str); + + ret = 0; + +#ifdef CMAKE_RCDEFINE_NO_QUOTED_STRINGS + fprintf(stdout, "LoadString skipped\n"); +#else + char buf[256]; + if (::LoadString(NULL, 1026, buf, sizeof(buf)) > 0) + { + fprintf(stdout, "LoadString worked\n"); + fprintf(stdout, "buf='%s'\n", buf); + } + else + { + fprintf(stdout, "LoadString failed\n"); + ret = 1; + } +#endif + } + } + } + } + + return ret; } diff --git a/Tests/VSResource/test.rc b/Tests/VSResource/test.rc index 2e87a6840..4ce4b5312 100644 --- a/Tests/VSResource/test.rc +++ b/Tests/VSResource/test.rc @@ -1,10 +1,17 @@ #ifdef CMAKE_RCDEFINE -hello TEXT DISCARDABLE CMAKE_RCDEFINE +// This line can compile with either an unquoted or a quoted string +1025 TEXTFILE CMAKE_RCDEFINE + +#ifndef CMAKE_RCDEFINE_NO_QUOTED_STRINGS +// This block can only be compiled if CMAKE_RCDEFINE preprocesses +// to a double quoted string STRINGTABLE BEGIN - 1 CMAKE_RCDEFINE + 1026 CMAKE_RCDEFINE END +#endif + #else #error "resource compiler did not get defines from command line!" #endif diff --git a/Tests/VSResource/test.txt b/Tests/VSResource/test.txt index 980a0d5f1..c27c68d1a 100644 --- a/Tests/VSResource/test.txt +++ b/Tests/VSResource/test.txt @@ -1 +1 @@ -Hello World! +Hello World! (@TEXTFILE_FROM_SOURCE_DIR@)