Przeglądaj źródła

ENH: fix parens in the path with spaces in the path

Bill Hoffman 18 lat temu
rodzic
commit
5647e6e254

+ 18 - 5
Source/CMakeLists.txt

@@ -1011,12 +1011,24 @@ IF(BUILD_TESTING)
       --test-command  testIOS
       )
   ENDIF(NOT CMAKE_TEST_DIFFERENT_GENERATOR)
-
+  SET(MAKE_IS_GNU )
+  IF(${CMAKE_TEST_MAKEPROGRAM} MATCHES make)
+    EXECUTE_PROCESS(COMMAND ${CMAKE_TEST_MAKEPROGRAM} --version
+      RESULT_VARIABLE res OUTPUT_VARIABLE out
+      ERROR_QUIET
+      OUTPUT_QUIET)
+    IF("${res}" EQUAL 0)
+      IF("${out}" MATCHES "GNU")
+        SET(MAKE_IS_GNU 1)
+      ENDIF("${out}" MATCHES "GNU")
+    ENDIF("${res}" EQUAL 0)
+  ENDIF(${CMAKE_TEST_MAKEPROGRAM} MATCHES make)
 
   # only add this test on platforms that support it
   # some old versions of make simply cannot handle spaces in paths
-  IF ("${CMAKE_TEST_MAKEPROGRAM}" MATCHES "nmake|gmake|wmake" OR
-      "${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio|Xcode")
+  IF (MAKE_IS_GNU OR 
+      "${CMAKE_TEST_MAKEPROGRAM}" MATCHES "nmake|gmake|wmake" OR
+      "${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio|XCode")
     ADD_TEST(SubDirSpaces ${CMAKE_CTEST_COMMAND}
       --build-and-test
       "${CMake_SOURCE_DIR}/Tests/SubDirSpaces"
@@ -1030,8 +1042,9 @@ IF(BUILD_TESTING)
       "${CMake_BINARY_DIR}/Tests/SubDirSpaces/ShouldBeHere"
       "${CMake_BINARY_DIR}/Tests/SubDirSpaces/testfromsubdir.obj"
       )
-  ENDIF ("${CMAKE_TEST_MAKEPROGRAM}" MATCHES "nmake|gmake|wmake" OR
-    "${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio|Xcode")
+  ENDIF (MAKE_IS_GNU OR
+    "${CMAKE_TEST_MAKEPROGRAM}" MATCHES "nmake|gmake|wmake" OR
+    "${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio|XCode")
 
   IF (WIN32)
     ADD_TEST(SubDir ${CMAKE_CTEST_COMMAND}

+ 9 - 1
Source/cmLocalGenerator.cxx

@@ -1023,7 +1023,7 @@ cmLocalGenerator::ConvertToOutputForExisting(const char* p)
       {
       if(!cmSystemTools::GetShortPath(ret.c_str(), ret))
         {
-        ret = this->Convert(p,START_OUTPUT,MAKEFILE,true);
+        ret = this->Convert(p,START_OUTPUT,SHELL,true);
         }
       }
     }
@@ -2088,6 +2088,14 @@ std::string cmLocalGenerator::Convert(const char* source,
         result[0] = '/';
         }
       }
+    // if this is unix then we need to escape () in the shell
+#if !defined(WIN32) || defined(CYGWIN)
+    forceOn = true;
+#endif
+    if(forceOn )
+      {
+      result = cmSystemTools::EscapeForUnixShell(result);
+      }
     }
   return result;
 }

+ 2 - 2
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -1743,7 +1743,7 @@ cmLocalUnixMakefileGenerator3
   // Call make on the given file.
   std::string cmd;
   cmd += "$(MAKE) -f ";
-  cmd += this->Convert(makefile,NONE,MAKEFILE);
+  cmd += this->Convert(makefile,NONE,SHELL);
   cmd += " ";
   
   // Passg down verbosity level.
@@ -1765,7 +1765,7 @@ cmLocalUnixMakefileGenerator3
   // Add the target.
   if (tgt && tgt[0] != '\0')
     {
-    std::string tgt2 = this->Convert(tgt,HOME_OUTPUT,MAKEFILE);
+    std::string tgt2 = this->Convert(tgt,HOME_OUTPUT,SHELL);
     tgt2 = this->ConvertToMakeTarget(tgt2.c_str());
     cmd += tgt2;
     }

+ 58 - 0
Source/cmSystemTools.cxx

@@ -1341,6 +1341,64 @@ std::string cmSystemTools::ConvertToOutputPath(const char* path)
 #endif
 }
 
