1 /*=========================================================================
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: cmSystemTools.cxx,v $
6 Date: $Date: 2002-07-25 20:41:36 $
7 Version: $Revision: 1.162 $
9 Copyright (c) 2002 Insight Consortium. All rights reserved.
10 See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmSystemTools.h"
21 #include "cmRegularExpression.h"
23 #include "cmDirectory.h"
24 #include "cmMakefile.h"
26 // support for realpath call
30 #include <sys/param.h>
34 #if defined(_MSC_VER) || defined(__BORLANDC__)
38 #define _unlink unlink
39 inline int Mkdir(const char* dir
)
43 inline const char* Getcwd(char* buf
, unsigned int len
)
45 return _getcwd(buf
, len
);
47 inline int Chdir(const char* dir
)
49 #if defined(__BORLANDC__)
56 #include <sys/types.h>
59 inline int Mkdir(const char* dir
)
61 return mkdir(dir
, 00777);
63 inline const char* Getcwd(char* buf
, unsigned int len
)
65 return getcwd(buf
, len
);
67 inline int Chdir(const char* dir
)
73 bool cmSystemTools::s_DisableRunCommandOutput
= false;
74 bool cmSystemTools::s_ErrorOccured
= false;
75 bool cmSystemTools::s_DisableMessages
= false;
77 void (*cmSystemTools::s_ErrorCallback
)(const char*, const char*, bool&);
79 // adds the elements of the env variable path to the arg passed in
80 void cmSystemTools::GetPath(std::vector
<std::string
>& path
)
82 #if defined(_WIN32) && !defined(__CYGWIN__)
83 const char* pathSep
= ";";
85 const char* pathSep
= ":";
87 std::string pathEnv
= getenv("PATH");
88 // A hack to make the below algorithm work.
89 if(pathEnv
[pathEnv
.length()-1] != ':')
93 std::string::size_type start
=0;
97 std::string::size_type endpos
= pathEnv
.find(pathSep
, start
);
98 if(endpos
!= std::string::npos
)
100 path
.push_back(pathEnv
.substr(start
, endpos
-start
));
108 for(std::vector
<std::string
>::iterator i
= path
.begin();
109 i
!= path
.end(); ++i
)
111 cmSystemTools::ConvertToUnixSlashes(*i
);
116 const char* cmSystemTools::GetExecutableExtension()
118 #if defined(_WIN32) || defined(__CYGWIN__)
126 bool cmSystemTools::MakeDirectory(const char* path
)
128 if(cmSystemTools::FileExists(path
))
132 std::string dir
= path
;
137 cmSystemTools::ConvertToUnixSlashes(dir
);
139 std::string::size_type pos
= dir
.find(':');
140 if(pos
== std::string::npos
)
145 while((pos
= dir
.find('/', pos
)) != std::string::npos
)
147 topdir
= dir
.substr(0, pos
);
148 Mkdir(topdir
.c_str());
151 if(dir
[dir
.size()-1] == '/')
153 topdir
= dir
.substr(0, dir
.size());
159 if(Mkdir(topdir
.c_str()) != 0)
161 // There is a bug in the Borland Run time library which makes MKDIR
162 // return EACCES when it should return EEXISTS
163 // if it is some other error besides directory exists
165 if( (errno
!= EEXIST
)
171 cmSystemTools::Error("Faild to create directory:", path
);
179 // replace replace with with as many times as it shows up in source.
180 // write the result into source.
181 void cmSystemTools::ReplaceString(std::string
& source
,
185 std::string::size_type lengthReplace
= strlen(replace
);
186 std::string::size_type lengthWith
= strlen(with
);
188 std::string::size_type start
= source
.find(replace
);
189 while(start
!= std::string::npos
)
191 rest
= source
.substr(start
+lengthReplace
);
192 source
= source
.substr(0, start
);
195 start
= source
.find(replace
, start
+ lengthWith
);
199 // Read a registry value.
201 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
202 // => will return the data of the "default" value of the key
203 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
204 // => will return the data of the "Root" value of the key
206 #if defined(_WIN32) && !defined(__CYGWIN__)
207 bool cmSystemTools::ReadRegistryValue(const char *key
, std::string
&value
)
210 std::string primary
= key
;
212 std::string valuename
;
214 size_t start
= primary
.find("\\");
215 if (start
== std::string::npos
)
220 size_t valuenamepos
= primary
.find(";");
221 if (valuenamepos
!= std::string::npos
)
223 valuename
= primary
.substr(valuenamepos
+1);
226 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
227 primary
= primary
.substr(0, start
);
230 if (primary
== "HKEY_CURRENT_USER")
232 primaryKey
= HKEY_CURRENT_USER
;
234 if (primary
== "HKEY_CURRENT_CONFIG")
236 primaryKey
= HKEY_CURRENT_CONFIG
;
238 if (primary
== "HKEY_CLASSES_ROOT")
240 primaryKey
= HKEY_CLASSES_ROOT
;
242 if (primary
== "HKEY_LOCAL_MACHINE")
244 primaryKey
= HKEY_LOCAL_MACHINE
;
246 if (primary
== "HKEY_USERS")
248 primaryKey
= HKEY_USERS
;
252 if(RegOpenKeyEx(primaryKey
,
256 &hKey
) != ERROR_SUCCESS
)
262 DWORD dwType
, dwSize
;
265 if(RegQueryValueEx(hKey
,
266 (LPTSTR
)valuename
.c_str(),
270 &dwSize
) == ERROR_SUCCESS
)
272 if (dwType
== REG_SZ
)
282 bool cmSystemTools::ReadRegistryValue(const char *, std::string
&)
289 // Write a registry value.
291 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
292 // => will set the data of the "default" value of the key
293 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
294 // => will set the data of the "Root" value of the key
296 #if defined(_WIN32) && !defined(__CYGWIN__)
297 bool cmSystemTools::WriteRegistryValue(const char *key
, const char *value
)
299 std::string primary
= key
;
301 std::string valuename
;
303 size_t start
= primary
.find("\\");
304 if (start
== std::string::npos
)
309 size_t valuenamepos
= primary
.find(";");
310 if (valuenamepos
!= std::string::npos
)
312 valuename
= primary
.substr(valuenamepos
+1);
315 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
316 primary
= primary
.substr(0, start
);
319 if (primary
== "HKEY_CURRENT_USER")
321 primaryKey
= HKEY_CURRENT_USER
;
323 if (primary
== "HKEY_CURRENT_CONFIG")
325 primaryKey
= HKEY_CURRENT_CONFIG
;
327 if (primary
== "HKEY_CLASSES_ROOT")
329 primaryKey
= HKEY_CLASSES_ROOT
;
331 if (primary
== "HKEY_LOCAL_MACHINE")
333 primaryKey
= HKEY_LOCAL_MACHINE
;
335 if (primary
== "HKEY_USERS")
337 primaryKey
= HKEY_USERS
;
342 if(RegCreateKeyEx(primaryKey
,
346 REG_OPTION_NON_VOLATILE
,
350 &dwDummy
) != ERROR_SUCCESS
)
355 if(RegSetValueEx(hKey
,
356 (LPTSTR
)valuename
.c_str(),
360 (DWORD
)(strlen(value
) + 1)) == ERROR_SUCCESS
)
367 bool cmSystemTools::WriteRegistryValue(const char *, const char *)
373 // Delete a registry value.
375 // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
376 // => will delete the data of the "default" value of the key
377 // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
378 // => will delete the data of the "Root" value of the key
380 #if defined(_WIN32) && !defined(__CYGWIN__)
381 bool cmSystemTools::DeleteRegistryValue(const char *key
)
383 std::string primary
= key
;
385 std::string valuename
;
387 size_t start
= primary
.find("\\");
388 if (start
== std::string::npos
)
393 size_t valuenamepos
= primary
.find(";");
394 if (valuenamepos
!= std::string::npos
)
396 valuename
= primary
.substr(valuenamepos
+1);
399 second
= primary
.substr(start
+1, valuenamepos
-start
-1);
400 primary
= primary
.substr(0, start
);
403 if (primary
== "HKEY_CURRENT_USER")
405 primaryKey
= HKEY_CURRENT_USER
;
407 if (primary
== "HKEY_CURRENT_CONFIG")
409 primaryKey
= HKEY_CURRENT_CONFIG
;
411 if (primary
== "HKEY_CLASSES_ROOT")
413 primaryKey
= HKEY_CLASSES_ROOT
;
415 if (primary
== "HKEY_LOCAL_MACHINE")
417 primaryKey
= HKEY_LOCAL_MACHINE
;
419 if (primary
== "HKEY_USERS")
421 primaryKey
= HKEY_USERS
;
425 if(RegOpenKeyEx(primaryKey
,
429 &hKey
) != ERROR_SUCCESS
)
435 if(RegDeleteValue(hKey
,
436 (LPTSTR
)valuename
.c_str()) == ERROR_SUCCESS
)
444 bool cmSystemTools::DeleteRegistryValue(const char *)
450 // replace replace with with as many times as it shows up in source.
451 // write the result into source.
452 #if defined(_WIN32) && !defined(__CYGWIN__)
453 void cmSystemTools::ExpandRegistryValues(std::string
& source
)
455 // Regular expression to match anything inside [...] that begins in HKEY.
456 // Note that there is a special rule for regular expressions to match a
457 // close square-bracket inside a list delimited by square brackets.
458 // The "[^]]" part of this expression will match any character except
459 // a close square-bracket. The ']' character must be the first in the
460 // list of characters inside the [^...] block of the expression.
461 cmRegularExpression
regEntry("\\[(HKEY[^]]*)\\]");
463 // check for black line or comment
464 while (regEntry
.find(source
))
466 // the arguments are the second match
467 std::string key
= regEntry
.match(1);
469 if (ReadRegistryValue(key
.c_str(), val
))
471 std::string reg
= "[";
473 cmSystemTools::ReplaceString(source
, reg
.c_str(), val
.c_str());
477 std::string reg
= "[";
479 cmSystemTools::ReplaceString(source
, reg
.c_str(), "/registry");
484 void cmSystemTools::ExpandRegistryValues(std::string
&)
490 std::string
cmSystemTools::EscapeQuotes(const char* str
)
492 std::string result
= "";
493 for(const char* ch
= str
; *ch
!= '\0'; ++ch
)
504 bool cmSystemTools::SameFile(const char* file1
, const char* file2
)
507 HANDLE hFile1
, hFile2
;
509 hFile1
= CreateFile( file1
,
514 FILE_FLAG_BACKUP_SEMANTICS
,
517 hFile2
= CreateFile( file2
,
522 FILE_FLAG_BACKUP_SEMANTICS
,
525 if( hFile1
== INVALID_HANDLE_VALUE
|| hFile2
== INVALID_HANDLE_VALUE
)
527 if(hFile1
!= INVALID_HANDLE_VALUE
)
531 if(hFile2
!= INVALID_HANDLE_VALUE
)
538 BY_HANDLE_FILE_INFORMATION fiBuf1
;
539 BY_HANDLE_FILE_INFORMATION fiBuf2
;
540 GetFileInformationByHandle( hFile1
, &fiBuf1
);
541 GetFileInformationByHandle( hFile2
, &fiBuf2
);
544 return (fiBuf1
.nFileIndexHigh
== fiBuf2
.nFileIndexHigh
&&
545 fiBuf1
.nFileIndexLow
== fiBuf2
.nFileIndexLow
);
547 struct stat fileStat1
, fileStat2
;
548 if (stat(file1
, &fileStat1
) == 0 && stat(file2
, &fileStat2
) == 0)
550 // see if the files are the same file
551 // check the device inode and size
552 if(fileStat2
.st_dev
== fileStat1
.st_dev
&&
553 fileStat2
.st_ino
== fileStat1
.st_ino
&&
554 fileStat2
.st_size
== fileStat1
.st_size
565 // return true if the file exists
566 bool cmSystemTools::FileExists(const char* filename
)
569 if (stat(filename
, &fs
) != 0)
580 // Return a capitalized string (i.e the first letter is uppercased, all other
582 std::string
cmSystemTools::Capitalized(const std::string
& s
)
586 n
[0] = toupper(s
[0]);
587 for (size_t i
= 1; i
< s
.size(); i
++)
589 n
[i
] = tolower(s
[i
]);
595 // Return a lower case string
596 std::string
cmSystemTools::LowerCase(const std::string
& s
)
600 for (size_t i
= 0; i
< s
.size(); i
++)
602 n
[i
] = tolower(s
[i
]);
607 // Return a lower case string
608 std::string
cmSystemTools::UpperCase(const std::string
& s
)
612 for (size_t i
= 0; i
< s
.size(); i
++)
614 n
[i
] = toupper(s
[i
]);
620 // convert windows slashes to unix slashes
621 void cmSystemTools::ConvertToUnixSlashes(std::string
& path
)
623 std::string::size_type pos
= 0;
624 while((pos
= path
.find('\\', pos
)) != std::string::npos
)
629 // remove any trailing slash
630 if(path
.size() && path
[path
.size()-1] == '/')
632 path
= path
.substr(0, path
.size()-1);
635 // if there is a tilda ~ then replace it with HOME
636 if(path
.find("~") == 0)
640 path
= std::string(getenv("HOME")) + path
.substr(1);
644 // if there is a /tmp_mnt in a path get rid of it!
646 if(path
.find("/tmp_mnt") == 0)
648 path
= path
.substr(8);
653 // change // to /, and escape any spaces in the path
654 std::string
cmSystemTools::ConvertToUnixOutputPath(const char* path
)
656 std::string ret
= path
;
658 // remove // except at the beginning might be a cygwin drive
659 std::string::size_type pos
= 1;
660 while((pos
= ret
.find("//", pos
)) != std::string::npos
)
664 // now escape spaces if there is a space in the path
665 if(ret
.find(" ") != std::string::npos
)
667 std::string result
= "";
669 for(const char* ch
= ret
.c_str(); *ch
!= '\0'; ++ch
)
671 // if it is already escaped then don't try to escape it again
672 if(*ch
== ' ' && lastch
!= '\\')
686 std::string
cmSystemTools::EscapeSpaces(const char* str
)
688 #if defined(_WIN32) && !defined(__CYGWIN__)
691 // if there are spaces
692 std::string temp
= str
;
693 if (temp
.find(" ") != std::string::npos
&&
694 temp
.find("\"")==std::string::npos
)
703 std::string result
= "";
704 for(const char* ch
= str
; *ch
!= '\0'; ++ch
)
716 std::string
cmSystemTools::ConvertToOutputPath(const char* path
)
718 #if defined(_WIN32) && !defined(__CYGWIN__)
719 return cmSystemTools::ConvertToWindowsOutputPath(path
);
721 return cmSystemTools::ConvertToUnixOutputPath(path
);
726 // remove double slashes not at the start
727 std::string
cmSystemTools::ConvertToWindowsOutputPath(const char* path
)
729 std::string ret
= path
;
730 std::string::size_type pos
= 0;
731 // first convert all of the slashes
732 while((pos
= ret
.find('/', pos
)) != std::string::npos
)
737 // check for really small paths
742 // now clean up a bit and remove double slashes
743 // Only if it is not the first position in the path which is a network
745 pos
= 1; // start at position 1
746 while((pos
= ret
.find("\\\\", pos
)) != std::string::npos
)
750 // now double quote the path if it has spaces in it
751 // and is not already double quoted
752 if(ret
.find(" ") != std::string::npos
756 result
= "\"" + ret
+ "\"";
762 inline void RemoveComments(char* ptr
)
775 bool cmSystemTools::ParseFunction(std::ifstream
& fin
,
777 std::vector
<std::string
>& arguments
,
778 const char* filename
,
783 arguments
= std::vector
<std::string
>();
784 const int BUFFER_SIZE
= 4096;
785 char inbuffer
[BUFFER_SIZE
];
790 if(fin
.getline(inbuffer
, BUFFER_SIZE
) )
792 RemoveComments(inbuffer
);
793 cmRegularExpression
blankLine("^[ \t\r]*$");
794 // cmRegularExpression comment("^[ \t]*#.*$");
795 cmRegularExpression
oneLiner("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)\\)[ \t\r]*$");
796 cmRegularExpression
multiLine("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)$");
797 cmRegularExpression
lastLine("^(.*)\\)[ \t\r]*$");
799 // check for blank line or comment
800 if(blankLine
.find(inbuffer
) )
804 // look for a oneline fun(arg arg2)
805 else if(oneLiner
.find(inbuffer
))
807 // the arguments are the second match
808 std::string args
= oneLiner
.match(2);
809 name
= oneLiner
.match(1);
810 // break up the arguments
811 cmSystemTools::GetArguments(args
, arguments
);
814 // look for a start of a multiline with no trailing ")" fun(arg arg2
815 else if(multiLine
.find(inbuffer
))
817 name
= multiLine
.match(1);
818 std::string args
= multiLine
.match(2);
819 cmSystemTools::GetArguments(args
, arguments
);
820 // Read lines until the closing paren is hit
824 // read lines until the end paren is found
825 if(fin
.getline(inbuffer
, BUFFER_SIZE
) )
827 RemoveComments(inbuffer
);
828 // Check for comment lines and ignore them.
829 if(blankLine
.find(inbuffer
))
831 // Is this the last line?
832 if(lastLine
.find(inbuffer
))
835 std::string args
= lastLine
.match(1);
836 cmSystemTools::GetArguments(args
, arguments
);
840 std::string line
= inbuffer
;
841 cmSystemTools::GetArguments(line
, arguments
);
847 cmSystemTools::Error("Parse error in read function missing end )\nIn File: ",
848 filename
, "\nCurrent line:", inbuffer
);
857 cmSystemTools::Error("Parse error in read function\nIn file:",
858 filename
, "\nCurrent line:", inbuffer
);
866 void cmSystemTools::GetArguments(std::string
& line
,
867 std::vector
<std::string
>& arguments
)
869 // Match a normal argument (not quoted, no spaces).
870 cmRegularExpression
normalArgument("[ \t]*(([^ \t\r\\]|[\\].)+)[ \t\r]*");
871 // Match a quoted argument (surrounded by double quotes, spaces allowed).
872 cmRegularExpression
quotedArgument("[ \t]*(\"([^\"\\]|[\\].)*\")[ \t\r]*");
878 std::string::size_type endpos
=0;
879 bool foundQuoted
= quotedArgument
.find(line
.c_str());
880 bool foundNormal
= normalArgument
.find(line
.c_str());
882 if(foundQuoted
&& foundNormal
)
884 // Both matches were found. Take the earlier one.
885 // Favor double-quoted version if there is a tie.
886 if(normalArgument
.start(1) < quotedArgument
.start(1))
888 arg
= normalArgument
.match(1);
889 endpos
= normalArgument
.end(1);
893 arg
= quotedArgument
.match(1);
894 endpos
= quotedArgument
.end(1);
895 // Strip off the double quotes on the ends.
896 arg
= arg
.substr(1, arg
.length()-2);
899 else if (foundQuoted
)
901 arg
= quotedArgument
.match(1);
902 endpos
= quotedArgument
.end(1);
903 // Strip off the double quotes on the ends.
904 arg
= arg
.substr(1, arg
.length()-2);
908 arg
= normalArgument
.match(1);
909 endpos
= normalArgument
.end(1);
917 arguments
.push_back(cmSystemTools::RemoveEscapes(arg
.c_str()));
918 line
= line
.substr(endpos
, line
.length() - endpos
);
924 std::string
cmSystemTools::RemoveEscapes(const char* s
)
926 std::string result
= "";
927 for(const char* ch
= s
; *ch
; ++ch
)
929 if(*ch
== '\\' && *(ch
+1) != ';')
934 case '\\': result
.insert(result
.end(), '\\'); break;
935 case '"': result
.insert(result
.end(), '"'); break;
936 case ' ': result
.insert(result
.end(), ' '); break;
937 case 't': result
.insert(result
.end(), '\t'); break;
938 case 'n': result
.insert(result
.end(), '\n'); break;
939 case 'r': result
.insert(result
.end(), '\r'); break;
940 case '0': result
.insert(result
.end(), '\0'); break;
943 cmSystemTools::Error("Trailing backslash in argument:\n", s
);
948 std::string
chStr(1, *ch
);
949 cmSystemTools::Error("Invalid escape sequence \\", chStr
.c_str(),
950 "\nin argument ", s
);
956 result
.insert(result
.end(), *ch
);
962 void cmSystemTools::Error(const char* m1
, const char* m2
,
963 const char* m3
, const char* m4
)
965 std::string message
= "CMake Error: ";
982 cmSystemTools::s_ErrorOccured
= true;
983 cmSystemTools::Message(message
.c_str(),"Error");
987 void cmSystemTools::SetErrorCallback(ErrorCallback f
)
992 void cmSystemTools::Message(const char* m1
, const char *title
)
994 if(s_DisableMessages
)
1000 (*s_ErrorCallback
)(m1
, title
, s_DisableMessages
);
1005 std::cerr
<< m1
<< std::endl
;
1011 bool cmSystemTools::CopyFileIfDifferent(const char* source
,
1012 const char* destination
)
1014 if(cmSystemTools::FilesDiffer(source
, destination
))
1016 cmSystemTools::cmCopyFile(source
, destination
);
1023 bool cmSystemTools::FilesDiffer(const char* source
,
1024 const char* destination
)
1026 struct stat statSource
;
1027 if (stat(source
, &statSource
) != 0)
1032 struct stat statDestination
;
1033 if (stat(destination
, &statDestination
) != 0)
1038 if(statSource
.st_size
!= statDestination
.st_size
)
1043 if(statSource
.st_size
== 0)
1048 #if defined(_WIN32) || defined(__CYGWIN__)
1049 std::ifstream
finSource(source
,
1050 std::ios::binary
| std::ios::in
);
1051 std::ifstream
finDestination(destination
,
1052 std::ios::binary
| std::ios::in
);
1054 std::ifstream
finSource(source
);
1055 std::ifstream
finDestination(destination
);
1057 if(!finSource
|| !finDestination
)
1062 char* source_buf
= new char[statSource
.st_size
];
1063 char* dest_buf
= new char[statSource
.st_size
];
1065 finSource
.read(source_buf
, statSource
.st_size
);
1066 finDestination
.read(dest_buf
, statSource
.st_size
);
1068 if(statSource
.st_size
!= static_cast<long>(finSource
.gcount()) ||
1069 statSource
.st_size
!= static_cast<long>(finDestination
.gcount()))
1072 msg
<< "FilesDiffer failed to read files (allocated: "
1073 << statSource
.st_size
<< ", read source: " << finSource
.gcount()
1074 << ", read dest: " << finDestination
.gcount();
1075 cmSystemTools::Error(msg
.str().c_str());
1076 delete [] source_buf
;
1080 int ret
= memcmp((const void*)source_buf
,
1081 (const void*)dest_buf
,
1082 statSource
.st_size
);
1085 delete [] source_buf
;
1092 * Copy a file named by "source" to the file named by "destination".
1094 void cmSystemTools::cmCopyFile(const char* source
,
1095 const char* destination
)
1097 const int bufferSize
= 4096;
1098 char buffer
[bufferSize
];
1100 // If destination is a directory, try to create a file with the same
1101 // name as the source in that directory.
1103 std::string new_destination
;
1104 if(cmSystemTools::FileExists(destination
) &&
1105 cmSystemTools::FileIsDirectory(destination
))
1107 new_destination
= destination
;
1108 cmSystemTools::ConvertToUnixSlashes(new_destination
);
1109 new_destination
+= '/';
1110 std::string source_name
= source
;
1111 new_destination
+= cmSystemTools::GetFilenameName(source_name
);
1112 destination
= new_destination
.c_str();
1115 // Create destination directory
1117 std::string destination_dir
= destination
;
1118 destination_dir
= cmSystemTools::GetFilenamePath(destination_dir
);
1119 cmSystemTools::MakeDirectory(destination_dir
.c_str());
1123 #if defined(_WIN32) || defined(__CYGWIN__)
1124 std::ifstream
fin(source
,
1125 std::ios::binary
| std::ios::in
);
1127 std::ifstream
fin(source
);
1131 cmSystemTools::Error("CopyFile failed to open input file \"",
1136 #if defined(_WIN32) || defined(__CYGWIN__)
1137 std::ofstream
fout(destination
,
1138 std::ios::binary
| std::ios::out
| std::ios::trunc
);
1140 std::ofstream
fout(destination
,
1141 std::ios::out
| std::ios::trunc
);
1145 cmSystemTools::Error("CopyFile failed to open output file \"",
1150 // This copy loop is very sensitive on certain platforms with
1151 // slightly broken stream libraries (like HPUX). Normally, it is
1152 // incorrect to not check the error condition on the fin.read()
1153 // before using the data, but the fin.gcount() will be zero if an
1154 // error occurred. Therefore, the loop should be safe everywhere.
1157 fin
.read(buffer
, bufferSize
);
1160 fout
.write(buffer
, fin
.gcount());
1169 struct stat statSource
, statDestination
;
1170 if (stat(source
, &statSource
) != 0 ||
1171 stat(destination
, &statDestination
) != 0)
1173 cmSystemTools::Error("CopyFile failed to copy files!");
1176 if (statSource
.st_size
!= statDestination
.st_size
)
1179 msg
<< "CopyFile failed to copy files (sizes differ, source: "
1180 << statSource
.st_size
<< " , dest: " << statDestination
.st_size
;
1181 cmSystemTools::Error(msg
.str().c_str());
1185 // return true if the file exists
1186 long int cmSystemTools::ModifiedTime(const char* filename
)
1189 if (stat(filename
, &fs
) != 0)
1195 return (long int)fs
.st_mtime
;
1201 bool cmSystemTools::RemoveFile(const char* source
)
1203 return unlink(source
) != 0 ? false : true;
1206 bool cmSystemTools::IsOn(const char* val
)
1212 std::basic_string
<char> v
= val
;
1214 for(std::basic_string
<char>::iterator c
= v
.begin();
1219 return (v
== "ON" || v
== "1" || v
== "YES" || v
== "TRUE" || v
== "Y");
1222 bool cmSystemTools::IsOff(const char* val
)
1224 if (!val
|| strlen(val
) == 0)
1228 std::basic_string
<char> v
= val
;
1230 for(std::basic_string
<char>::iterator c
= v
.begin();
1235 return (v
== "OFF" || v
== "0" || v
== "NO" || v
== "FALSE" ||
1236 v
== "N" || v
== "NOTFOUND" || v
== "IGNORE");
1240 bool cmSystemTools::RunCommand(const char* command
,
1241 std::string
& output
,
1246 return cmSystemTools::RunCommand(command
, output
, foo
, dir
, verbose
);
1249 #if defined(WIN32) && !defined(__CYGWIN__)
1250 // use this for shell commands like echo and dir
1251 bool RunCommandViaSystem(const char* command
,
1253 std::string
& output
,
1257 const int BUFFER_SIZE
= 4096;
1258 char buffer
[BUFFER_SIZE
];
1259 std::string commandInDir
;
1262 commandInDir
= "cd ";
1263 commandInDir
+= cmSystemTools::ConvertToOutputPath(dir
);
1264 commandInDir
+= " && ";
1265 commandInDir
+= command
;
1269 commandInDir
= command
;
1271 command
= commandInDir
.c_str();
1272 std::string commandToFile
= command
;
1273 commandToFile
+= " > ";
1274 std::string tempFile
;
1275 tempFile
+= _tempnam(0, "cmake");
1277 commandToFile
+= tempFile
;
1278 retVal
= system(commandToFile
.c_str());
1279 std::ifstream
fin(tempFile
.c_str());
1284 std::string errormsg
= "RunCommand produced no output: command: \"";
1285 errormsg
+= command
;
1287 errormsg
+= "\nOutput file: ";
1288 errormsg
+= tempFile
;
1289 cmSystemTools::Error(errormsg
.c_str());
1292 cmSystemTools::RemoveFile(tempFile
.c_str());
1295 bool multiLine
= false;
1298 fin
.getline(buffer
, BUFFER_SIZE
);
1307 cmSystemTools::RemoveFile(tempFile
.c_str());
1312 #endif // endif WIN32 not CYGWIN
1315 // run a command unix uses popen (easy)
1316 // windows uses system and ShortPath
1317 bool cmSystemTools::RunCommand(const char* command
,
1318 std::string
& output
,
1323 if(s_DisableRunCommandOutput
)
1328 #if defined(WIN32) && !defined(__CYGWIN__)
1329 // if the command does not start with a quote, then
1330 // try to find the program, and if the program can not be
1331 // found use system to run the command as it must be a built in
1332 // shell command like echo or dir
1334 if(command
[0] == '\"')
1336 // count the number of quotes
1337 for(const char* s
= command
; *s
!= 0; ++s
)
1348 // if there are more than two double quotes use
1349 // GetShortPathName, the cmd.exe program in windows which
1350 // is used by system fails to execute if there are more than
1351 // one set of quotes in the arguments
1354 cmRegularExpression
quoted("^\"([^\"]*)\"[ \t](.*)");
1355 if(quoted
.find(command
))
1357 std::string shortCmd
;
1358 std::string cmd
= quoted
.match(1);
1359 std::string args
= quoted
.match(2);
1360 if(!cmSystemTools::GetShortPath(cmd
.c_str(), shortCmd
))
1362 cmSystemTools::Error("GetShortPath failed for " , cmd
.c_str());
1367 return RunCommandViaSystem(shortCmd
.c_str(), dir
,
1368 output
, retVal
, verbose
);
1372 cmSystemTools::Error("Could not parse command line with quotes ",
1377 // if there is only one set of quotes or no quotes then just run the command
1378 return RunCommandViaSystem(command
, dir
, output
, retVal
, verbose
);
1380 // if only popen worked on windows.....
1381 std::string commandInDir
;
1384 commandInDir
= "cd ";
1385 commandInDir
+= dir
;
1386 commandInDir
+= " && ";
1387 commandInDir
+= command
;
1391 commandInDir
= command
;
1393 command
= commandInDir
.c_str();
1394 const int BUFFER_SIZE
= 4096;
1395 char buffer
[BUFFER_SIZE
];
1398 std::cout
<< "running " << command
<< std::endl
;
1402 FILE* cpipe
= popen(command
, "r");
1407 fgets(buffer
, BUFFER_SIZE
, cpipe
);
1412 std::cout
<< buffer
<< std::flush
;
1415 fgets(buffer
, BUFFER_SIZE
, cpipe
);
1418 retVal
= pclose(cpipe
);
1419 if (WIFEXITED(retVal
))
1421 retVal
= WEXITSTATUS(retVal
);
1424 if (WIFSIGNALED(retVal
))
1426 retVal
= WTERMSIG(retVal
);
1427 cmStringStream error
;
1428 error
<< "\nProcess terminated due to ";
1452 error
<< "signal " << retVal
;
1455 output
+= error
.str();
1462 * Find the file the given name. Searches the given path and then
1463 * the system search path. Returns the full path to the file if it is
1464 * found. Otherwise, the empty string is returned.
1466 std::string
cmSystemTools::FindFile(const char* name
,
1467 const std::vector
<std::string
>& userPaths
)
1469 // Add the system search path to our path.
1470 std::vector
<std::string
> path
= userPaths
;
1471 cmSystemTools::GetPath(path
);
1473 std::string tryPath
;
1474 for(std::vector
<std::string
>::const_iterator p
= path
.begin();
1475 p
!= path
.end(); ++p
)
1480 if(cmSystemTools::FileExists(tryPath
.c_str()) &&
1481 !cmSystemTools::FileIsDirectory(tryPath
.c_str()))
1483 return cmSystemTools::CollapseFullPath(tryPath
.c_str());
1486 // Couldn't find the file.
1491 * Find the executable with the given name. Searches the given path and then
1492 * the system search path. Returns the full path to the executable if it is
1493 * found. Otherwise, the empty string is returned.
1495 std::string
cmSystemTools::FindProgram(const char* name
,
1496 const std::vector
<std::string
>& userPaths
,
1497 bool no_system_path
)
1499 // See if the executable exists as written.
1500 if(cmSystemTools::FileExists(name
) &&
1501 !cmSystemTools::FileIsDirectory(name
))
1503 return cmSystemTools::CollapseFullPath(name
);
1505 std::string tryPath
= name
;
1506 tryPath
+= cmSystemTools::GetExecutableExtension();
1507 if(cmSystemTools::FileExists(tryPath
.c_str()) &&
1508 !cmSystemTools::FileIsDirectory(tryPath
.c_str()))
1510 return cmSystemTools::CollapseFullPath(tryPath
.c_str());
1513 // Add the system search path to our path.
1514 std::vector
<std::string
> path
= userPaths
;
1515 if (!no_system_path
)
1517 cmSystemTools::GetPath(path
);
1520 for(std::vector
<std::string
>::const_iterator p
= path
.begin();
1521 p
!= path
.end(); ++p
)
1526 if(cmSystemTools::FileExists(tryPath
.c_str()) &&
1527 !cmSystemTools::FileIsDirectory(tryPath
.c_str()))
1529 return cmSystemTools::CollapseFullPath(tryPath
.c_str());
1533 if(cmSystemTools::FileExists(tryPath
.c_str()) &&
1534 !cmSystemTools::FileIsDirectory(tryPath
.c_str()))
1536 return cmSystemTools::CollapseFullPath(tryPath
.c_str());
1542 tryPath
+= cmSystemTools::GetExecutableExtension();
1543 if(cmSystemTools::FileExists(tryPath
.c_str()) &&
1544 !cmSystemTools::FileIsDirectory(tryPath
.c_str()))
1546 return cmSystemTools::CollapseFullPath(tryPath
.c_str());
1550 // Couldn't find the program.
1556 * Find the library with the given name. Searches the given path and then
1557 * the system search path. Returns the full path to the library if it is
1558 * found. Otherwise, the empty string is returned.
1560 std::string
cmSystemTools::FindLibrary(const char* name
,
1561 const std::vector
<std::string
>& userPaths
,
1562 const cmMakefile
*makefile
)
1564 // See if the executable exists as written.
1565 if(cmSystemTools::FileExists(name
))
1567 return cmSystemTools::CollapseFullPath(name
);
1570 // Add the system search path to our path.
1571 std::vector
<std::string
> path
= userPaths
;
1572 cmSystemTools::GetPath(path
);
1574 // Add some lib directories specific to compilers, depending on the
1575 // current generator, so that library that might have been stored here
1576 // can be found too.
1577 // i.e. Microsoft Visual Studio or .Net: path to compiler/../Lib
1578 // Borland: path to compiler/../Lib
1581 const char* genName
= makefile
->GetDefinition("CMAKE_GENERATOR");
1584 if (!strcmp(genName
, "NMake Makefiles") ||
1585 !strcmp(genName
, "Visual Studio 6"))
1587 const char* compiler
= makefile
->GetDefinition("CMAKE_CXX_COMPILER");
1590 std::string compiler_path
= cmSystemTools::FindProgram(compiler
);
1591 if (compiler_path
.size())
1593 std::string lib_path
=
1594 cmSystemTools::GetFilenamePath(
1595 cmSystemTools::GetFilenamePath(compiler_path
)) + "/Lib";
1596 path
.push_back(lib_path
);
1600 else if (!strcmp(genName
, "Visual Studio 7"))
1602 // It is likely that the compiler won't be in the path for .Net, but
1603 // we know where devenv is.
1604 const char* devenv
= makefile
->GetDefinition("MICROSOFT_DEVENV");
1607 std::string devenv_path
= cmSystemTools::FindProgram(devenv
);
1608 if (devenv_path
.size())
1610 std::string vc7_path
=
1611 cmSystemTools::GetFilenamePath(
1612 cmSystemTools::GetFilenamePath(
1613 cmSystemTools::GetFilenamePath(devenv_path
))) + "/Vc7";
1614 path
.push_back(vc7_path
+ "/lib");
1615 path
.push_back(vc7_path
+ "/PlatformSDK/lib");
1619 else if (!strcmp(genName
, "Borland Makefiles"))
1621 const char* bcb_bin_path
= makefile
->GetDefinition("BCB_BIN_PATH");
1624 std::string lib_path
=
1625 cmSystemTools::GetFilenamePath(bcb_bin_path
) + "/Lib";
1626 path
.push_back(lib_path
);
1632 std::string tryPath
;
1633 for(std::vector
<std::string
>::const_iterator p
= path
.begin();
1634 p
!= path
.end(); ++p
)
1636 #if defined(_WIN32) && !defined(__CYGWIN__)
1641 if(cmSystemTools::FileExists(tryPath
.c_str()))
1643 return cmSystemTools::CollapseFullPath(tryPath
.c_str());
1650 if(cmSystemTools::FileExists(tryPath
.c_str()))
1652 return cmSystemTools::CollapseFullPath(tryPath
.c_str());
1658 if(cmSystemTools::FileExists(tryPath
.c_str()))
1660 return cmSystemTools::CollapseFullPath(tryPath
.c_str());
1666 if(cmSystemTools::FileExists(tryPath
.c_str()))
1668 return cmSystemTools::CollapseFullPath(tryPath
.c_str());
1673 // Couldn't find the library.
1677 bool cmSystemTools::FileIsDirectory(const char* name
)
1680 if(stat(name
, &fs
) == 0)
1683 return ((fs
.st_mode
& _S_IFDIR
) != 0);
1685 return S_ISDIR(fs
.st_mode
);
1694 int cmSystemTools::ChangeDirectory(const char *dir
)
1699 std::string
cmSystemTools::GetCurrentWorkingDirectory()
1702 std::string path
= Getcwd(buf
, 2048);
1707 * Given the path to a program executable, get the directory part of the path with the
1708 * file stripped off. If there is no directory part, the empty string is returned.
1710 std::string
cmSystemTools::GetProgramPath(const char* in_name
)
1712 std::string dir
, file
;
1713 cmSystemTools::SplitProgramPath(in_name
, dir
, file
);
1718 * Given the path to a program executable, get the directory part of the path
1719 * with the file stripped off. If there is no directory part, the empty
1720 * string is returned.
1722 void cmSystemTools::SplitProgramPath(const char* in_name
,
1728 cmSystemTools::ConvertToUnixSlashes(dir
);
1730 if(!cmSystemTools::FileIsDirectory(dir
.c_str()))
1732 std::string::size_type slashPos
= dir
.rfind("/");
1733 if(slashPos
!= std::string::npos
)
1735 file
= dir
.substr(slashPos
+1);
1736 dir
= dir
.substr(0, slashPos
);
1745 if((dir
!= "") && !cmSystemTools::FileIsDirectory(dir
.c_str()))
1747 std::string oldDir
= in_name
;
1748 cmSystemTools::ConvertToUnixSlashes(oldDir
);
1749 cmSystemTools::Error("Error splitting file name off end of path:\n",
1750 oldDir
.c_str(), "\nDirectory not found: ",
1758 * Given a path to a file or directory, convert it to a full path.
1759 * This collapses away relative paths. The full path is returned.
1761 std::string
cmSystemTools::CollapseFullPath(const char* in_name
)
1763 std::string dir
, file
;
1764 cmSystemTools::SplitProgramPath(in_name
, dir
, file
);
1766 // Ultra-hack warning:
1767 // This changes to the target directory, saves the working directory,
1768 // and then changes back to the original working directory.
1769 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
1770 if(dir
!= "") { Chdir(dir
.c_str()); }
1771 std::string newDir
= cmSystemTools::GetCurrentWorkingDirectory();
1774 cmSystemTools::ConvertToUnixSlashes(newDir
);
1775 std::string newPath
= newDir
+"/"+file
;
1779 char resolved_name
[MAXPATHLEN
];
1782 char resolved_name
[PATH_MAX
];
1784 char resolved_name
[5024];
1789 realpath(dir
.c_str(), resolved_name
);
1790 dir
= resolved_name
;
1794 dir
= cmSystemTools::GetCurrentWorkingDirectory();
1800 return dir
+ "/" + file
;
1805 * Return path of a full filename (no trailing slashes).
1806 * Warning: returned path is converted to Unix slashes format.
1808 std::string
cmSystemTools::GetFilenamePath(const std::string
& filename
)
1810 std::string fn
= filename
;
1811 cmSystemTools::ConvertToUnixSlashes(fn
);
1813 std::string::size_type slash_pos
= fn
.rfind("/");
1814 if(slash_pos
!= std::string::npos
)
1816 return fn
.substr(0, slash_pos
);
1826 * Return file name of a full filename (i.e. file name without path).
1828 std::string
cmSystemTools::GetFilenameName(const std::string
& filename
)
1830 std::string fn
= filename
;
1831 cmSystemTools::ConvertToUnixSlashes(fn
);
1833 std::string::size_type slash_pos
= fn
.rfind("/");
1834 if(slash_pos
!= std::string::npos
)
1836 return fn
.substr(slash_pos
+ 1);
1846 * Return file extension of a full filename (dot included).
1847 * Warning: this is the longest extension (for example: .tar.gz)
1849 std::string
cmSystemTools::GetFilenameExtension(const std::string
& filename
)
1851 std::string name
= cmSystemTools::GetFilenameName(filename
);
1852 std::string::size_type dot_pos
= name
.find(".");
1853 if(dot_pos
!= std::string::npos
)
1855 return name
.substr(dot_pos
);
1865 * Return file name without extension of a full filename (i.e. without path).
1866 * Warning: it considers the longest extension (for example: .tar.gz)
1868 std::string
cmSystemTools::GetFilenameWithoutExtension(const std::string
& filename
)
1870 std::string name
= cmSystemTools::GetFilenameName(filename
);
1871 std::string::size_type dot_pos
= name
.find(".");
1872 if(dot_pos
!= std::string::npos
)
1874 return name
.substr(0, dot_pos
);
1884 * Return file name without extension of a full filename (i.e. without path).
1885 * Warning: it considers the last extension (for example: removes .gz
1889 cmSystemTools::GetFilenameWithoutLastExtension(const std::string
& filename
)
1891 std::string name
= cmSystemTools::GetFilenameName(filename
);
1892 std::string::size_type dot_pos
= name
.rfind(".");
1893 if(dot_pos
!= std::string::npos
)
1895 return name
.substr(0, dot_pos
);
1904 void cmSystemTools::Glob(const char *directory
, const char *regexp
,
1905 std::vector
<std::string
>& files
)
1908 cmRegularExpression
reg(regexp
);
1910 if (d
.Load(directory
))
1914 numf
= d
.GetNumberOfFiles();
1915 for (i
= 0; i
< numf
; i
++)
1917 std::string fname
= d
.GetFile(i
);
1918 if (reg
.find(fname
))
1920 files
.push_back(fname
);
1927 void cmSystemTools::GlobDirs(const char *fullPath
,
1928 std::vector
<std::string
>& files
)
1930 std::string path
= fullPath
;
1931 std::string::size_type pos
= path
.find("/*");
1932 if(pos
== std::string::npos
)
1934 files
.push_back(fullPath
);
1937 std::string startPath
= path
.substr(0, pos
);
1938 std::string finishPath
= path
.substr(pos
+2);
1941 if (d
.Load(startPath
.c_str()))
1943 for (unsigned int i
= 0; i
< d
.GetNumberOfFiles(); ++i
)
1945 if((std::string(d
.GetFile(i
)) != ".")
1946 && (std::string(d
.GetFile(i
)) != ".."))
1948 std::string fname
= startPath
;
1950 fname
+= d
.GetFile(i
);
1951 if(cmSystemTools::FileIsDirectory(fname
.c_str()))
1953 fname
+= finishPath
;
1954 cmSystemTools::GlobDirs(fname
.c_str(), files
);
1962 void cmSystemTools::ExpandListArguments(std::vector
<std::string
> const& arguments
,
1963 std::vector
<std::string
>& newargs
)
1965 std::vector
<std::string
>::const_iterator i
;
1967 for(i
= arguments
.begin();i
!= arguments
.end(); ++i
)
1969 // if there are no ; in the name then just copy the current string
1970 if(i
->find(';') == std::string::npos
)
1972 newargs
.push_back(*i
);
1976 std::string::size_type start
= 0;
1977 std::string::size_type endpos
= 0;
1978 const std::string::size_type size
= i
->size();
1979 // break up ; separated sections of the string into separate strings
1980 while(endpos
!= size
)
1982 endpos
= i
->find(';', start
);
1983 if(endpos
== std::string::npos
)
1989 // skip right over escaped ; ( \; )
1990 while((endpos
!= std::string::npos
)
1992 && ((*i
)[endpos
-1] == '\\') )
1994 endpos
= i
->find(';', endpos
+1);
1996 if(endpos
== std::string::npos
)
2001 std::string::size_type len
= endpos
- start
;
2004 // check for a closing ] after the start position
2005 if(i
->find('[', start
) == std::string::npos
)
2007 // if there is no [ in the string then keep it
2008 newarg
= i
->substr(start
, len
);
2014 for(std::string::size_type j
= start
; j
< endpos
; ++j
)
2020 else if (i
->at(j
) == ']')
2025 if(opencount
!= closecount
)
2028 endpos
= i
->find(';', endpos
+1);
2029 if(endpos
== std::string::npos
)
2033 len
= endpos
- start
;
2035 newarg
= i
->substr(start
, len
);
2037 std::string::size_type pos
= newarg
.find("\\;");
2038 if(pos
!= std::string::npos
)
2040 newarg
.erase(pos
, 1);
2042 newargs
.push_back(newarg
);
2050 bool cmSystemTools::GetShortPath(const char* path
, std::string
& shortPath
)
2052 #if defined(WIN32) && !defined(__CYGWIN__)
2053 const int size
= int(strlen(path
)) +1; // size of return
2054 char *buffer
= new char[size
]; // create a buffer
2055 char *tempPath
= new char[size
]; // create a buffer
2058 // if the path passed in has quotes around it, first remove the quotes
2059 if (path
[0] == '"' && path
[strlen(path
)-1] == '"')
2061 strcpy(tempPath
,path
+1);
2062 tempPath
[strlen(tempPath
)-1] = '\0';
2066 strcpy(tempPath
,path
);
2070 ret
= GetShortPathName(tempPath
, buffer
, size
);
2072 if(buffer
[0] == 0 || ret
> size
)
2078 FORMAT_MESSAGE_ALLOCATE_BUFFER
|
2079 FORMAT_MESSAGE_FROM_SYSTEM
|
2080 FORMAT_MESSAGE_IGNORE_INSERTS
,
2083 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), // Default language
2088 cmSystemTools::Error((LPCTSTR
)lpMsgBuf
);
2089 LocalFree( lpMsgBuf
);
2091 cmSystemTools::Error("Unable to get a short path: ", path
);