Pārlūkot izejas kodu

Merge topic 'fix-11695-spaces-in-vs10-rc-defs'

008d116 VSResource: Avoid windres /D with quoted spaces (#11695)
8f9919d Avoid space in rc /D values for VS6 and Cygwin (#11695)
78fe97f Fix line too long KWStyle issue (#11695)
6627560 VS10: Escape double quote chars in defines for rc files (#11695)
Brad King 15 gadi atpakaļ
vecāks
revīzija
ecfe0f7ca8

+ 6 - 3
Source/cmLocalVisualStudio7Generator.cxx

@@ -755,7 +755,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
     }
     }
   fout << "\"\n";
   fout << "\"\n";
   targetOptions.OutputFlagMap(fout, "\t\t\t\t");
   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\tAssemblerListingLocation=\"" << configName << "\"\n";
   fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
   fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
   if(targetBuilds)
   if(targetBuilds)
@@ -789,7 +789,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
     }
     }
   // add the -D flags to the RC tool
   // add the -D flags to the RC tool
   fout << "\"";
   fout << "\"";
-  targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "");
+  targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "", "RC");
   fout << "/>\n";
   fout << "/>\n";
   tool = "VCMIDLTool";
   tool = "VCMIDLTool";
   if(this->FortranProject)
   if(this->FortranProject)
@@ -1462,6 +1462,7 @@ void cmLocalVisualStudio7Generator
       else if(!fcinfo.FileConfigMap.empty())
       else if(!fcinfo.FileConfigMap.empty())
         {
         {
         const char* aCompilerTool = "VCCLCompilerTool";
         const char* aCompilerTool = "VCCLCompilerTool";
+        const char* lang = "CXX";
         if(this->FortranProject)
         if(this->FortranProject)
           {
           {
           aCompilerTool = "VFFortranCompilerTool";
           aCompilerTool = "VFFortranCompilerTool";
@@ -1479,6 +1480,7 @@ void cmLocalVisualStudio7Generator
         if(ext == "rc")
         if(ext == "rc")
           {
           {
           aCompilerTool = "VCResourceCompilerTool";  
           aCompilerTool = "VCResourceCompilerTool";  
+          lang = "RC";
           if(this->FortranProject)
           if(this->FortranProject)
             {
             {
             aCompilerTool = "VFResourceCompilerTool";
             aCompilerTool = "VFResourceCompilerTool";
@@ -1520,7 +1522,8 @@ void cmLocalVisualStudio7Generator
             fileOptions.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n");
             fileOptions.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n");
             fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
             fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
             fileOptions.OutputPreprocessorDefinitions(fout,
             fileOptions.OutputPreprocessorDefinitions(fout,
-                                                      "\t\t\t\t\t", "\n");
+                                                      "\t\t\t\t\t", "\n",
+                                                      lang);
             }
             }
           if(!fc.AdditionalDeps.empty())
           if(!fc.AdditionalDeps.empty())
             {
             {

+ 7 - 4
Source/cmVisualStudio10TargetGenerator.cxx

@@ -717,6 +717,10 @@ void cmVisualStudio10TargetGenerator::WriteCLSources()
       // is ended on a new line
       // is ended on a new line
       this->WriteString("</ClCompile>\n", 2);
       this->WriteString("</ClCompile>\n", 2);
       }
       }
+    else if(!header && rc && this->OutputSourceSpecificFlags(*source))
+      {
+      this->WriteString("</ResourceCompile>\n", 2);
+      }
     else
     else
       {
       {
       (*this->BuildFileStream ) << " />\n";
       (*this->BuildFileStream ) << " />\n";
@@ -853,8 +857,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
       clOptions.OutputAdditionalOptions(*this->BuildFileStream, "      ", "");
       clOptions.OutputAdditionalOptions(*this->BuildFileStream, "      ", "");
       clOptions.OutputFlagMap(*this->BuildFileStream, "      "); 
       clOptions.OutputFlagMap(*this->BuildFileStream, "      "); 
       clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream,
       clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream,
-                                              "      ", "\n");
-      
+                                              "      ", "\n", lang);
       }
       }
     }
     }
   return hasFlags;
   return hasFlags;
@@ -1120,7 +1123,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
     }
     }
 
 
   clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ", 
   clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ", 