+std::string cmSystemTools::EscapeForUnixShell(std::string& result)
+{
+  // For UNIX Shell paths we need to escape () in the path
+  if(result.find_first_of("()") != result.npos)
+    {
+    std::string newResult = "";
+    char lastch = 1;
+    bool inDollarVariable = false;
+    for(const char* ch = result.c_str(); *ch != '\0'; ++ch)
+      {
+      // if it is already escaped then don't try to escape it again
+      if((*ch == ' ' || *ch == '(' || *ch == ')') && lastch != '\\')
+        {
+        if(*ch == '(' && lastch == '$')
+          {
+          inDollarVariable = true;
+          }
+        // if we are in a $(..... and we get a ) then do not escape
+        // the ) and but set inDollarVariable to false
+        else if(*ch == ')' && inDollarVariable)
+          {
+          inDollarVariable = false;
+          }
+        else
+          {
+          newResult += '\\';
+          }
+        }
+      newResult += *ch;
+      lastch = *ch;
+      }
+    return newResult;
+    }
+  return result;
+}
+
+std::string cmSystemTools::ConvertToShellPath(const char* path)
+{
+  bool useUnix = false; // assume windows
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  // if windows and force paths but not cygwin useUnix is on
+  if(s_ForceUnixPaths)
+    {
+    useUnix = true;
+    }
+#else
+  // if not win32 and maybe cygwin then unix is true
+  useUnix = true;
+#endif
+  // if unix we need to call EscapeForUnixShell as well
+  if(useUnix)
+    {
+    std::string result = cmSystemTools::ConvertToUnixOutputPath(path);
+    return cmSystemTools::EscapeForUnixShell(result);
+    }
+  return cmSystemTools::ConvertToWindowsOutputPath(path);
+}
+
 std::string cmSystemTools::ConvertToRunCommandPath(const char* path)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)

+ 4 - 2
Source/cmSystemTools.h

@@ -293,10 +293,12 @@ public:
   // be used when RunCommand is called from cmake, because the 
   // running cmake needs paths to be in its format
   static std::string ConvertToRunCommandPath(const char* path);
-
+  // convert to a shell path
+  static std::string ConvertToShellPath(const char* path);
   //! Check if the first string ends with the second one.
   static bool StringEndsWith(const char* str1, const char* str2);
-
+  // escape for unix shells
+  static std::string EscapeForUnixShell(std::string& result);
   static bool CreateSymlink(const char* origName, const char* newName);
   
   /** compute the relative path from local to remote.  local must 

+ 3 - 16
Source/kwsys/SystemTools.cxx

@@ -1414,7 +1414,7 @@ kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path)
     ret.erase(pos, 1);
     }
   // escape spaces and () in the path
-  if(ret.find_first_of(" ()") != kwsys_stl::string::npos)
+  if(ret.find_first_of(" ") != kwsys_stl::string::npos)
     {
     kwsys_stl::string result = "";
     char lastch = 1;
@@ -1422,22 +1422,9 @@ kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path)
     for(const char* ch = ret.c_str(); *ch != '\0'; ++ch)
       {
         // if it is already escaped then don't try to escape it again
-      if((*ch == ' ' || *ch == '(' || *ch == ')') && lastch != '\\')
+      if((*ch == ' ') && lastch != '\\')
         {
-        if(*ch == '(' && lastch == '$')
-          {
-          inDollarVariable = true;
-          }
-        // if we are in a $(..... and we get a ) then do not escape
-        // the ) and but set inDollarVariable to false
-        else if(*ch == ')' && inDollarVariable)
-          {
-          inDollarVariable = false;
-          }
-        else
-          {
-          result += '\\';
-          }
+        result += '\\';
         }
       result += *ch;
       lastch = *ch;

+ 3 - 1
Tests/SubDirSpaces/CMakeLists.txt

@@ -1,5 +1,5 @@
 PROJECT(SUBDIR)
-SUBDIRS("Executable Sources" EXCLUDE_FROM_ALL "Some Examples")
+SUBDIRS("Executable Sources" "Some(x86) Sources" EXCLUDE_FROM_ALL "Some Examples")
 WRITE_FILE(${SUBDIR_BINARY_DIR}/ShouldBeHere "This file should exist.")
 #WATCOM WMAKE does not support + in the name of a file!
 IF(WATCOM)
@@ -41,3 +41,5 @@ ELSE(WATCOM)
     vcl_algorithm+vcl_pair+double.foo.c)
 ENDIF(WATCOM)  
 ADD_EXECUTABLE(TestWithAuxSourceDir ${SOURCES})
+target_link_libraries(TestWithAuxSourceDir testOddPath)
+

+ 1 - 0
Tests/SubDirSpaces/Some(x86) Sources/CMakeLists.txt

@@ -0,0 +1 @@
+add_library(testOddPath test.c)

+ 3 - 0
Tests/SubDirSpaces/Some(x86) Sources/test.c

@@ -0,0 +1,3 @@
+void testOdd()
+{
+}

+ 2 - 1
Tests/SubDirSpaces/ThirdSubDir/testfromauxsubdir.c

@@ -4,11 +4,12 @@ void secondone();
 void pair_stuff();
 void pair_p_stuff();
 void vcl_stuff();
-
+void testOdd();
 int main()
 {
   printf("Hello from subdirectory\n");
   secondone();
+  testOdd();
   pair_stuff();
   pair_p_stuff();
   vcl_stuff();