1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmFileCommand.cxx,v $
6 Date: $Date: 2009-03-06 14:14:57 $
7 Version: $Revision: 1.118 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html 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 "cmFileCommand.h"
19 #include "cmHexFileConverter.h"
20 #include "cmFileTimeComparison.h"
22 #if defined(CMAKE_BUILD_WITH_CMAKE)
26 #undef GetCurrentDirectory
27 #include <sys/types.h>
30 #include <cmsys/Directory.hxx>
31 #include <cmsys/Glob.hxx>
32 #include <cmsys/RegularExpression.hxx>
34 // Table of permissions flags.
35 #if defined(_WIN32) && !defined(__CYGWIN__)
36 static mode_t mode_owner_read
= S_IREAD
;
37 static mode_t mode_owner_write
= S_IWRITE
;
38 static mode_t mode_owner_execute
= S_IEXEC
;
39 static mode_t mode_group_read
= 0;
40 static mode_t mode_group_write
= 0;
41 static mode_t mode_group_execute
= 0;
42 static mode_t mode_world_read
= 0;
43 static mode_t mode_world_write
= 0;
44 static mode_t mode_world_execute
= 0;
45 static mode_t mode_setuid
= 0;
46 static mode_t mode_setgid
= 0;
48 static mode_t mode_owner_read
= S_IRUSR
;
49 static mode_t mode_owner_write
= S_IWUSR
;
50 static mode_t mode_owner_execute
= S_IXUSR
;
51 static mode_t mode_group_read
= S_IRGRP
;
52 static mode_t mode_group_write
= S_IWGRP
;
53 static mode_t mode_group_execute
= S_IXGRP
;
54 static mode_t mode_world_read
= S_IROTH
;
55 static mode_t mode_world_write
= S_IWOTH
;
56 static mode_t mode_world_execute
= S_IXOTH
;
57 static mode_t mode_setuid
= S_ISUID
;
58 static mode_t mode_setgid
= S_ISGID
;
63 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
67 this->SetError("must be called with at least two arguments.");
70 std::string subCommand
= args
[0];
71 if ( subCommand
== "WRITE" )
73 return this->HandleWriteCommand(args
, false);
75 else if ( subCommand
== "APPEND" )
77 return this->HandleWriteCommand(args
, true);
79 else if ( subCommand
== "DOWNLOAD" )
81 return this->HandleDownloadCommand(args
);
83 else if ( subCommand
== "READ" )
85 return this->HandleReadCommand(args
);
87 else if ( subCommand
== "STRINGS" )
89 return this->HandleStringsCommand(args
);
91 else if ( subCommand
== "GLOB" )
93 return this->HandleGlobCommand(args
, false);
95 else if ( subCommand
== "GLOB_RECURSE" )
97 return this->HandleGlobCommand(args
, true);
99 else if ( subCommand
== "MAKE_DIRECTORY" )
101 return this->HandleMakeDirectoryCommand(args
);
103 else if ( subCommand
== "REMOVE" )
105 return this->HandleRemove(args
, false);
107 else if ( subCommand
== "REMOVE_RECURSE" )
109 return this->HandleRemove(args
, true);
111 else if ( subCommand
== "INSTALL" )
113 return this->HandleInstallCommand(args
);
115 else if ( subCommand
== "DIFFERENT" )
117 return this->HandleDifferentCommand(args
);
119 else if ( subCommand
== "RPATH_CHANGE" || subCommand
== "CHRPATH" )
121 return this->HandleRPathChangeCommand(args
);
123 else if ( subCommand
== "RPATH_CHECK" )
125 return this->HandleRPathCheckCommand(args
);
127 else if ( subCommand
== "RPATH_REMOVE" )
129 return this->HandleRPathRemoveCommand(args
);
131 else if ( subCommand
== "RELATIVE_PATH" )
133 return this->HandleRelativePathCommand(args
);
135 else if ( subCommand
== "TO_CMAKE_PATH" )
137 return this->HandleCMakePathCommand(args
, false);
139 else if ( subCommand
== "TO_NATIVE_PATH" )
141 return this->HandleCMakePathCommand(args
, true);
144 std::string e
= "does not recognize sub-command "+subCommand
;
145 this->SetError(e
.c_str());
149 //----------------------------------------------------------------------------
150 bool cmFileCommand::HandleWriteCommand(std::vector
<std::string
> const& args
,
154 std::vector
<std::string
>::const_iterator i
= args
.begin();
156 i
++; // Get rid of subcommand
158 std::string fileName
= *i
;
159 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
161 fileName
= this->Makefile
->GetCurrentDirectory();
162 fileName
+= "/" + *i
;
167 for(;i
!= args
.end(); ++i
)
171 if ( !this->Makefile
->CanIWriteThisFile(fileName
.c_str()) )
174 = "attempted to write a file: " + fileName
+
175 " into a source directory.";
176 this->SetError(e
.c_str());
177 cmSystemTools::SetFatalErrorOccured();
180 std::string dir
= cmSystemTools::GetFilenamePath(fileName
);
181 cmSystemTools::MakeDirectory(dir
.c_str());
184 #if defined( _MSC_VER ) || defined( __MINGW32__ )
186 #elif defined( __BORLANDC__ )
195 // Set permissions to writable
196 if ( cmSystemTools::GetPermissions(fileName
.c_str(), mode
) )
198 cmSystemTools::SetPermissions(fileName
.c_str(),
199 #if defined( _MSC_VER ) || defined( __MINGW32__ )
206 // If GetPermissions fails, pretend like it is ok. File open will fail if
207 // the file is not writable
208 std::ofstream
file(fileName
.c_str(), append
?std::ios::app
: std::ios::out
);
211 std::string error
= "Internal CMake error when trying to open file: ";
212 error
+= fileName
.c_str();
213 error
+= " for writing.";
214 this->SetError(error
.c_str());
219 cmSystemTools::SetPermissions(fileName
.c_str(), mode
);
223 //----------------------------------------------------------------------------
224 bool cmFileCommand::HandleReadCommand(std::vector
<std::string
> const& args
)
226 if ( args
.size() < 3 )
228 this->SetError("READ must be called with at least two additional "
233 cmCommandArgumentsHelper argHelper
;
234 cmCommandArgumentGroup group
;
236 cmCAString
readArg (&argHelper
, "READ");
237 cmCAString
fileNameArg (&argHelper
, 0);
238 cmCAString
resultArg (&argHelper
, 0);
240 cmCAString
offsetArg (&argHelper
, "OFFSET", &group
);
241 cmCAString
limitArg (&argHelper
, "LIMIT", &group
);
242 cmCAEnabler
hexOutputArg (&argHelper
, "HEX", &group
);
244 fileNameArg
.Follows(&readArg
);
245 resultArg
.Follows(&fileNameArg
);
246 group
.Follows(&resultArg
);
247 argHelper
.Parse(&args
, 0);
249 std::string fileName
= fileNameArg
.GetString();
250 if ( !cmsys::SystemTools::FileIsFullPath(fileName
.c_str()) )
252 fileName
= this->Makefile
->GetCurrentDirectory();
253 fileName
+= "/" + fileNameArg
.GetString();
256 std::string variable
= resultArg
.GetString();
258 // Open the specified file.
259 #if defined(_WIN32) || defined(__CYGWIN__)
260 std::ifstream
file(fileName
.c_str(), std::ios::in
|
261 (hexOutputArg
.IsEnabled() ? std::ios::binary
: std::ios::in
));
263 std::ifstream
file(fileName
.c_str(), std::ios::in
);
268 std::string error
= "Internal CMake error when trying to open file: ";
269 error
+= fileName
.c_str();
270 error
+= " for reading.";
271 this->SetError(error
.c_str());
277 if (limitArg
.GetString().size() > 0)
279 sizeLimit
= atoi(limitArg
.GetCString());
282 // is there an offset?
284 if (offsetArg
.GetString().size() > 0)
286 offset
= atoi(offsetArg
.GetCString());
293 if (hexOutputArg
.IsEnabled())
295 // Convert part of the file into hex code
297 while((sizeLimit
!= 0) && (c
= file
.get(), file
))
300 sprintf(hex
, "%x", c
&0xff);
311 bool has_newline
= false;
312 while (sizeLimit
!= 0 &&
313 cmSystemTools::GetLineFromStream(file
, line
, &has_newline
,
318 sizeLimit
= sizeLimit
- static_cast<long>(line
.size());
335 this->Makefile
->AddDefinition(variable
.c_str(), output
.c_str());
339 //----------------------------------------------------------------------------
340 bool cmFileCommand::HandleStringsCommand(std::vector
<std::string
> const& args
)
344 this->SetError("STRINGS requires a file name and output variable");
348 // Get the file to read.
349 std::string fileName
= args
[1];
350 if(!cmsys::SystemTools::FileIsFullPath(fileName
.c_str()))
352 fileName
= this->Makefile
->GetCurrentDirectory();
353 fileName
+= "/" + args
[1];
356 // Get the variable in which to store the results.
357 std::string outVar
= args
[2];
359 // Parse the options.
368 unsigned int minlen
= 0;
369 unsigned int maxlen
= 0;
370 int limit_input
= -1;
371 int limit_output
= -1;
372 unsigned int limit_count
= 0;
373 cmsys::RegularExpression regex
;
374 bool have_regex
= false;
375 bool newline_consume
= false;
376 bool hex_conversion_enabled
= true;
377 int arg_mode
= arg_none
;
378 for(unsigned int i
=3; i
< args
.size(); ++i
)
380 if(args
[i
] == "LIMIT_INPUT")
382 arg_mode
= arg_limit_input
;
384 else if(args
[i
] == "LIMIT_OUTPUT")
386 arg_mode
= arg_limit_output
;
388 else if(args
[i
] == "LIMIT_COUNT")
390 arg_mode
= arg_limit_count
;
392 else if(args
[i
] == "LENGTH_MINIMUM")
394 arg_mode
= arg_length_minimum
;
396 else if(args
[i
] == "LENGTH_MAXIMUM")
398 arg_mode
= arg_length_maximum
;
400 else if(args
[i
] == "REGEX")
402 arg_mode
= arg_regex
;
404 else if(args
[i
] == "NEWLINE_CONSUME")
406 newline_consume
= true;
409 else if(args
[i
] == "NO_HEX_CONVERSION")
411 hex_conversion_enabled
= false;
414 else if(arg_mode
== arg_limit_input
)
416 if(sscanf(args
[i
].c_str(), "%d", &limit_input
) != 1 ||
420 e
<< "STRINGS option LIMIT_INPUT value \""
421 << args
[i
] << "\" is not an unsigned integer.";
422 this->SetError(e
.str().c_str());
427 else if(arg_mode
== arg_limit_output
)
429 if(sscanf(args
[i
].c_str(), "%d", &limit_output
) != 1 ||
433 e
<< "STRINGS option LIMIT_OUTPUT value \""
434 << args
[i
] << "\" is not an unsigned integer.";
435 this->SetError(e
.str().c_str());
440 else if(arg_mode
== arg_limit_count
)
443 if(sscanf(args
[i
].c_str(), "%d", &count
) != 1 || count
< 0)
446 e
<< "STRINGS option LIMIT_COUNT value \""
447 << args
[i
] << "\" is not an unsigned integer.";
448 this->SetError(e
.str().c_str());
454 else if(arg_mode
== arg_length_minimum
)
457 if(sscanf(args
[i
].c_str(), "%d", &len
) != 1 || len
< 0)
460 e
<< "STRINGS option LENGTH_MINIMUM value \""
461 << args
[i
] << "\" is not an unsigned integer.";
462 this->SetError(e
.str().c_str());
468 else if(arg_mode
== arg_length_maximum
)
471 if(sscanf(args
[i
].c_str(), "%d", &len
) != 1 || len
< 0)
474 e
<< "STRINGS option LENGTH_MAXIMUM value \""
475 << args
[i
] << "\" is not an unsigned integer.";
476 this->SetError(e
.str().c_str());
482 else if(arg_mode
== arg_regex
)
484 if(!regex
.compile(args
[i
].c_str()))
487 e
<< "STRINGS option REGEX value \""
488 << args
[i
] << "\" could not be compiled.";
489 this->SetError(e
.str().c_str());
498 e
<< "STRINGS given unknown argument \""
500 this->SetError(e
.str().c_str());
505 if (hex_conversion_enabled
)
507 // TODO: should work without temp file, but just on a memory buffer
508 std::string binaryFileName
= this->Makefile
->GetCurrentOutputDirectory();
509 binaryFileName
+= cmake::GetCMakeFilesDirectory();
510 binaryFileName
+= "/FileCommandStringsBinaryFile";
511 if(cmHexFileConverter::TryConvert(fileName
.c_str(),binaryFileName
.c_str()))
513 fileName
= binaryFileName
;
517 // Open the specified file.
518 #if defined(_WIN32) || defined(__CYGWIN__)
519 std::ifstream
fin(fileName
.c_str(), std::ios::in
| std::ios::binary
);
521 std::ifstream
fin(fileName
.c_str(), std::ios::in
);
526 e
<< "STRINGS file \"" << fileName
<< "\" cannot be read.";
527 this->SetError(e
.str().c_str());
531 // Parse strings out of the file.
533 std::vector
<std::string
> strings
;
536 while((!limit_count
|| strings
.size() < limit_count
) &&
537 (limit_input
< 0 || static_cast<int>(fin
.tellg()) < limit_input
) &&
538 (c
= fin
.get(), fin
))
542 // A terminating null character has been found. Check if the
543 // current string matches the requirements. Since it was
544 // terminated by a null character, we require that the length be
545 // at least one no matter what the user specified.
546 if(s
.length() >= minlen
&& s
.length() >= 1 &&
547 (!have_regex
|| regex
.find(s
.c_str())))
549 output_size
+= static_cast<int>(s
.size()) + 1;
550 if(limit_output
>= 0 && output_size
>= limit_output
)
555 strings
.push_back(s
);
558 // Reset the string to empty.
561 else if(c
== '\n' && !newline_consume
)
563 // The current line has been terminated. Check if the current
564 // string matches the requirements. The length may now be as
565 // low as zero since blank lines are allowed.
566 if(s
.length() >= minlen
&&
567 (!have_regex
|| regex
.find(s
.c_str())))
569 output_size
+= static_cast<int>(s
.size()) + 1;
570 if(limit_output
>= 0 && output_size
>= limit_output
)
575 strings
.push_back(s
);
578 // Reset the string to empty.
583 // Ignore CR character to make output always have UNIX newlines.
585 else if(c
>= 0x20 && c
< 0x7F || c
== '\t' || c
== '\f' ||
586 (c
== '\n' && newline_consume
))
588 // This is an ASCII character that may be part of a string.
593 // This is a non-string character. Reset the string to emtpy.
597 // Terminate a string if the maximum length is reached.
598 if(maxlen
> 0 && s
.size() == maxlen
)
600 if(s
.length() >= minlen
&&
601 (!have_regex
|| regex
.find(s
.c_str())))
603 output_size
+= static_cast<int>(s
.size()) + 1;
604 if(limit_output
>= 0 && output_size
>= limit_output
)
609 strings
.push_back(s
);
615 // If there is a non-empty current string we have hit the end of the
616 // input file or the input size limit. Check if the current string
617 // matches the requirements.
618 if((!limit_count
|| strings
.size() < limit_count
) &&
619 !s
.empty() && s
.length() >= minlen
&&
620 (!have_regex
|| regex
.find(s
.c_str())))
622 output_size
+= static_cast<int>(s
.size()) + 1;
623 if(limit_output
< 0 || output_size
< limit_output
)
625 strings
.push_back(s
);
629 // Encode the result in a CMake list.
630 const char* sep
= "";
632 for(std::vector
<std::string
>::const_iterator si
= strings
.begin();
633 si
!= strings
.end(); ++si
)
635 // Separate the strings in the output to make it a list.
639 // Store the string in the output, but escape semicolons to
640 // make sure it is a list.
641 std::string
const& sr
= *si
;
642 for(unsigned int i
=0; i
< sr
.size(); ++i
)
652 // Save the output in a makefile variable.
653 this->Makefile
->AddDefinition(outVar
.c_str(), output
.c_str());
657 //----------------------------------------------------------------------------
658 bool cmFileCommand::HandleGlobCommand(std::vector
<std::string
> const& args
,
661 if ( args
.size() < 2 )
663 this->SetError("GLOB requires at least a variable name");
667 std::vector
<std::string
>::const_iterator i
= args
.begin();
669 i
++; // Get rid of subcommand
671 std::string variable
= *i
;
674 g
.SetRecurse(recurse
);
676 bool explicitFollowSymlinks
= false;
677 cmPolicies::PolicyStatus status
=
678 this->Makefile
->GetPolicyStatus(cmPolicies::CMP0009
);
683 case cmPolicies::NEW
:
684 g
.RecurseThroughSymlinksOff();
686 case cmPolicies::OLD
:
687 case cmPolicies::WARN
:
688 case cmPolicies::REQUIRED_IF_USED
:
689 case cmPolicies::REQUIRED_ALWAYS
:
690 g
.RecurseThroughSymlinksOn();
695 std::string output
= "";
697 for ( ; i
!= args
.end(); ++i
)
699 if ( recurse
&& (*i
== "FOLLOW_SYMLINKS") )
701 explicitFollowSymlinks
= true;
702 g
.RecurseThroughSymlinksOn();
704 if ( i
== args
.end() )
707 "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS");
712 if ( *i
== "RELATIVE" )
714 ++i
; // skip RELATIVE
715 if ( i
== args
.end() )
717 this->SetError("GLOB requires a directory after the RELATIVE tag");
720 g
.SetRelative(i
->c_str());
724 this->SetError("GLOB requires a glob expression after the directory");
729 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
731 std::string expr
= this->Makefile
->GetCurrentDirectory();
732 // Handle script mode
733 if ( expr
.size() > 0 )
748 std::vector
<std::string
>::size_type cc
;
749 std::vector
<std::string
>& files
= g
.GetFiles();
750 for ( cc
= 0; cc
< files
.size(); cc
++ )
761 if(recurse
&& !explicitFollowSymlinks
)
765 case cmPolicies::NEW
:
766 // Correct behavior, yay!
768 case cmPolicies::OLD
:
769 // Probably not really the expected behavior, but the author explicitly
770 // asked for the old behavior... no warning.
771 case cmPolicies::WARN
:
772 // Possibly unexpected old behavior *and* we actually traversed
773 // symlinks without being explicitly asked to: warn the author.
774 if(g
.GetFollowedSymlinkCount() != 0)
776 this->Makefile
->IssueMessage(cmake::AUTHOR_WARNING
,
777 this->Makefile
->GetPolicies()->
778 GetPolicyWarning(cmPolicies::CMP0009
));
781 case cmPolicies::REQUIRED_IF_USED
:
782 case cmPolicies::REQUIRED_ALWAYS
:
783 this->SetError("policy CMP0009 error");
784 this->Makefile
->IssueMessage(cmake::FATAL_ERROR
,
785 this->Makefile
->GetPolicies()->
786 GetRequiredPolicyError(cmPolicies::CMP0009
));
791 this->Makefile
->AddDefinition(variable
.c_str(), output
.c_str());
795 //----------------------------------------------------------------------------
796 bool cmFileCommand::HandleMakeDirectoryCommand(
797 std::vector
<std::string
> const& args
)
801 this->SetError("called with incorrect number of arguments");
805 std::vector
<std::string
>::const_iterator i
= args
.begin();
807 i
++; // Get rid of subcommand
810 for ( ; i
!= args
.end(); ++i
)
812 const std::string
* cdir
= &(*i
);
813 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
815 expr
= this->Makefile
->GetCurrentDirectory();
819 if ( !this->Makefile
->CanIWriteThisFile(cdir
->c_str()) )
821 std::string e
= "attempted to create a directory: " + *cdir
822 + " into a source directory.";
823 this->SetError(e
.c_str());
824 cmSystemTools::SetFatalErrorOccured();
827 if ( !cmSystemTools::MakeDirectory(cdir
->c_str()) )
829 std::string error
= "problem creating directory: " + *cdir
;
830 this->SetError(error
.c_str());
837 //----------------------------------------------------------------------------
839 cmFileCommand::HandleDifferentCommand(std::vector
<std::string
> const& args
)
842 FILE(DIFFERENT <variable> FILES <lhs> <rhs>)
845 // Evaluate arguments.
846 const char* file_lhs
= 0;
847 const char* file_rhs
= 0;
849 enum Doing
{ DoingNone
, DoingVar
, DoingFileLHS
, DoingFileRHS
};
850 Doing doing
= DoingVar
;
851 for(unsigned int i
=1; i
< args
.size(); ++i
)
853 if(args
[i
] == "FILES")
855 doing
= DoingFileLHS
;
857 else if(doing
== DoingVar
)
859 var
= args
[i
].c_str();
862 else if(doing
== DoingFileLHS
)
864 file_lhs
= args
[i
].c_str();
865 doing
= DoingFileRHS
;
867 else if(doing
== DoingFileRHS
)
869 file_rhs
= args
[i
].c_str();
875 e
<< "DIFFERENT given unknown argument " << args
[i
];
876 this->SetError(e
.str().c_str());
882 this->SetError("DIFFERENT not given result variable name.");
885 if(!file_lhs
|| !file_rhs
)
887 this->SetError("DIFFERENT not given FILES option with two file names.");
891 // Compare the files.
893 cmSystemTools::FilesDiffer(file_lhs
, file_rhs
)? "1" : "0";
894 this->Makefile
->AddDefinition(var
, result
);
898 //----------------------------------------------------------------------------
899 // File installation helper class.
900 struct cmFileInstaller
902 // Methods to actually install files.
903 bool InstallFile(const char* fromFile
, const char* toFile
, bool always
);
904 bool InstallDirectory(const char* source
, const char* destination
,
907 // All instances need the file command and makefile using them.
908 cmFileInstaller(cmFileCommand
* fc
, cmMakefile
* mf
):
909 FileCommand(fc
), Makefile(mf
), DestDirLength(0), MatchlessFiles(true)
911 // Get the current manifest.
913 this->Makefile
->GetSafeDefinition("CMAKE_INSTALL_MANIFEST_FILES");
917 // Save the updated install manifest.
918 this->Makefile
->AddDefinition("CMAKE_INSTALL_MANIFEST_FILES",
919 this->Manifest
.c_str());
923 cmFileCommand
* FileCommand
;
924 cmMakefile
* Makefile
;
925 cmFileTimeComparison FileTimes
;
928 // The length of the destdir setting.
931 // Whether to install a file not matching any expression.
934 // The current file manifest (semicolon separated list).
935 std::string Manifest
;
937 // Permissions for files and directories installed by this object.
938 mode_t FilePermissions
;
939 mode_t DirPermissions
;
941 // Properties set by pattern and regex match rules.
942 struct MatchProperties
946 MatchProperties(): Exclude(false), Permissions(0) {}
950 cmsys::RegularExpression Regex
;
951 MatchProperties Properties
;
952 std::string RegexString
;
953 MatchRule(std::string
const& regex
):
954 Regex(regex
.c_str()), RegexString(regex
) {}
956 std::vector
<MatchRule
> MatchRules
;
958 // Get the properties from rules matching this input file.
959 MatchProperties
CollectMatchProperties(const char* file
,
962 // Match rules are case-insensitive on some platforms.
963 #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
964 std::string lower
= cmSystemTools::LowerCase(file
);
965 file
= lower
.c_str();
968 // Collect properties from all matching rules.
969 bool matched
= false;
970 MatchProperties result
;
971 for(std::vector
<MatchRule
>::iterator mr
= this->MatchRules
.begin();
972 mr
!= this->MatchRules
.end(); ++mr
)
974 if(mr
->Regex
.find(file
))
977 result
.Exclude
|= mr
->Properties
.Exclude
;
978 result
.Permissions
|= mr
->Properties
.Permissions
;
981 if(!matched
&& !this->MatchlessFiles
&& !isDirectory
)
983 result
.Exclude
= true;
988 // Append a file to the installation manifest.
989 void ManifestAppend(std::string
const& file
)
991 this->Manifest
+= ";";
992 this->Manifest
+= file
.substr(this->DestDirLength
);
995 // Translate an argument to a permissions bit.
996 bool CheckPermissions(std::string
const& arg
, mode_t
& permissions
)
998 if(arg
== "OWNER_READ") { permissions
|= mode_owner_read
; }
999 else if(arg
== "OWNER_WRITE") { permissions
|= mode_owner_write
; }
1000 else if(arg
== "OWNER_EXECUTE") { permissions
|= mode_owner_execute
; }
1001 else if(arg
== "GROUP_READ") { permissions
|= mode_group_read
; }
1002 else if(arg
== "GROUP_WRITE") { permissions
|= mode_group_write
; }
1003 else if(arg
== "GROUP_EXECUTE") { permissions
|= mode_group_execute
; }
1004 else if(arg
== "WORLD_READ") { permissions
|= mode_world_read
; }
1005 else if(arg
== "WORLD_WRITE") { permissions
|= mode_world_write
; }
1006 else if(arg
== "WORLD_EXECUTE") { permissions
|= mode_world_execute
; }
1007 else if(arg
== "SETUID") { permissions
|= mode_setuid
; }
1008 else if(arg
== "SETGID") { permissions
|= mode_setgid
; }
1012 e
<< "INSTALL given invalid permission \"" << arg
<< "\".";
1013 this->FileCommand
->SetError(e
.str().c_str());
1020 bool InstallSymlink(const char* fromFile
, const char* toFile
, bool always
);
1023 //----------------------------------------------------------------------------
1024 bool cmFileInstaller::InstallSymlink(const char* fromFile
, const char* toFile
,
1027 // Read the original symlink.
1028 std::string symlinkTarget
;
1029 if(!cmSystemTools::ReadSymlink(fromFile
, symlinkTarget
))
1032 e
<< "INSTALL cannot read symlink \"" << fromFile
1033 << "\" to duplicate at \"" << toFile
<< "\".";
1034 this->FileCommand
->SetError(e
.str().c_str());
1038 // Compare the symlink value to that at the destination if not
1039 // always installing.
1043 std::string oldSymlinkTarget
;
1044 if(cmSystemTools::ReadSymlink(toFile
, oldSymlinkTarget
))
1046 if(symlinkTarget
== oldSymlinkTarget
)
1053 // Inform the user about this file installation.
1054 std::string message
= (copy
? "Installing: " : "Up-to-date: ");
1056 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1060 // Remove the destination file so we can always create the symlink.
1061 cmSystemTools::RemoveFile(toFile
);
1063 // Create the symlink.
1064 if(!cmSystemTools::CreateSymlink(symlinkTarget
.c_str(), toFile
))
1067 e
<< "INSTALL cannot duplicate symlink \"" << fromFile
1068 << "\" at \"" << toFile
<< "\".";
1069 this->FileCommand
->SetError(e
.str().c_str());
1074 // Add the file to the manifest.
1075 this->ManifestAppend(toFile
);
1080 //----------------------------------------------------------------------------
1081 bool cmFileInstaller::InstallFile(const char* fromFile
, const char* toFile
,
1084 // Collect any properties matching this file name.
1085 MatchProperties match_properties
=
1086 this->CollectMatchProperties(fromFile
, false);
1088 // Skip the file if it is excluded.
1089 if(match_properties
.Exclude
)
1094 // Short-circuit for symbolic links.
1095 if(cmSystemTools::FileIsSymlink(fromFile
))
1097 return this->InstallSymlink(fromFile
, toFile
, always
);
1100 // Determine whether we will copy the file.
1104 // If both files exist with the same time do not copy.
1105 if(!this->FileTimes
.FileTimesDiffer(fromFile
, toFile
))
1111 // Inform the user about this file installation.
1112 std::string message
= (copy
? "Installing: " : "Up-to-date: ");
1114 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1117 if(copy
&& !cmSystemTools::CopyAFile(fromFile
, toFile
, true, false))
1120 e
<< "INSTALL cannot copy file \"" << fromFile
1121 << "\" to \"" << toFile
<< "\".";
1122 this->FileCommand
->SetError(e
.str().c_str());
1126 // Add the file to the manifest.
1127 this->ManifestAppend(toFile
);
1129 // Set the file modification time of the destination file.
1132 if (!cmSystemTools::CopyFileTime(fromFile
, toFile
))
1135 e
<< "Problem setting modification time on file \"" << toFile
<< "\"";
1136 this->FileCommand
->SetError(e
.str().c_str());
1141 // Set permissions of the destination file.
1142 mode_t permissions
= (match_properties
.Permissions
?
1143 match_properties
.Permissions
: this->FilePermissions
);
1146 // No permissions were explicitly provided but the user requested
1147 // that the source file permissions be used.
1148 cmSystemTools::GetPermissions(fromFile
, permissions
);
1150 if(permissions
&& !cmSystemTools::SetPermissions(toFile
, permissions
))
1153 e
<< "Problem setting permissions on file \"" << toFile
<< "\"";
1154 this->FileCommand
->SetError(e
.str().c_str());
1161 //----------------------------------------------------------------------------
1162 bool cmFileInstaller::InstallDirectory(const char* source
,
1163 const char* destination
,
1166 // Collect any properties matching this directory name.
1167 MatchProperties match_properties
=
1168 this->CollectMatchProperties(source
, true);
1170 // Skip the directory if it is excluded.
1171 if(match_properties
.Exclude
)
1176 // Short-circuit for symbolic links.
1177 if(cmSystemTools::FileIsSymlink(source
))
1179 return this->InstallSymlink(source
, destination
, always
);
1182 // Inform the user about this directory installation.
1183 std::string message
= "Installing: ";
1184 message
+= destination
;
1185 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1187 // Make sure the destination directory exists.
1188 if(!cmSystemTools::MakeDirectory(destination
))
1193 // Compute the requested permissions for the destination directory.
1194 mode_t permissions
= (match_properties
.Permissions
?
1195 match_properties
.Permissions
: this->DirPermissions
);
1198 // No permissions were explicitly provided but the user requested
1199 // that the source directory permissions be used.
1200 cmSystemTools::GetPermissions(source
, permissions
);
1203 // Compute the set of permissions required on this directory to
1204 // recursively install files and subdirectories safely.
1205 mode_t required_permissions
=
1206 mode_owner_read
| mode_owner_write
| mode_owner_execute
;
1208 // If the required permissions are specified it is safe to set the
1209 // final permissions now. Otherwise we must add the required
1210 // permissions temporarily during file installation.
1211 mode_t permissions_before
= 0;
1212 mode_t permissions_after
= 0;
1213 if(permissions
& required_permissions
)
1215 permissions_before
= permissions
;
1219 permissions_before
= permissions
| required_permissions
;
1220 permissions_after
= permissions
;
1223 // Set the required permissions of the destination directory.
1224 if(permissions_before
&&
1225 !cmSystemTools::SetPermissions(destination
, permissions_before
))
1228 e
<< "Problem setting permissions on directory \""
1229 << destination
<< "\"";
1230 this->FileCommand
->SetError(e
.str().c_str());
1234 // Load the directory contents to traverse it recursively.
1235 cmsys::Directory dir
;
1236 if(source
&& *source
)
1240 unsigned long numFiles
= static_cast<unsigned long>(dir
.GetNumberOfFiles());
1241 for(unsigned long fileNum
= 0; fileNum
< numFiles
; ++fileNum
)
1243 if(!(strcmp(dir
.GetFile(fileNum
), ".") == 0 ||
1244 strcmp(dir
.GetFile(fileNum
), "..") == 0))
1246 cmsys_stl::string fromPath
= source
;
1248 fromPath
+= dir
.GetFile(fileNum
);
1249 if(cmSystemTools::FileIsDirectory(fromPath
.c_str()))
1251 cmsys_stl::string toDir
= destination
;
1253 toDir
+= dir
.GetFile(fileNum
);
1254 if(!this->InstallDirectory(fromPath
.c_str(), toDir
.c_str(), always
))
1261 // Install this file.
1262 std::string toFile
= destination
;
1264 toFile
+= dir
.GetFile(fileNum
);
1265 if(!this->InstallFile(fromPath
.c_str(), toFile
.c_str(), always
))
1273 // Set the requested permissions of the destination directory.
1274 if(permissions_after
&&
1275 !cmSystemTools::SetPermissions(destination
, permissions_after
))
1278 e
<< "Problem setting permissions on directory \"" << destination
<< "\"";
1279 this->FileCommand
->SetError(e
.str().c_str());
1286 //----------------------------------------------------------------------------
1287 void cmFileCommand::HandleInstallPermissions(cmFileInstaller
& installer
,
1288 mode_t
& permissions_file
,
1289 mode_t
& permissions_dir
,
1291 bool use_given_permissions_file
,
1292 bool use_given_permissions_dir
,
1293 bool use_source_permissions
) const
1295 // Choose a default for shared library permissions.
1296 bool install_so_no_exe
= this->Makefile
->IsOn("CMAKE_INSTALL_SO_NO_EXE");
1297 // If file permissions were not specified set default permissions
1298 // for this target type.
1299 if(!use_given_permissions_file
&& !use_source_permissions
)
1303 case cmTarget::SHARED_LIBRARY
:
1304 case cmTarget::MODULE_LIBRARY
:
1305 if(install_so_no_exe
)
1307 // Use read/write permissions.
1308 permissions_file
= 0;
1309 permissions_file
|= mode_owner_read
;
1310 permissions_file
|= mode_owner_write
;
1311 permissions_file
|= mode_group_read
;
1312 permissions_file
|= mode_world_read
;
1315 case cmTarget::EXECUTABLE
:
1316 case cmTarget::INSTALL_PROGRAMS
:
1317 // Use read/write/executable permissions.
1318 permissions_file
= 0;
1319 permissions_file
|= mode_owner_read
;
1320 permissions_file
|= mode_owner_write
;
1321 permissions_file
|= mode_owner_execute
;
1322 permissions_file
|= mode_group_read
;
1323 permissions_file
|= mode_group_execute
;
1324 permissions_file
|= mode_world_read
;
1325 permissions_file
|= mode_world_execute
;
1328 // Use read/write permissions.
1329 permissions_file
= 0;
1330 permissions_file
|= mode_owner_read
;
1331 permissions_file
|= mode_owner_write
;
1332 permissions_file
|= mode_group_read
;
1333 permissions_file
|= mode_world_read
;
1338 // If directory permissions were not specified set default permissions.
1339 if(!use_given_permissions_dir
&& !use_source_permissions
)
1341 // Use read/write/executable permissions.
1342 permissions_dir
= 0;
1343 permissions_dir
|= mode_owner_read
;
1344 permissions_dir
|= mode_owner_write
;
1345 permissions_dir
|= mode_owner_execute
;
1346 permissions_dir
|= mode_group_read
;
1347 permissions_dir
|= mode_group_execute
;
1348 permissions_dir
|= mode_world_read
;
1349 permissions_dir
|= mode_world_execute
;
1351 // Set the installer permissions.
1352 installer
.FilePermissions
= permissions_file
;
1353 installer
.DirPermissions
= permissions_dir
;
1356 //----------------------------------------------------------------------------
1358 ::GetTargetTypeFromString(const std::string
& stype
, int& itype
) const
1360 if ( stype
== "EXECUTABLE" )
1362 itype
= cmTarget::EXECUTABLE
;
1364 else if ( stype
== "PROGRAM" )
1366 itype
= cmTarget::INSTALL_PROGRAMS
;
1368 else if ( stype
== "STATIC_LIBRARY" )
1370 itype
= cmTarget::STATIC_LIBRARY
;
1372 else if ( stype
== "SHARED_LIBRARY" )
1374 itype
= cmTarget::SHARED_LIBRARY
;
1376 else if ( stype
== "MODULE" )
1378 itype
= cmTarget::MODULE_LIBRARY
;
1380 else if ( stype
== "DIRECTORY" )
1382 itype
= cmTarget::INSTALL_DIRECTORY
;
1387 //----------------------------------------------------------------------------
1388 bool cmFileCommand::HandleInstallDestination(cmFileInstaller
& installer
,
1389 std::string
& destination
)
1391 // allow for / to be a valid destination
1392 if ( destination
.size() < 2 && destination
!= "/" )
1394 this->SetError("called with inapropriate arguments. "
1395 "No DESTINATION provided or .");
1399 const char* destdir
= cmSystemTools::GetEnv("DESTDIR");
1400 if ( destdir
&& *destdir
)
1402 std::string sdestdir
= destdir
;
1403 cmSystemTools::ConvertToUnixSlashes(sdestdir
);
1404 char ch1
= destination
[0];
1405 char ch2
= destination
[1];
1407 if ( destination
.size() > 2 )
1409 ch3
= destination
[2];
1415 if ( ( ch1
>= 'a' && ch1
<= 'z' || ch1
>= 'A' && ch1
<= 'Z' ) &&
1419 // let's do some destdir magic:
1432 // This is relative path on unix or windows. Since we are doing
1433 // destdir, this case does not make sense.
1434 this->SetError("called with relative DESTINATION. This "
1435 "does not make sense when using DESTDIR. Specify "
1436 "absolute path or remove DESTDIR environment variable.");
1444 // looks like a network path.
1445 std::string message
= "called with network path DESTINATION. This "
1446 "does not make sense when using DESTDIR. Specify local "
1447 "absolute path or remove DESTDIR environment variable."
1449 message
+= destination
;
1450 this->SetError(message
.c_str());
1454 destination
= sdestdir
+ (destination
.c_str() + skip
);
1455 installer
.DestDirLength
= int(sdestdir
.size());
1458 if ( !cmSystemTools::FileExists(destination
.c_str()) )
1460 if ( !cmSystemTools::MakeDirectory(destination
.c_str()) )
1462 std::string errstring
= "cannot create directory: " + destination
+
1463 ". Maybe need administrative privileges.";
1464 this->SetError(errstring
.c_str());
1468 if ( !cmSystemTools::FileIsDirectory(destination
.c_str()) )
1470 std::string errstring
= "INSTALL destination: " + destination
+
1471 " is not a directory.";
1472 this->SetError(errstring
.c_str());
1478 //----------------------------------------------------------------------------
1480 cmFileCommand::HandleRPathChangeCommand(std::vector
<std::string
> const& args
)
1482 // Evaluate arguments.
1483 const char* file
= 0;
1484 const char* oldRPath
= 0;
1485 const char* newRPath
= 0;
1486 enum Doing
{ DoingNone
, DoingFile
, DoingOld
, DoingNew
};
1487 Doing doing
= DoingNone
;
1488 for(unsigned int i
=1; i
< args
.size(); ++i
)
1490 if(args
[i
] == "OLD_RPATH")
1494 else if(args
[i
] == "NEW_RPATH")
1498 else if(args
[i
] == "FILE")
1502 else if(doing
== DoingFile
)
1504 file
= args
[i
].c_str();
1507 else if(doing
== DoingOld
)
1509 oldRPath
= args
[i
].c_str();
1512 else if(doing
== DoingNew
)
1514 newRPath
= args
[i
].c_str();
1520 e
<< "RPATH_CHANGE given unknown argument " << args
[i
];
1521 this->SetError(e
.str().c_str());
1527 this->SetError("RPATH_CHANGE not given FILE option.");
1532 this->SetError("RPATH_CHANGE not given OLD_RPATH option.");
1537 this->SetError("RPATH_CHANGE not given NEW_RPATH option.");
1540 if(!cmSystemTools::FileExists(file
, true))
1543 e
<< "RPATH_CHANGE given FILE \"" << file
<< "\" that does not exist.";
1544 this->SetError(e
.str().c_str());
1547 bool success
= true;
1548 cmSystemToolsFileTime
* ft
= cmSystemTools::FileTimeNew();
1549 bool have_ft
= cmSystemTools::FileTimeGet(file
, ft
);
1552 if(!cmSystemTools::ChangeRPath(file
, oldRPath
, newRPath
, &emsg
, &changed
))
1555 e
<< "RPATH_CHANGE could not write new RPATH:\n"
1556 << " " << newRPath
<< "\n"
1558 << " " << file
<< "\n"
1560 this->SetError(e
.str().c_str());
1567 std::string message
= "Set runtime path of \"";
1569 message
+= "\" to \"";
1570 message
+= newRPath
;
1572 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1576 cmSystemTools::FileTimeSet(file
, ft
);
1579 cmSystemTools::FileTimeDelete(ft
);
1583 //----------------------------------------------------------------------------
1585 cmFileCommand::HandleRPathRemoveCommand(std::vector
<std::string
> const& args
)
1587 // Evaluate arguments.
1588 const char* file
= 0;
1589 enum Doing
{ DoingNone
, DoingFile
};
1590 Doing doing
= DoingNone
;
1591 for(unsigned int i
=1; i
< args
.size(); ++i
)
1593 if(args
[i
] == "FILE")
1597 else if(doing
== DoingFile
)
1599 file
= args
[i
].c_str();
1605 e
<< "RPATH_REMOVE given unknown argument " << args
[i
];
1606 this->SetError(e
.str().c_str());
1612 this->SetError("RPATH_REMOVE not given FILE option.");
1615 if(!cmSystemTools::FileExists(file
, true))
1618 e
<< "RPATH_REMOVE given FILE \"" << file
<< "\" that does not exist.";
1619 this->SetError(e
.str().c_str());
1622 bool success
= true;
1623 cmSystemToolsFileTime
* ft
= cmSystemTools::FileTimeNew();
1624 bool have_ft
= cmSystemTools::FileTimeGet(file
, ft
);
1627 if(!cmSystemTools::RemoveRPath(file
, &emsg
, &removed
))
1630 e
<< "RPATH_REMOVE could not remove RPATH from file:\n"
1631 << " " << file
<< "\n"
1633 this->SetError(e
.str().c_str());
1640 std::string message
= "Removed runtime path from \"";
1643 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1647 cmSystemTools::FileTimeSet(file
, ft
);
1650 cmSystemTools::FileTimeDelete(ft
);
1654 //----------------------------------------------------------------------------
1656 cmFileCommand::HandleRPathCheckCommand(std::vector
<std::string
> const& args
)
1658 // Evaluate arguments.
1659 const char* file
= 0;
1660 const char* rpath
= 0;
1661 enum Doing
{ DoingNone
, DoingFile
, DoingRPath
};
1662 Doing doing
= DoingNone
;
1663 for(unsigned int i
=1; i
< args
.size(); ++i
)
1665 if(args
[i
] == "RPATH")
1669 else if(args
[i
] == "FILE")
1673 else if(doing
== DoingFile
)
1675 file
= args
[i
].c_str();
1678 else if(doing
== DoingRPath
)
1680 rpath
= args
[i
].c_str();
1686 e
<< "RPATH_CHECK given unknown argument " << args
[i
];
1687 this->SetError(e
.str().c_str());
1693 this->SetError("RPATH_CHECK not given FILE option.");
1698 this->SetError("RPATH_CHECK not given RPATH option.");
1702 // If the file exists but does not have the desired RPath then
1703 // delete it. This is used during installation to re-install a file
1704 // if its RPath will change.
1705 if(cmSystemTools::FileExists(file
, true) &&
1706 !cmSystemTools::CheckRPath(file
, rpath
))
1708 cmSystemTools::RemoveFile(file
);
1714 //----------------------------------------------------------------------------
1715 bool cmFileCommand::HandleInstallCommand(std::vector
<std::string
> const& args
)
1717 if ( args
.size() < 6 )
1719 this->SetError("called with incorrect number of arguments");
1723 // Construct a file installer object.
1724 cmFileInstaller
installer(this, this->Makefile
);
1726 std::string rename
= "";
1727 std::string destination
= "";
1729 std::vector
<std::string
> files
;
1730 int itype
= cmTarget::INSTALL_FILES
;
1732 std::map
<cmStdString
, const char*> properties
;
1733 bool optional
= false;
1734 bool result
= this->ParseInstallArgs(args
, installer
, properties
,
1735 itype
, rename
, destination
, files
,
1739 result
= this->DoInstall(installer
,
1740 itype
, rename
, destination
, files
, optional
);
1745 //----------------------------------------------------------------------------
1746 bool cmFileCommand::ParseInstallArgs(std::vector
<std::string
> const& args
,
1747 cmFileInstaller
& installer
,
1748 std::map
<cmStdString
, const char*>& properties
,
1750 std::string
& rename
,
1751 std::string
& destination
,
1752 std::vector
<std::string
>& files
,
1755 std::string stype
= "FILES";
1756 enum Doing
{ DoingNone
, DoingFiles
, DoingProperties
,
1757 DoingPermissionsFile
, DoingPermissionsDir
,
1758 DoingPermissionsMatch
, DoingSelf24
};
1759 Doing doing
= DoingNone
;
1760 bool use_given_permissions_file
= false;
1761 bool use_given_permissions_dir
= false;
1762 bool use_source_permissions
= false;
1763 mode_t permissions_file
= 0;
1764 mode_t permissions_dir
= 0;
1766 cmFileInstaller::MatchRule
* current_match_rule
= 0;
1767 std::vector
<std::string
>::size_type i
= 0;
1768 i
++; // Get rid of subcommand
1769 for ( ; i
!= args
.size(); ++i
)
1771 const std::string
* cstr
= &args
[i
];
1772 if ( *cstr
== "DESTINATION" && i
< args
.size()-1 )
1774 if(current_match_rule
)
1777 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1778 this->SetError(e
.str().c_str());
1783 destination
= args
[i
];
1786 else if ( *cstr
== "TYPE" && i
< args
.size()-1 )
1788 if(current_match_rule
)
1791 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1792 this->SetError(e
.str().c_str());
1798 if ( args
[i
+1] == "OPTIONAL" )
1805 else if ( *cstr
== "RENAME" && i
< args
.size()-1 )
1807 if(current_match_rule
)
1810 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1811 this->SetError(e
.str().c_str());
1819 else if ( *cstr
== "REGEX" && i
< args
.size()-1 )
1822 installer
.MatchRules
.push_back(cmFileInstaller::MatchRule(args
[i
]));
1823 current_match_rule
= &*(installer
.MatchRules
.end()-1);
1824 if(!current_match_rule
->Regex
.is_valid())
1827 e
<< "INSTALL could not compile REGEX \"" << args
[i
] << "\".";
1828 this->SetError(e
.str().c_str());
1833 else if ( *cstr
== "EXCLUDE" )
1835 // Add this property to the current match rule.
1836 if(!current_match_rule
)
1839 e
<< "INSTALL does not allow \""
1840 << *cstr
<< "\" before a REGEX is given.";
1841 this->SetError(e
.str().c_str());
1844 current_match_rule
->Properties
.Exclude
= true;
1845 doing
= DoingPermissionsMatch
;
1847 else if ( *cstr
== "PROPERTIES" )
1849 if(current_match_rule
)
1852 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1853 this->SetError(e
.str().c_str());
1857 doing
= DoingProperties
;
1859 else if ( *cstr
== "PERMISSIONS" )
1861 if(current_match_rule
)
1863 doing
= DoingPermissionsMatch
;
1867 doing
= DoingPermissionsFile
;
1868 use_given_permissions_file
= true;
1871 else if ( *cstr
== "DIR_PERMISSIONS" )
1873 if(current_match_rule
)
1876 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1877 this->SetError(e
.str().c_str());
1881 use_given_permissions_dir
= true;
1882 doing
= DoingPermissionsDir
;
1884 else if ( *cstr
== "USE_SOURCE_PERMISSIONS" )
1886 if(current_match_rule
)
1889 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1890 this->SetError(e
.str().c_str());
1895 use_source_permissions
= true;
1897 else if ( *cstr
== "FILES_MATCHING" )
1899 if(current_match_rule
)
1902 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1903 this->SetError(e
.str().c_str());
1908 installer
.MatchlessFiles
= false;
1910 else if ( *cstr
== "COMPONENTS" )
1912 if(this->Makefile
->IsOn("CMAKE_INSTALL_SELF_2_4"))
1914 // When CMake 2.4 builds this CMake version we need to support
1915 // the install scripts it generates since it asks this CMake
1916 // to install itself using the rules it generated.
1917 doing
= DoingSelf24
;
1921 e
<< "INSTALL called with old-style COMPONENTS argument. "
1922 << "This script was generated with an older version of CMake. "
1923 << "Re-run this cmake version on your build tree.";
1924 this->SetError(e
.str().c_str());
1927 else if ( *cstr
== "CONFIGURATIONS" )
1930 e
<< "INSTALL called with old-style CONFIGURATIONS argument. "
1931 << "This script was generated with an older version of CMake. "
1932 << "Re-run this cmake version on your build tree.";
1933 this->SetError(e
.str().c_str());
1936 else if(*cstr
== "FILES" && doing
!= DoingFiles
)
1938 if(current_match_rule
)
1941 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1942 this->SetError(e
.str().c_str());
1948 else if(doing
== DoingProperties
&& i
< args
.size()-1)
1950 properties
[args
[i
]] = args
[i
+1].c_str();
1953 else if(doing
== DoingFiles
)
1955 files
.push_back(*cstr
);
1957 else if(doing
== DoingPermissionsFile
)
1959 if(!installer
.CheckPermissions(args
[i
], permissions_file
))
1964 else if(doing
== DoingPermissionsDir
)
1966 if(!installer
.CheckPermissions(args
[i
], permissions_dir
))
1971 else if(doing
== DoingPermissionsMatch
)
1973 if(!installer
.CheckPermissions(
1974 args
[i
], current_match_rule
->Properties
.Permissions
))
1979 else if(doing
== DoingSelf24
)
1981 // Ignore these arguments for compatibility. This should be
1982 // reached only when CMake 2.4 is installing the current
1983 // CMake. It can be removed when CMake 2.6 or higher is
1984 // required to build CMake.
1988 this->SetError("called with inappropriate arguments");
1993 // now check and postprocess what has been parsed
1994 if ( files
.size() == 0 )
1996 // nothing to do, no files were listed.
1997 // if this is handled as error, INSTALL_FILES() creates an invalid
1998 // cmake_install.cmake script with no FILES() arguments if no files were
1999 // given to INSTALL_FILES(). This was accepted with CMake 2.4.x.
2003 // Check rename form.
2006 if(itype
!= cmTarget::INSTALL_FILES
&&
2007 itype
!= cmTarget::INSTALL_PROGRAMS
)
2009 this->SetError("INSTALL option RENAME may be used only with "
2010 "FILES or PROGRAMS.");
2013 if(files
.size() > 1)
2015 this->SetError("INSTALL option RENAME may be used only with "
2021 if (this->HandleInstallDestination(installer
, destination
) == false)
2026 if(properties
.find("VERSION") != properties
.end())
2029 e
<< "INSTALL called with old-style VERSION property. "
2030 << "This script was generated with an older version of CMake. "
2031 << "Re-run this cmake version on your build tree.";
2032 this->SetError(e
.str().c_str());
2035 if(properties
.find("SOVERSION") != properties
.end())
2038 e
<< "INSTALL called with old-style SOVERSION property. "
2039 << "This script was generated with an older version of CMake. "
2040 << "Re-run this cmake version on your build tree.";
2041 this->SetError(e
.str().c_str());
2045 this->GetTargetTypeFromString(stype
, itype
);
2047 this->HandleInstallPermissions(installer
,
2051 use_given_permissions_file
,
2052 use_given_permissions_dir
,
2053 use_source_permissions
);
2058 //----------------------------------------------------------------------------
2059 bool cmFileCommand::DoInstall( cmFileInstaller
& installer
,
2061 const std::string
& rename
,
2062 const std::string
& destination
,
2063 const std::vector
<std::string
>& files
,
2064 const bool optional
)
2066 typedef std::set
<cmStdString
>::const_iterator iter_type
;
2068 // Check whether files should be copied always or only if they have
2071 cmSystemTools::IsOn(cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS"));
2073 // Handle each file listed.
2074 for (std::vector
<std::string
>::size_type i
= 0; i
< files
.size(); i
++ )
2076 // Split the input file into its directory and name components.
2077 std::vector
<std::string
> fromPathComponents
;
2078 cmSystemTools::SplitPath(files
[i
].c_str(), fromPathComponents
);
2079 std::string fromName
= *(fromPathComponents
.end()-1);
2080 std::string fromDir
= cmSystemTools::JoinPath(fromPathComponents
.begin(),
2081 fromPathComponents
.end()-1);
2083 // Compute the full path to the destination file.
2084 std::string toFile
= destination
;
2085 std::string
const& toName
= rename
.empty()? fromName
: rename
;
2092 // Construct the full path to the source file. The file name may
2093 // have been changed above.
2094 std::string fromFile
= fromDir
;
2095 if(!fromName
.empty())
2098 fromFile
+= fromName
;
2101 std::string message
;
2102 if(!cmSystemTools::SameFile(fromFile
.c_str(), toFile
.c_str()))
2104 if(itype
== cmTarget::INSTALL_DIRECTORY
&&
2105 (fromFile
.empty() ||
2106 cmSystemTools::FileIsDirectory(fromFile
.c_str())))
2108 // Try installing this directory.
2109 if(!installer
.InstallDirectory(fromFile
.c_str(), toFile
.c_str(),
2115 else if(cmSystemTools::FileExists(fromFile
.c_str()))
2117 // Install this file.
2118 if(!installer
.InstallFile(fromFile
.c_str(), toFile
.c_str(),
2126 // The input file does not exist and installation is not optional.
2128 e
<< "INSTALL cannot find file \"" << fromFile
<< "\" to install.";
2129 this->SetError(e
.str().c_str());
2138 //----------------------------------------------------------------------------
2139 bool cmFileCommand::HandleRelativePathCommand(
2140 std::vector
<std::string
> const& args
)
2142 if(args
.size() != 4 )
2144 this->SetError("called with incorrect number of arguments");
2148 const std::string
& outVar
= args
[1];
2149 const std::string
& directoryName
= args
[2];
2150 const std::string
& fileName
= args
[3];
2152 if(!cmSystemTools::FileIsFullPath(directoryName
.c_str()))
2154 std::string errstring
=
2155 "RelativePath must be passed a full path to the directory: "
2157 this->SetError(errstring
.c_str());
2160 if(!cmSystemTools::FileIsFullPath(fileName
.c_str()))
2162 std::string errstring
=
2163 "RelativePath must be passed a full path to the file: "
2165 this->SetError(errstring
.c_str());
2169 std::string res
= cmSystemTools::RelativePath(directoryName
.c_str(),
2171 this->Makefile
->AddDefinition(outVar
.c_str(),
2177 //----------------------------------------------------------------------------
2178 bool cmFileCommand::HandleRemove(std::vector
<std::string
> const& args
,
2182 std::string message
;
2183 std::vector
<std::string
>::const_iterator i
= args
.begin();
2185 i
++; // Get rid of subcommand
2186 for(;i
!= args
.end(); ++i
)
2188 std::string fileName
= *i
;
2189 if(!cmsys::SystemTools::FileIsFullPath(fileName
.c_str()))
2191 fileName
= this->Makefile
->GetCurrentDirectory();
2192 fileName
+= "/" + *i
;
2195 if(cmSystemTools::FileIsDirectory(fileName
.c_str()) && recurse
)
2197 cmSystemTools::RemoveADirectory(fileName
.c_str());
2201 cmSystemTools::RemoveFile(fileName
.c_str());
2207 //----------------------------------------------------------------------------
2208 bool cmFileCommand::HandleCMakePathCommand(std::vector
<std::string
>
2212 std::vector
<std::string
>::const_iterator i
= args
.begin();
2213 if(args
.size() != 3)
2215 this->SetError("FILE(SYSTEM_PATH ENV result) must be called with "
2216 "only three arguments.");
2219 i
++; // Get rid of subcommand
2220 #if defined(_WIN32) && !defined(__CYGWIN__)
2225 std::vector
<cmsys::String
> path
= cmSystemTools::SplitString(i
->c_str(),
2228 const char* var
= i
->c_str();
2230 for(std::vector
<cmsys::String
>::iterator j
= path
.begin();
2231 j
!= path
.end(); ++j
)
2233 if(j
!= path
.begin())
2239 cmSystemTools::ConvertToUnixSlashes(*j
);
2243 *j
= cmSystemTools::ConvertToOutputPath(j
->c_str());
2244 // remove double quotes in the path
2245 cmsys::String
& s
= *j
;
2247 if(s
.size() > 1 && s
[0] == '\"' && s
[s
.size()-1] == '\"')
2249 s
= s
.substr(1,s
.size()-2);
2254 this->Makefile
->AddDefinition(var
, value
.c_str());
2257 #if defined(CMAKE_BUILD_WITH_CMAKE)
2259 // Stuff for curl download
2260 typedef std::vector
<char> cmFileCommandVectorOfChar
;
2263 cmFileCommandWriteMemoryCallback(void *ptr
, size_t size
, size_t nmemb
,
2266 register int realsize
= (int)(size
* nmemb
);
2267 std::ofstream
* fout
= static_cast<std::ofstream
*>(data
);
2268 const char* chPtr
= static_cast<char*>(ptr
);
2269 fout
->write(chPtr
, realsize
);
2274 cmFileCommandCurlDebugCallback(CURL
*, curl_infotype
, char *chPtr
,
2275 size_t size
, void *data
)
2277 cmFileCommandVectorOfChar
*vec
2278 = static_cast<cmFileCommandVectorOfChar
*>(data
);
2279 vec
->insert(vec
->end(), chPtr
, chPtr
+ size
);
2290 cmFileCommand::HandleDownloadCommand(std::vector
<std::string
>
2293 #if defined(CMAKE_BUILD_WITH_CMAKE)
2294 std::vector
<std::string
>::const_iterator i
= args
.begin();
2297 this->SetError("FILE(DOWNLOAD url file) must be called with "
2298 "at least three arguments.");
2301 i
++; // Get rid of subcommand
2302 std::string url
= *i
;
2304 std::string file
= *i
;
2307 std::string verboseLog
;
2308 std::string statusVar
;
2309 while(i
!= args
.end())
2316 timeout
= atof(i
->c_str());
2320 this->SetError("FILE(DOWNLOAD url file TIMEOUT time) missing "
2321 "time for TIMEOUT.");
2325 else if(*i
== "LOG")
2328 if( i
== args
.end())
2330 this->SetError("FILE(DOWNLOAD url file LOG VAR) missing "
2336 else if(*i
== "STATUS")
2339 if( i
== args
.end())
2341 this->SetError("FILE(DOWNLOAD url file STATUS VAR) missing "
2350 std::string dir
= cmSystemTools::GetFilenamePath(file
.c_str());
2351 if(!cmSystemTools::FileExists(dir
.c_str()) &&
2352 !cmSystemTools::MakeDirectory(dir
.c_str()))
2354 std::string errstring
= "FILE(DOWNLOAD ) error; cannot create directory: "
2355 + dir
+ ". Maybe need administrative privileges.";
2356 this->SetError(errstring
.c_str());
2360 std::ofstream
fout(file
.c_str(), std::ios::binary
);
2363 this->SetError("FILE(DOWNLOAD url file TIMEOUT time) can not open "
2368 curl_global_init(CURL_GLOBAL_DEFAULT
);
2369 curl
= curl_easy_init();
2372 this->SetError("FILE(DOWNLOAD ) error "
2373 "initializing curl.");
2377 curl_easy_setopt(curl
, CURLOPT_URL
, url
.c_str());
2378 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
,
2379 cmFileCommandWriteMemoryCallback
);
2380 curl_easy_setopt(curl
, CURLOPT_DEBUGFUNCTION
,
2381 cmFileCommandCurlDebugCallback
);
2382 cmFileCommandVectorOfChar chunkDebug
;
2383 ::curl_easy_setopt(curl
, CURLOPT_FILE
, (void *)&fout
);
2384 ::curl_easy_setopt(curl
, CURLOPT_DEBUGDATA
, (void *)&chunkDebug
);
2385 if(verboseLog
.size())
2387 curl_easy_setopt(curl
, CURLOPT_VERBOSE
, 1);
2391 curl_easy_setopt(curl
, CURLOPT_TIMEOUT
, timeout
);
2393 CURLcode res
= curl_easy_perform(curl
);
2394 /* always cleanup */
2395 curl_easy_cleanup(curl
);
2396 if(statusVar
.size())
2398 cmOStringStream result
;
2399 result
<< (int)res
<< ";\"" << curl_easy_strerror(res
) << "\"";
2400 this->Makefile
->AddDefinition(statusVar
.c_str(),
2401 result
.str().c_str());
2403 curl_global_cleanup();
2404 if(chunkDebug
.size())
2406 chunkDebug
.push_back(0);
2407 if(CURLE_OPERATION_TIMEOUTED
== res
)
2409 std::string output
= &*chunkDebug
.begin();
2411 if(verboseLog
.size())
2413 this->Makefile
->AddDefinition(verboseLog
.c_str(),
2414 &*chunkDebug
.begin());
2418 this->Makefile
->AddDefinition(verboseLog
.c_str(),
2419 &*chunkDebug
.begin());
2423 this->SetError("FILE(DOWNLOAD ) "
2424 "not supported in bootstrap cmake ");