-                                          "\n");
+                                          "\n", "CXX");
   this->WriteString("<AssemblerListingLocation>", 3);
   this->WriteString("<AssemblerListingLocation>", 3);
   *this->BuildFileStream << configName 
   *this->BuildFileStream << configName 
                          << "</AssemblerListingLocation>\n";
                          << "</AssemblerListingLocation>\n";
@@ -1155,7 +1158,7 @@ WriteRCOptions(std::string const& configName,
   this->WriteString("<ResourceCompile>\n", 2);
   this->WriteString("<ResourceCompile>\n", 2);
   Options& clOptions = *(this->ClOptions[configName]);
   Options& clOptions = *(this->ClOptions[configName]);
   clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
   clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
-                                          "\n");
+                                          "\n", "RC");
   this->OutputIncludes(includes);
   this->OutputIncludes(includes);
   this->WriteString("</ResourceCompile>\n", 2);
   this->WriteString("</ResourceCompile>\n", 2);
 }
 }

+ 7 - 1
Source/cmVisualStudioGeneratorOptions.cxx

@@ -204,7 +204,8 @@ void
 cmVisualStudioGeneratorOptions
 cmVisualStudioGeneratorOptions
 ::OutputPreprocessorDefinitions(std::ostream& fout,
 ::OutputPreprocessorDefinitions(std::ostream& fout,
                                 const char* prefix,
                                 const char* prefix,
-                                const char* suffix)
+                                const char* suffix,
+                                const char* lang)
 {
 {
   if(this->Defines.empty())
   if(this->Defines.empty())
     {
     {
@@ -251,6 +252,11 @@ cmVisualStudioGeneratorOptions
     if(this->Version == 10)
     if(this->Version == 10)
       {
       {
       define = cmVisualStudio10GeneratorOptionsEscapeForXML(define.c_str());
       define = cmVisualStudio10GeneratorOptionsEscapeForXML(define.c_str());
+
+      if(0 == strcmp(lang, "RC"))
+        {
+        cmSystemTools::ReplaceString(define, "\"", "\\\"");
+        }
       }
       }
     else
     else
       {
       {

+ 2 - 1
Source/cmVisualStudioGeneratorOptions.h

@@ -54,7 +54,8 @@ public:
   // Write options to output.
   // Write options to output.
   void OutputPreprocessorDefinitions(std::ostream& fout,
   void OutputPreprocessorDefinitions(std::ostream& fout,
                                      const char* prefix,
                                      const char* prefix,
-                                     const char* suffix);
+                                     const char* suffix,
+                                     const char* lang);
   void OutputFlagMap(std::ostream& fout, const char* indent);
   void OutputFlagMap(std::ostream& fout, const char* indent);
   void OutputAdditionalOptions(std::ostream& fout,
   void OutputAdditionalOptions(std::ostream& fout,
                                const char* prefix,
                                const char* prefix,

+ 33 - 3
Tests/VSResource/CMakeLists.txt

@@ -1,7 +1,37 @@
-cmake_minimum_required (VERSION 2.6)
-project (VSResource)
-add_definitions(/DCMAKE_RCDEFINE="test.txt")
+cmake_minimum_required(VERSION 2.8.3.20110118)
+project(VSResource)
+
 string(REPLACE "/INCREMENTAL:YES" ""
 string(REPLACE "/INCREMENTAL:YES" ""
   CMAKE_EXE_LINKER_FLAGS_DEBUG
   CMAKE_EXE_LINKER_FLAGS_DEBUG
   "${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
   "${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
+
+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" @ONLY)
+  include_directories(${CMAKE_CURRENT_BINARY_DIR})
+  add_definitions(/DCMAKE_RCDEFINE="test with spaces.txt")
+endif()
+
 add_executable(VSResource main.cpp test.rc)
 add_executable(VSResource main.cpp test.rc)

+ 77 - 7
Tests/VSResource/main.cpp

@@ -1,10 +1,80 @@
 #include <windows.h>
 #include <windows.h>
+#include <stdio.h>
 
 
-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;
 }
 }

+ 14 - 2
Tests/VSResource/test.rc

@@ -1,5 +1,17 @@
 #ifdef CMAKE_RCDEFINE
 #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
+  1026 CMAKE_RCDEFINE
+END
+#endif
+
 #else
 #else
 #error "resource compiler did not get defines from command line!"
 #error "resource compiler did not get defines from command line!"
-#endif
+#endif

+ 1 - 1
Tests/VSResource/test.txt

@@ -1 +1 @@
-Hello World!
+Hello World! (@TEXTFILE_FROM_SOURCE_DIR@)