1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmFileCommand.cxx,v $
6 Date: $Date: 2009-09-11 12:18:03 $
7 Version: $Revision: 1.136 $
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
== "RENAME" )
105 return this->HandleRename(args
);
107 else if ( subCommand
== "REMOVE" )
109 return this->HandleRemove(args
, false);
111 else if ( subCommand
== "REMOVE_RECURSE" )
113 return this->HandleRemove(args
, true);
115 else if ( subCommand
== "COPY" )
117 return this->HandleCopyCommand(args
);
119 else if ( subCommand
== "INSTALL" )
121 return this->HandleInstallCommand(args
);
123 else if ( subCommand
== "DIFFERENT" )
125 return this->HandleDifferentCommand(args
);
127 else if ( subCommand
== "RPATH_CHANGE" || subCommand
== "CHRPATH" )
129 return this->HandleRPathChangeCommand(args
);
131 else if ( subCommand
== "RPATH_CHECK" )
133 return this->HandleRPathCheckCommand(args
);
135 else if ( subCommand
== "RPATH_REMOVE" )
137 return this->HandleRPathRemoveCommand(args
);
139 else if ( subCommand
== "RELATIVE_PATH" )
141 return this->HandleRelativePathCommand(args
);
143 else if ( subCommand
== "TO_CMAKE_PATH" )
145 return this->HandleCMakePathCommand(args
, false);
147 else if ( subCommand
== "TO_NATIVE_PATH" )
149 return this->HandleCMakePathCommand(args
, true);
152 std::string e
= "does not recognize sub-command "+subCommand
;
153 this->SetError(e
.c_str());
157 //----------------------------------------------------------------------------
158 bool cmFileCommand::HandleWriteCommand(std::vector
<std::string
> const& args
,
162 std::vector
<std::string
>::const_iterator i
= args
.begin();
164 i
++; // Get rid of subcommand
166 std::string fileName
= *i
;
167 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
169 fileName
= this->Makefile
->GetCurrentDirectory();
170 fileName
+= "/" + *i
;
175 for(;i
!= args
.end(); ++i
)
179 if ( !this->Makefile
->CanIWriteThisFile(fileName
.c_str()) )
182 = "attempted to write a file: " + fileName
+
183 " into a source directory.";
184 this->SetError(e
.c_str());
185 cmSystemTools::SetFatalErrorOccured();
188 std::string dir
= cmSystemTools::GetFilenamePath(fileName
);
189 cmSystemTools::MakeDirectory(dir
.c_str());
192 #if defined( _MSC_VER ) || defined( __MINGW32__ )
194 #elif defined( __BORLANDC__ )
203 // Set permissions to writable
204 if ( cmSystemTools::GetPermissions(fileName
.c_str(), mode
) )
206 cmSystemTools::SetPermissions(fileName
.c_str(),
207 #if defined( _MSC_VER ) || defined( __MINGW32__ )
214 // If GetPermissions fails, pretend like it is ok. File open will fail if
215 // the file is not writable
216 std::ofstream
file(fileName
.c_str(), append
?std::ios::app
: std::ios::out
);
219 std::string error
= "Internal CMake error when trying to open file: ";
220 error
+= fileName
.c_str();
221 error
+= " for writing.";
222 this->SetError(error
.c_str());
227 cmSystemTools::SetPermissions(fileName
.c_str(), mode
);
231 //----------------------------------------------------------------------------
232 bool cmFileCommand::HandleReadCommand(std::vector
<std::string
> const& args
)
234 if ( args
.size() < 3 )
236 this->SetError("READ must be called with at least two additional "
241 cmCommandArgumentsHelper argHelper
;
242 cmCommandArgumentGroup group
;
244 cmCAString
readArg (&argHelper
, "READ");
245 cmCAString
fileNameArg (&argHelper
, 0);
246 cmCAString
resultArg (&argHelper
, 0);
248 cmCAString
offsetArg (&argHelper
, "OFFSET", &group
);
249 cmCAString
limitArg (&argHelper
, "LIMIT", &group
);
250 cmCAEnabler
hexOutputArg (&argHelper
, "HEX", &group
);
252 fileNameArg
.Follows(&readArg
);
253 resultArg
.Follows(&fileNameArg
);
254 group
.Follows(&resultArg
);
255 argHelper
.Parse(&args
, 0);
257 std::string fileName
= fileNameArg
.GetString();
258 if ( !cmsys::SystemTools::FileIsFullPath(fileName
.c_str()) )
260 fileName
= this->Makefile
->GetCurrentDirectory();
261 fileName
+= "/" + fileNameArg
.GetString();
264 std::string variable
= resultArg
.GetString();
266 // Open the specified file.
267 #if defined(_WIN32) || defined(__CYGWIN__)
268 std::ifstream
file(fileName
.c_str(), std::ios::in
|
269 (hexOutputArg
.IsEnabled() ? std::ios::binary
: std::ios::in
));
271 std::ifstream
file(fileName
.c_str(), std::ios::in
);
276 std::string error
= "Internal CMake error when trying to open file: ";
277 error
+= fileName
.c_str();
278 error
+= " for reading.";
279 this->SetError(error
.c_str());
285 if (limitArg
.GetString().size() > 0)
287 sizeLimit
= atoi(limitArg
.GetCString());
290 // is there an offset?
292 if (offsetArg
.GetString().size() > 0)
294 offset
= atoi(offsetArg
.GetCString());
301 if (hexOutputArg
.IsEnabled())
303 // Convert part of the file into hex code
305 while((sizeLimit
!= 0) && (file
.get(c
)))
308 sprintf(hex
, "%.2x", c
&0xff);
319 bool has_newline
= false;
320 while (sizeLimit
!= 0 &&
321 cmSystemTools::GetLineFromStream(file
, line
, &has_newline
,
326 sizeLimit
= sizeLimit
- static_cast<long>(line
.size());
343 this->Makefile
->AddDefinition(variable
.c_str(), output
.c_str());
347 //----------------------------------------------------------------------------
348 bool cmFileCommand::HandleStringsCommand(std::vector
<std::string
> const& args
)
352 this->SetError("STRINGS requires a file name and output variable");
356 // Get the file to read.
357 std::string fileName
= args
[1];
358 if(!cmsys::SystemTools::FileIsFullPath(fileName
.c_str()))
360 fileName
= this->Makefile
->GetCurrentDirectory();
361 fileName
+= "/" + args
[1];
364 // Get the variable in which to store the results.
365 std::string outVar
= args
[2];
367 // Parse the options.
376 unsigned int minlen
= 0;
377 unsigned int maxlen
= 0;
378 int limit_input
= -1;
379 int limit_output
= -1;
380 unsigned int limit_count
= 0;
381 cmsys::RegularExpression regex
;
382 bool have_regex
= false;
383 bool newline_consume
= false;
384 bool hex_conversion_enabled
= true;
385 int arg_mode
= arg_none
;
386 for(unsigned int i
=3; i
< args
.size(); ++i
)
388 if(args
[i
] == "LIMIT_INPUT")
390 arg_mode
= arg_limit_input
;
392 else if(args
[i
] == "LIMIT_OUTPUT")
394 arg_mode
= arg_limit_output
;
396 else if(args
[i
] == "LIMIT_COUNT")
398 arg_mode
= arg_limit_count
;
400 else if(args
[i
] == "LENGTH_MINIMUM")
402 arg_mode
= arg_length_minimum
;
404 else if(args
[i
] == "LENGTH_MAXIMUM")
406 arg_mode
= arg_length_maximum
;
408 else if(args
[i
] == "REGEX")
410 arg_mode
= arg_regex
;
412 else if(args
[i
] == "NEWLINE_CONSUME")
414 newline_consume
= true;
417 else if(args
[i
] == "NO_HEX_CONVERSION")
419 hex_conversion_enabled
= false;
422 else if(arg_mode
== arg_limit_input
)
424 if(sscanf(args
[i
].c_str(), "%d", &limit_input
) != 1 ||
428 e
<< "STRINGS option LIMIT_INPUT value \""
429 << args
[i
] << "\" is not an unsigned integer.";
430 this->SetError(e
.str().c_str());
435 else if(arg_mode
== arg_limit_output
)
437 if(sscanf(args
[i
].c_str(), "%d", &limit_output
) != 1 ||
441 e
<< "STRINGS option LIMIT_OUTPUT value \""
442 << args
[i
] << "\" is not an unsigned integer.";
443 this->SetError(e
.str().c_str());
448 else if(arg_mode
== arg_limit_count
)
451 if(sscanf(args
[i
].c_str(), "%d", &count
) != 1 || count
< 0)
454 e
<< "STRINGS option LIMIT_COUNT value \""
455 << args
[i
] << "\" is not an unsigned integer.";
456 this->SetError(e
.str().c_str());
462 else if(arg_mode
== arg_length_minimum
)
465 if(sscanf(args
[i
].c_str(), "%d", &len
) != 1 || len
< 0)
468 e
<< "STRINGS option LENGTH_MINIMUM value \""
469 << args
[i
] << "\" is not an unsigned integer.";
470 this->SetError(e
.str().c_str());
476 else if(arg_mode
== arg_length_maximum
)
479 if(sscanf(args
[i
].c_str(), "%d", &len
) != 1 || len
< 0)
482 e
<< "STRINGS option LENGTH_MAXIMUM value \""
483 << args
[i
] << "\" is not an unsigned integer.";
484 this->SetError(e
.str().c_str());
490 else if(arg_mode
== arg_regex
)
492 if(!regex
.compile(args
[i
].c_str()))
495 e
<< "STRINGS option REGEX value \""
496 << args
[i
] << "\" could not be compiled.";
497 this->SetError(e
.str().c_str());
506 e
<< "STRINGS given unknown argument \""
508 this->SetError(e
.str().c_str());
513 if (hex_conversion_enabled
)
515 // TODO: should work without temp file, but just on a memory buffer
516 std::string binaryFileName
= this->Makefile
->GetCurrentOutputDirectory();
517 binaryFileName
+= cmake::GetCMakeFilesDirectory();
518 binaryFileName
+= "/FileCommandStringsBinaryFile";
519 if(cmHexFileConverter::TryConvert(fileName
.c_str(),binaryFileName
.c_str()))
521 fileName
= binaryFileName
;
525 // Open the specified file.
526 #if defined(_WIN32) || defined(__CYGWIN__)
527 std::ifstream
fin(fileName
.c_str(), std::ios::in
| std::ios::binary
);
529 std::ifstream
fin(fileName
.c_str(), std::ios::in
);
534 e
<< "STRINGS file \"" << fileName
<< "\" cannot be read.";
535 this->SetError(e
.str().c_str());
539 // Parse strings out of the file.
541 std::vector
<std::string
> strings
;
544 while((!limit_count
|| strings
.size() < limit_count
) &&
545 (limit_input
< 0 || static_cast<int>(fin
.tellg()) < limit_input
) &&
546 (c
= fin
.get(), fin
))
550 // A terminating null character has been found. Check if the
551 // current string matches the requirements. Since it was
552 // terminated by a null character, we require that the length be
553 // at least one no matter what the user specified.
554 if(s
.length() >= minlen
&& s
.length() >= 1 &&
555 (!have_regex
|| regex
.find(s
.c_str())))
557 output_size
+= static_cast<int>(s
.size()) + 1;
558 if(limit_output
>= 0 && output_size
>= limit_output
)
563 strings
.push_back(s
);
566 // Reset the string to empty.
569 else if(c
== '\n' && !newline_consume
)
571 // The current line has been terminated. Check if the current
572 // string matches the requirements. The length may now be as
573 // low as zero since blank lines are allowed.
574 if(s
.length() >= minlen
&&
575 (!have_regex
|| regex
.find(s
.c_str())))
577 output_size
+= static_cast<int>(s
.size()) + 1;
578 if(limit_output
>= 0 && output_size
>= limit_output
)
583 strings
.push_back(s
);
586 // Reset the string to empty.
591 // Ignore CR character to make output always have UNIX newlines.
593 else if((c
>= 0x20 && c
< 0x7F) || c
== '\t' || c
== '\f' ||
594 (c
== '\n' && newline_consume
))
596 // This is an ASCII character that may be part of a string.
601 // This is a non-string character. Reset the string to emtpy.
605 // Terminate a string if the maximum length is reached.
606 if(maxlen
> 0 && s
.size() == maxlen
)
608 if(s
.length() >= minlen
&&
609 (!have_regex
|| regex
.find(s
.c_str())))
611 output_size
+= static_cast<int>(s
.size()) + 1;
612 if(limit_output
>= 0 && output_size
>= limit_output
)
617 strings
.push_back(s
);
623 // If there is a non-empty current string we have hit the end of the
624 // input file or the input size limit. Check if the current string
625 // matches the requirements.
626 if((!limit_count
|| strings
.size() < limit_count
) &&
627 !s
.empty() && s
.length() >= minlen
&&
628 (!have_regex
|| regex
.find(s
.c_str())))
630 output_size
+= static_cast<int>(s
.size()) + 1;
631 if(limit_output
< 0 || output_size
< limit_output
)
633 strings
.push_back(s
);
637 // Encode the result in a CMake list.
638 const char* sep
= "";
640 for(std::vector
<std::string
>::const_iterator si
= strings
.begin();
641 si
!= strings
.end(); ++si
)
643 // Separate the strings in the output to make it a list.
647 // Store the string in the output, but escape semicolons to
648 // make sure it is a list.
649 std::string
const& sr
= *si
;
650 for(unsigned int i
=0; i
< sr
.size(); ++i
)
660 // Save the output in a makefile variable.
661 this->Makefile
->AddDefinition(outVar
.c_str(), output
.c_str());
665 //----------------------------------------------------------------------------
666 bool cmFileCommand::HandleGlobCommand(std::vector
<std::string
> const& args
,
669 if ( args
.size() < 2 )
671 this->SetError("GLOB requires at least a variable name");
675 std::vector
<std::string
>::const_iterator i
= args
.begin();
677 i
++; // Get rid of subcommand
679 std::string variable
= *i
;
682 g
.SetRecurse(recurse
);
684 bool explicitFollowSymlinks
= false;
685 cmPolicies::PolicyStatus status
=
686 this->Makefile
->GetPolicyStatus(cmPolicies::CMP0009
);
691 case cmPolicies::NEW
:
692 g
.RecurseThroughSymlinksOff();
694 case cmPolicies::OLD
:
695 case cmPolicies::WARN
:
696 case cmPolicies::REQUIRED_IF_USED
:
697 case cmPolicies::REQUIRED_ALWAYS
:
698 g
.RecurseThroughSymlinksOn();
703 std::string output
= "";
705 for ( ; i
!= args
.end(); ++i
)
707 if ( recurse
&& (*i
== "FOLLOW_SYMLINKS") )
709 explicitFollowSymlinks
= true;
710 g
.RecurseThroughSymlinksOn();
712 if ( i
== args
.end() )
715 "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS");
720 if ( *i
== "RELATIVE" )
722 ++i
; // skip RELATIVE
723 if ( i
== args
.end() )
725 this->SetError("GLOB requires a directory after the RELATIVE tag");
728 g
.SetRelative(i
->c_str());
732 this->SetError("GLOB requires a glob expression after the directory");
737 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
739 std::string expr
= this->Makefile
->GetCurrentDirectory();
740 // Handle script mode
741 if ( expr
.size() > 0 )
756 std::vector
<std::string
>::size_type cc
;
757 std::vector
<std::string
>& files
= g
.GetFiles();
758 for ( cc
= 0; cc
< files
.size(); cc
++ )
769 if(recurse
&& !explicitFollowSymlinks
)
773 case cmPolicies::NEW
:
774 // Correct behavior, yay!
776 case cmPolicies::OLD
:
777 // Probably not really the expected behavior, but the author explicitly
778 // asked for the old behavior... no warning.
779 case cmPolicies::WARN
:
780 // Possibly unexpected old behavior *and* we actually traversed
781 // symlinks without being explicitly asked to: warn the author.
782 if(g
.GetFollowedSymlinkCount() != 0)
784 this->Makefile
->IssueMessage(cmake::AUTHOR_WARNING
,
785 this->Makefile
->GetPolicies()->
786 GetPolicyWarning(cmPolicies::CMP0009
));
789 case cmPolicies::REQUIRED_IF_USED
:
790 case cmPolicies::REQUIRED_ALWAYS
:
791 this->SetError("policy CMP0009 error");
792 this->Makefile
->IssueMessage(cmake::FATAL_ERROR
,
793 this->Makefile
->GetPolicies()->
794 GetRequiredPolicyError(cmPolicies::CMP0009
));
799 this->Makefile
->AddDefinition(variable
.c_str(), output
.c_str());
803 //----------------------------------------------------------------------------
804 bool cmFileCommand::HandleMakeDirectoryCommand(
805 std::vector
<std::string
> const& args
)
809 this->SetError("called with incorrect number of arguments");
813 std::vector
<std::string
>::const_iterator i
= args
.begin();
815 i
++; // Get rid of subcommand
818 for ( ; i
!= args
.end(); ++i
)
820 const std::string
* cdir
= &(*i
);
821 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
823 expr
= this->Makefile
->GetCurrentDirectory();
827 if ( !this->Makefile
->CanIWriteThisFile(cdir
->c_str()) )
829 std::string e
= "attempted to create a directory: " + *cdir
830 + " into a source directory.";
831 this->SetError(e
.c_str());
832 cmSystemTools::SetFatalErrorOccured();
835 if ( !cmSystemTools::MakeDirectory(cdir
->c_str()) )
837 std::string error
= "problem creating directory: " + *cdir
;
838 this->SetError(error
.c_str());
845 //----------------------------------------------------------------------------
847 cmFileCommand::HandleDifferentCommand(std::vector
<std::string
> const& args
)
850 FILE(DIFFERENT <variable> FILES <lhs> <rhs>)
853 // Evaluate arguments.
854 const char* file_lhs
= 0;
855 const char* file_rhs
= 0;
857 enum Doing
{ DoingNone
, DoingVar
, DoingFileLHS
, DoingFileRHS
};
858 Doing doing
= DoingVar
;
859 for(unsigned int i
=1; i
< args
.size(); ++i
)
861 if(args
[i
] == "FILES")
863 doing
= DoingFileLHS
;
865 else if(doing
== DoingVar
)
867 var
= args
[i
].c_str();
870 else if(doing
== DoingFileLHS
)
872 file_lhs
= args
[i
].c_str();
873 doing
= DoingFileRHS
;
875 else if(doing
== DoingFileRHS
)
877 file_rhs
= args
[i
].c_str();
883 e
<< "DIFFERENT given unknown argument " << args
[i
];
884 this->SetError(e
.str().c_str());
890 this->SetError("DIFFERENT not given result variable name.");
893 if(!file_lhs
|| !file_rhs
)
895 this->SetError("DIFFERENT not given FILES option with two file names.");
899 // Compare the files.
901 cmSystemTools::FilesDiffer(file_lhs
, file_rhs
)? "1" : "0";
902 this->Makefile
->AddDefinition(var
, result
);
906 //----------------------------------------------------------------------------
907 // File installation helper class.
910 cmFileCopier(cmFileCommand
* command
, const char* name
= "COPY"):
911 FileCommand(command
),
912 Makefile(command
->GetMakefile()),
915 MatchlessFiles(true),
919 UseGivenPermissionsFile(false),
920 UseGivenPermissionsDir(false),
921 UseSourcePermissions(true),
925 virtual ~cmFileCopier() {}
927 bool Run(std::vector
<std::string
> const& args
);
930 cmFileCommand
* FileCommand
;
931 cmMakefile
* Makefile
;
934 cmFileTimeComparison FileTimes
;
936 // Whether to install a file not matching any expression.
939 // Permissions for files and directories installed by this object.
940 mode_t FilePermissions
;
941 mode_t DirPermissions
;
943 // Properties set by pattern and regex match rules.
944 struct MatchProperties
948 MatchProperties(): Exclude(false), Permissions(0) {}
951 friend struct MatchRule
;
954 cmsys::RegularExpression Regex
;
955 MatchProperties Properties
;
956 std::string RegexString
;
957 MatchRule(std::string
const& regex
):
958 Regex(regex
.c_str()), RegexString(regex
) {}
960 std::vector
<MatchRule
> MatchRules
;
962 // Get the properties from rules matching this input file.
963 MatchProperties
CollectMatchProperties(const char* file
)
965 // Match rules are case-insensitive on some platforms.
966 #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
967 std::string lower
= cmSystemTools::LowerCase(file
);
968 file
= lower
.c_str();
971 // Collect properties from all matching rules.
972 bool matched
= false;
973 MatchProperties result
;
974 for(std::vector
<MatchRule
>::iterator mr
= this->MatchRules
.begin();
975 mr
!= this->MatchRules
.end(); ++mr
)
977 if(mr
->Regex
.find(file
))
980 result
.Exclude
|= mr
->Properties
.Exclude
;
981 result
.Permissions
|= mr
->Properties
.Permissions
;
984 if(!matched
&& !this->MatchlessFiles
)
986 result
.Exclude
= !cmSystemTools::FileIsDirectory(file
);
991 bool SetPermissions(const char* toFile
, mode_t permissions
)
993 if(permissions
&& !cmSystemTools::SetPermissions(toFile
, permissions
))
996 e
<< this->Name
<< " cannot set permissions on \"" << toFile
<< "\"";
997 this->FileCommand
->SetError(e
.str().c_str());
1003 // Translate an argument to a permissions bit.
1004 bool CheckPermissions(std::string
const& arg
, mode_t
& permissions
)
1006 if(arg
== "OWNER_READ") { permissions
|= mode_owner_read
; }
1007 else if(arg
== "OWNER_WRITE") { permissions
|= mode_owner_write
; }
1008 else if(arg
== "OWNER_EXECUTE") { permissions
|= mode_owner_execute
; }
1009 else if(arg
== "GROUP_READ") { permissions
|= mode_group_read
; }
1010 else if(arg
== "GROUP_WRITE") { permissions
|= mode_group_write
; }
1011 else if(arg
== "GROUP_EXECUTE") { permissions
|= mode_group_execute
; }
1012 else if(arg
== "WORLD_READ") { permissions
|= mode_world_read
; }
1013 else if(arg
== "WORLD_WRITE") { permissions
|= mode_world_write
; }
1014 else if(arg
== "WORLD_EXECUTE") { permissions
|= mode_world_execute
; }
1015 else if(arg
== "SETUID") { permissions
|= mode_setuid
; }
1016 else if(arg
== "SETGID") { permissions
|= mode_setgid
; }
1020 e
<< this->Name
<< " given invalid permission \"" << arg
<< "\".";
1021 this->FileCommand
->SetError(e
.str().c_str());
1027 bool InstallSymlink(const char* fromFile
, const char* toFile
);
1028 bool InstallFile(const char* fromFile
, const char* toFile
,
1029 MatchProperties
const& match_properties
);
1030 bool InstallDirectory(const char* source
, const char* destination
,
1031 MatchProperties
const& match_properties
);
1032 virtual bool Install(const char* fromFile
, const char* toFile
);
1033 virtual std::string
const& ToName(std::string
const& fromName
)
1034 { return fromName
; }
1042 virtual void ReportCopy(const char*, Type
, bool) {}
1043 virtual bool ReportMissing(const char* fromFile
)
1045 // The input file does not exist and installation is not optional.
1047 e
<< this->Name
<< " cannot find \"" << fromFile
<< "\".";
1048 this->FileCommand
->SetError(e
.str().c_str());
1052 MatchRule
* CurrentMatchRule
;
1053 bool UseGivenPermissionsFile
;
1054 bool UseGivenPermissionsDir
;
1055 bool UseSourcePermissions
;
1056 std::string Destination
;
1057 std::vector
<std::string
> Files
;
1060 virtual bool Parse(std::vector
<std::string
> const& args
);
1069 DoingPermissionsFile
,
1070 DoingPermissionsDir
,
1071 DoingPermissionsMatch
,
1074 virtual bool CheckKeyword(std::string
const& arg
);
1075 virtual bool CheckValue(std::string
const& arg
);
1077 void NotBeforeMatch(std::string
const& arg
)
1080 e
<< "option " << arg
<< " may not appear before PATTERN or REGEX.";
1081 this->FileCommand
->SetError(e
.str().c_str());
1082 this->Doing
= DoingError
;
1084 void NotAfterMatch(std::string
const& arg
)
1087 e
<< "option " << arg
<< " may not appear after PATTERN or REGEX.";
1088 this->FileCommand
->SetError(e
.str().c_str());
1089 this->Doing
= DoingError
;
1091 virtual void DefaultFilePermissions()
1093 // Use read/write permissions.
1094 this->FilePermissions
= 0;
1095 this->FilePermissions
|= mode_owner_read
;
1096 this->FilePermissions
|= mode_owner_write
;
1097 this->FilePermissions
|= mode_group_read
;
1098 this->FilePermissions
|= mode_world_read
;
1100 virtual void DefaultDirectoryPermissions()
1102 // Use read/write/executable permissions.
1103 this->DirPermissions
= 0;
1104 this->DirPermissions
|= mode_owner_read
;
1105 this->DirPermissions
|= mode_owner_write
;
1106 this->DirPermissions
|= mode_owner_execute
;
1107 this->DirPermissions
|= mode_group_read
;
1108 this->DirPermissions
|= mode_group_execute
;
1109 this->DirPermissions
|= mode_world_read
;
1110 this->DirPermissions
|= mode_world_execute
;
1114 //----------------------------------------------------------------------------
1115 bool cmFileCopier::Parse(std::vector
<std::string
> const& args
)
1117 this->Doing
= DoingFiles
;
1118 for(unsigned int i
=1; i
< args
.size(); ++i
)
1120 // Check this argument.
1121 if(!this->CheckKeyword(args
[i
]) &&
1122 !this->CheckValue(args
[i
]))
1125 e
<< "called with unknown argument \"" << args
[i
] << "\".";
1126 this->FileCommand
->SetError(e
.str().c_str());
1130 // Quit if an argument is invalid.
1131 if(this->Doing
== DoingError
)
1137 // Require a destination.
1138 if(this->Destination
.empty())
1141 e
<< this->Name
<< " given no DESTINATION";
1142 this->FileCommand
->SetError(e
.str().c_str());
1146 // If file permissions were not specified set default permissions.
1147 if(!this->UseGivenPermissionsFile
&& !this->UseSourcePermissions
)
1149 this->DefaultFilePermissions();
1152 // If directory permissions were not specified set default permissions.
1153 if(!this->UseGivenPermissionsDir
&& !this->UseSourcePermissions
)
1155 this->DefaultDirectoryPermissions();
1161 //----------------------------------------------------------------------------
1162 bool cmFileCopier::CheckKeyword(std::string
const& arg
)
1164 if(arg
== "DESTINATION")
1166 if(this->CurrentMatchRule
)
1168 this->NotAfterMatch(arg
);
1172 this->Doing
= DoingDestination
;
1175 else if(arg
== "PATTERN")
1177 this->Doing
= DoingPattern
;
1179 else if(arg
== "REGEX")
1181 this->Doing
= DoingRegex
;
1183 else if(arg
== "EXCLUDE")
1185 // Add this property to the current match rule.
1186 if(this->CurrentMatchRule
)
1188 this->CurrentMatchRule
->Properties
.Exclude
= true;
1189 this->Doing
= DoingNone
;
1193 this->NotBeforeMatch(arg
);
1196 else if(arg
== "PERMISSIONS")
1198 if(this->CurrentMatchRule
)
1200 this->Doing
= DoingPermissionsMatch
;
1204 this->NotBeforeMatch(arg
);
1207 else if(arg
== "FILE_PERMISSIONS")
1209 if(this->CurrentMatchRule
)
1211 this->NotAfterMatch(arg
);
1215 this->Doing
= DoingPermissionsFile
;
1216 this->UseGivenPermissionsFile
= true;
1219 else if(arg
== "DIRECTORY_PERMISSIONS")
1221 if(this->CurrentMatchRule
)
1223 this->NotAfterMatch(arg
);
1227 this->Doing
= DoingPermissionsDir
;
1228 this->UseGivenPermissionsDir
= true;
1231 else if(arg
== "USE_SOURCE_PERMISSIONS")
1233 if(this->CurrentMatchRule
)
1235 this->NotAfterMatch(arg
);
1239 this->Doing
= DoingNone
;
1240 this->UseSourcePermissions
= true;
1243 else if(arg
== "NO_SOURCE_PERMISSIONS")
1245 if(this->CurrentMatchRule
)
1247 this->NotAfterMatch(arg
);
1251 this->Doing
= DoingNone
;
1252 this->UseSourcePermissions
= false;
1255 else if(arg
== "FILES_MATCHING")
1257 if(this->CurrentMatchRule
)
1259 this->NotAfterMatch(arg
);
1263 this->Doing
= DoingNone
;
1264 this->MatchlessFiles
= false;
1274 //----------------------------------------------------------------------------
1275 bool cmFileCopier::CheckValue(std::string
const& arg
)
1280 if(arg
.empty() || cmSystemTools::FileIsFullPath(arg
.c_str()))
1282 this->Files
.push_back(arg
);
1286 std::string file
= this->Makefile
->GetCurrentDirectory();
1288 this->Files
.push_back(file
);
1291 case DoingDestination
:
1292 if(arg
.empty() || cmSystemTools::FileIsFullPath(arg
.c_str()))
1294 this->Destination
= arg
;
1298 this->Destination
= this->Makefile
->GetCurrentOutputDirectory();
1299 this->Destination
+= "/" + arg
;
1301 this->Doing
= DoingNone
;
1305 // Convert the pattern to a regular expression. Require a
1306 // leading slash and trailing end-of-string in the matched
1307 // string to make sure the pattern matches only whole file
1309 std::string regex
= "/";
1310 regex
+= cmsys::Glob::PatternToRegex(arg
, false);
1312 this->MatchRules
.push_back(MatchRule(regex
));
1313 this->CurrentMatchRule
= &*(this->MatchRules
.end()-1);
1314 if(this->CurrentMatchRule
->Regex
.is_valid())
1316 this->Doing
= DoingNone
;
1321 e
<< "could not compile PATTERN \"" << arg
<< "\".";
1322 this->FileCommand
->SetError(e
.str().c_str());
1323 this->Doing
= DoingError
;
1328 this->MatchRules
.push_back(MatchRule(arg
));
1329 this->CurrentMatchRule
= &*(this->MatchRules
.end()-1);
1330 if(this->CurrentMatchRule
->Regex
.is_valid())
1332 this->Doing
= DoingNone
;
1337 e
<< "could not compile REGEX \"" << arg
<< "\".";
1338 this->FileCommand
->SetError(e
.str().c_str());
1339 this->Doing
= DoingError
;
1342 case DoingPermissionsFile
:
1343 if(!this->CheckPermissions(arg
, this->FilePermissions
))
1345 this->Doing
= DoingError
;
1348 case DoingPermissionsDir
:
1349 if(!this->CheckPermissions(arg
, this->DirPermissions
))
1351 this->Doing
= DoingError
;
1354 case DoingPermissionsMatch
:
1355 if(!this->CheckPermissions(
1356 arg
, this->CurrentMatchRule
->Properties
.Permissions
))
1358 this->Doing
= DoingError
;
1367 //----------------------------------------------------------------------------
1368 bool cmFileCopier::Run(std::vector
<std::string
> const& args
)
1370 if(!this->Parse(args
))
1375 std::vector
<std::string
> const& files
= this->Files
;
1376 for(std::vector
<std::string
>::size_type i
= 0; i
< files
.size(); ++i
)
1378 // Split the input file into its directory and name components.
1379 std::vector
<std::string
> fromPathComponents
;
1380 cmSystemTools::SplitPath(files
[i
].c_str(), fromPathComponents
);
1381 std::string fromName
= *(fromPathComponents
.end()-1);
1382 std::string fromDir
= cmSystemTools::JoinPath(fromPathComponents
.begin(),
1383 fromPathComponents
.end()-1);
1385 // Compute the full path to the destination file.
1386 std::string toFile
= this->Destination
;
1387 std::string
const& toName
= this->ToName(fromName
);
1394 // Construct the full path to the source file. The file name may
1395 // have been changed above.
1396 std::string fromFile
= fromDir
;
1397 if(!fromName
.empty())
1400 fromFile
+= fromName
;
1403 if(!this->Install(fromFile
.c_str(), toFile
.c_str()))
1411 //----------------------------------------------------------------------------
1412 bool cmFileCopier::Install(const char* fromFile
, const char* toFile
)
1417 e
<< "INSTALL encountered an empty string input file name.";
1418 this->FileCommand
->SetError(e
.str().c_str());
1422 // Collect any properties matching this file name.
1423 MatchProperties match_properties
= this->CollectMatchProperties(fromFile
);
1425 // Skip the file if it is excluded.
1426 if(match_properties
.Exclude
)
1431 if(cmSystemTools::SameFile(fromFile
, toFile
))
1435 else if(cmSystemTools::FileIsSymlink(fromFile
))
1437 return this->InstallSymlink(fromFile
, toFile
);
1439 else if(cmSystemTools::FileIsDirectory(fromFile
))
1441 return this->InstallDirectory(fromFile
, toFile
, match_properties
);
1443 else if(cmSystemTools::FileExists(fromFile
))
1445 return this->InstallFile(fromFile
, toFile
, match_properties
);
1447 return this->ReportMissing(fromFile
);
1450 //----------------------------------------------------------------------------
1451 bool cmFileCopier::InstallSymlink(const char* fromFile
, const char* toFile
)
1453 // Read the original symlink.
1454 std::string symlinkTarget
;
1455 if(!cmSystemTools::ReadSymlink(fromFile
, symlinkTarget
))
1458 e
<< this->Name
<< " cannot read symlink \"" << fromFile
1459 << "\" to duplicate at \"" << toFile
<< "\".";
1460 this->FileCommand
->SetError(e
.str().c_str());
1464 // Compare the symlink value to that at the destination if not
1465 // always installing.
1469 std::string oldSymlinkTarget
;
1470 if(cmSystemTools::ReadSymlink(toFile
, oldSymlinkTarget
))
1472 if(symlinkTarget
== oldSymlinkTarget
)
1479 // Inform the user about this file installation.
1480 this->ReportCopy(toFile
, TypeLink
, copy
);
1484 // Remove the destination file so we can always create the symlink.
1485 cmSystemTools::RemoveFile(toFile
);
1487 // Create the symlink.
1488 if(!cmSystemTools::CreateSymlink(symlinkTarget
.c_str(), toFile
))
1491 e
<< this->Name
<< " cannot duplicate symlink \"" << fromFile
1492 << "\" at \"" << toFile
<< "\".";
1493 this->FileCommand
->SetError(e
.str().c_str());
1501 //----------------------------------------------------------------------------
1502 bool cmFileCopier::InstallFile(const char* fromFile
, const char* toFile
,
1503 MatchProperties
const& match_properties
)
1505 // Determine whether we will copy the file.
1509 // If both files exist with the same time do not copy.
1510 if(!this->FileTimes
.FileTimesDiffer(fromFile
, toFile
))
1516 // Inform the user about this file installation.
1517 this->ReportCopy(toFile
, TypeFile
, copy
);
1520 if(copy
&& !cmSystemTools::CopyAFile(fromFile
, toFile
, true, false))
1523 e
<< this->Name
<< " cannot copy file \"" << fromFile
1524 << "\" to \"" << toFile
<< "\".";
1525 this->FileCommand
->SetError(e
.str().c_str());
1529 // Set the file modification time of the destination file.
1530 if(copy
&& !this->Always
)
1532 if (!cmSystemTools::CopyFileTime(fromFile
, toFile
))
1535 e
<< this->Name
<< " cannot set modification time on \""
1537 this->FileCommand
->SetError(e
.str().c_str());
1542 // Set permissions of the destination file.
1543 mode_t permissions
= (match_properties
.Permissions
?
1544 match_properties
.Permissions
: this->FilePermissions
);
1547 // No permissions were explicitly provided but the user requested
1548 // that the source file permissions be used.
1549 cmSystemTools::GetPermissions(fromFile
, permissions
);
1551 return this->SetPermissions(toFile
, permissions
);
1554 //----------------------------------------------------------------------------
1555 bool cmFileCopier::InstallDirectory(const char* source
,
1556 const char* destination
,
1557 MatchProperties
const& match_properties
)
1559 // Inform the user about this directory installation.
1560 this->ReportCopy(destination
, TypeDir
, true);
1562 // Make sure the destination directory exists.
1563 if(!cmSystemTools::MakeDirectory(destination
))
1566 e
<< this->Name
<< " cannot make directory \"" << destination
<< "\": "
1567 << cmSystemTools::GetLastSystemError();
1568 this->FileCommand
->SetError(e
.str().c_str());
1572 // Compute the requested permissions for the destination directory.
1573 mode_t permissions
= (match_properties
.Permissions
?
1574 match_properties
.Permissions
: this->DirPermissions
);
1577 // No permissions were explicitly provided but the user requested
1578 // that the source directory permissions be used.
1579 cmSystemTools::GetPermissions(source
, permissions
);
1582 // Compute the set of permissions required on this directory to
1583 // recursively install files and subdirectories safely.
1584 mode_t required_permissions
=
1585 mode_owner_read
| mode_owner_write
| mode_owner_execute
;
1587 // If the required permissions are specified it is safe to set the
1588 // final permissions now. Otherwise we must add the required
1589 // permissions temporarily during file installation.
1590 mode_t permissions_before
= 0;
1591 mode_t permissions_after
= 0;
1592 if((permissions
& required_permissions
) == required_permissions
)
1594 permissions_before
= permissions
;
1598 permissions_before
= permissions
| required_permissions
;
1599 permissions_after
= permissions
;
1602 // Set the required permissions of the destination directory.
1603 if(!this->SetPermissions(destination
, permissions_before
))
1608 // Load the directory contents to traverse it recursively.
1609 cmsys::Directory dir
;
1610 if(source
&& *source
)
1614 unsigned long numFiles
= static_cast<unsigned long>(dir
.GetNumberOfFiles());
1615 for(unsigned long fileNum
= 0; fileNum
< numFiles
; ++fileNum
)
1617 if(!(strcmp(dir
.GetFile(fileNum
), ".") == 0 ||
1618 strcmp(dir
.GetFile(fileNum
), "..") == 0))
1620 cmsys_stl::string fromPath
= source
;
1622 fromPath
+= dir
.GetFile(fileNum
);
1623 std::string toPath
= destination
;
1625 toPath
+= dir
.GetFile(fileNum
);
1626 if(!this->Install(fromPath
.c_str(), toPath
.c_str()))
1633 // Set the requested permissions of the destination directory.
1634 return this->SetPermissions(destination
, permissions_after
);
1637 //----------------------------------------------------------------------------
1638 bool cmFileCommand::HandleCopyCommand(std::vector
<std::string
> const& args
)
1640 cmFileCopier
copier(this);
1641 return copier
.Run(args
);
1644 //----------------------------------------------------------------------------
1645 struct cmFileInstaller
: public cmFileCopier
1647 cmFileInstaller(cmFileCommand
* command
):
1648 cmFileCopier(command
, "INSTALL"),
1649 InstallType(cmTarget::INSTALL_FILES
),
1653 // Installation does not use source permissions by default.
1654 this->UseSourcePermissions
= false;
1655 // Check whether to copy files always or only if they have changed.
1657 cmSystemTools::IsOn(cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS"));
1658 // Get the current manifest.
1660 this->Makefile
->GetSafeDefinition("CMAKE_INSTALL_MANIFEST_FILES");
1664 // Save the updated install manifest.
1665 this->Makefile
->AddDefinition("CMAKE_INSTALL_MANIFEST_FILES",
1666 this->Manifest
.c_str());
1670 cmTarget::TargetType InstallType
;
1675 std::string Manifest
;
1676 void ManifestAppend(std::string
const& file
)
1678 this->Manifest
+= ";";
1679 this->Manifest
+= file
.substr(this->DestDirLength
);
1682 virtual std::string
const& ToName(std::string
const& fromName
)
1683 { return this->Rename
.empty()? fromName
: this->Rename
; }
1685 virtual void ReportCopy(const char* toFile
, Type type
, bool copy
)
1687 std::string message
= (copy
? "Installing: " : "Up-to-date: ");
1689 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1692 // Add the file to the manifest.
1693 this->ManifestAppend(toFile
);
1696 virtual bool ReportMissing(const char* fromFile
)
1698 return (this->Optional
||
1699 this->cmFileCopier::ReportMissing(fromFile
));
1701 virtual bool Install(const char* fromFile
, const char* toFile
)
1703 // Support installing from empty source to make a directory.
1704 if(this->InstallType
== cmTarget::INSTALL_DIRECTORY
&& !*fromFile
)
1706 return this->InstallDirectory(fromFile
, toFile
, MatchProperties());
1708 return this->cmFileCopier::Install(fromFile
, toFile
);
1711 virtual bool Parse(std::vector
<std::string
> const& args
);
1714 DoingType
= DoingLast1
,
1718 virtual bool CheckKeyword(std::string
const& arg
);
1719 virtual bool CheckValue(std::string
const& arg
);
1720 virtual void DefaultFilePermissions()
1722 this->cmFileCopier::DefaultFilePermissions();
1723 // Add execute permissions based on the target type.
1724 switch(this->InstallType
)
1726 case cmTarget::SHARED_LIBRARY
:
1727 case cmTarget::MODULE_LIBRARY
:
1728 if(this->Makefile
->IsOn("CMAKE_INSTALL_SO_NO_EXE"))
1732 case cmTarget::EXECUTABLE
:
1733 case cmTarget::INSTALL_PROGRAMS
:
1734 this->FilePermissions
|= mode_owner_execute
;
1735 this->FilePermissions
|= mode_group_execute
;
1736 this->FilePermissions
|= mode_world_execute
;
1741 bool GetTargetTypeFromString(const std::string
& stype
);
1742 bool HandleInstallDestination();
1745 //----------------------------------------------------------------------------
1746 bool cmFileInstaller::Parse(std::vector
<std::string
> const& args
)
1748 if(!this->cmFileCopier::Parse(args
))
1753 if(!this->Rename
.empty())
1755 if(this->InstallType
!= cmTarget::INSTALL_FILES
&&
1756 this->InstallType
!= cmTarget::INSTALL_PROGRAMS
)
1758 this->FileCommand
->SetError("INSTALL option RENAME may be used "
1759 "only with FILES or PROGRAMS.");
1762 if(this->Files
.size() > 1)
1764 this->FileCommand
->SetError("INSTALL option RENAME may be used "
1765 "only with one file.");
1770 if(!this->HandleInstallDestination())
1778 //----------------------------------------------------------------------------
1779 bool cmFileInstaller::CheckKeyword(std::string
const& arg
)
1783 if(this->CurrentMatchRule
)
1785 this->NotAfterMatch(arg
);
1789 this->Doing
= DoingType
;
1792 else if(arg
== "FILES")
1794 if(this->CurrentMatchRule
)
1796 this->NotAfterMatch(arg
);
1800 this->Doing
= DoingFiles
;
1803 else if(arg
== "RENAME")
1805 if(this->CurrentMatchRule
)
1807 this->NotAfterMatch(arg
);
1811 this->Doing
= DoingRename
;
1814 else if(arg
== "OPTIONAL")
1816 if(this->CurrentMatchRule
)
1818 this->NotAfterMatch(arg
);
1822 this->Doing
= DoingNone
;
1823 this->Optional
= true;
1826 else if(arg
== "PERMISSIONS")
1828 if(this->CurrentMatchRule
)
1830 this->Doing
= DoingPermissionsMatch
;
1834 // file(INSTALL) aliases PERMISSIONS to FILE_PERMISSIONS
1835 this->Doing
= DoingPermissionsFile
;
1836 this->UseGivenPermissionsFile
= true;
1839 else if(arg
== "DIR_PERMISSIONS")
1841 if(this->CurrentMatchRule
)
1843 this->NotAfterMatch(arg
);
1847 // file(INSTALL) aliases DIR_PERMISSIONS to DIRECTORY_PERMISSIONS
1848 this->Doing
= DoingPermissionsDir
;
1849 this->UseGivenPermissionsDir
= true;
1852 else if(arg
== "COMPONENTS" || arg
== "CONFIGURATIONS" ||
1853 arg
== "PROPERTIES")
1855 if(this->Makefile
->IsOn("CMAKE_INSTALL_SELF_2_4"))
1857 // When CMake 2.4 builds this CMake version we need to support
1858 // the install scripts it generates since it asks this CMake
1859 // to install itself using the rules it generated.
1860 this->Doing
= DoingSelf24
;
1865 e
<< "INSTALL called with old-style " << arg
<< " argument. "
1866 << "This script was generated with an older version of CMake. "
1867 << "Re-run this cmake version on your build tree.";
1868 this->FileCommand
->SetError(e
.str().c_str());
1869 this->Doing
= DoingError
;
1874 return this->cmFileCopier::CheckKeyword(arg
);
1879 //----------------------------------------------------------------------------
1880 bool cmFileInstaller::CheckValue(std::string
const& arg
)
1885 if(!this->GetTargetTypeFromString(arg
))
1887 this->Doing
= DoingError
;
1894 // Ignore these arguments for compatibility. This should be
1895 // reached only when CMake 2.4 is installing the current
1896 // CMake. It can be removed when CMake 2.6 or higher is
1897 // required to build CMake.
1900 return this->cmFileCopier::CheckValue(arg
);
1905 //----------------------------------------------------------------------------
1906 bool cmFileInstaller
1907 ::GetTargetTypeFromString(const std::string
& stype
)
1909 if ( stype
== "EXECUTABLE" )
1911 this->InstallType
= cmTarget::EXECUTABLE
;
1913 else if ( stype
== "FILE" )
1915 this->InstallType
= cmTarget::INSTALL_FILES
;
1917 else if ( stype
== "PROGRAM" )
1919 this->InstallType
= cmTarget::INSTALL_PROGRAMS
;
1921 else if ( stype
== "STATIC_LIBRARY" )
1923 this->InstallType
= cmTarget::STATIC_LIBRARY
;
1925 else if ( stype
== "SHARED_LIBRARY" )
1927 this->InstallType
= cmTarget::SHARED_LIBRARY
;
1929 else if ( stype
== "MODULE" )
1931 this->InstallType
= cmTarget::MODULE_LIBRARY
;
1933 else if ( stype
== "DIRECTORY" )
1935 this->InstallType
= cmTarget::INSTALL_DIRECTORY
;
1940 e
<< "Option TYPE given uknown value \"" << stype
<< "\".";
1941 this->FileCommand
->SetError(e
.str().c_str());
1947 //----------------------------------------------------------------------------
1948 bool cmFileInstaller::HandleInstallDestination()
1950 std::string
& destination
= this->Destination
;
1952 // allow for / to be a valid destination
1953 if ( destination
.size() < 2 && destination
!= "/" )
1955 this->FileCommand
->SetError("called with inapropriate arguments. "
1956 "No DESTINATION provided or .");
1960 const char* destdir
= cmSystemTools::GetEnv("DESTDIR");
1961 if ( destdir
&& *destdir
)
1963 std::string sdestdir
= destdir
;
1964 cmSystemTools::ConvertToUnixSlashes(sdestdir
);
1965 char ch1
= destination
[0];
1966 char ch2
= destination
[1];
1968 if ( destination
.size() > 2 )
1970 ch3
= destination
[2];
1976 if (((ch1
>= 'a' && ch1
<= 'z') || (ch1
>= 'A' && ch1
<= 'Z')) &&
1980 // let's do some destdir magic:
1993 // This is relative path on unix or windows. Since we are doing
1994 // destdir, this case does not make sense.
1995 this->FileCommand
->SetError(
1996 "called with relative DESTINATION. This "
1997 "does not make sense when using DESTDIR. Specify "
1998 "absolute path or remove DESTDIR environment variable.");
2006 // looks like a network path.
2007 std::string message
= "called with network path DESTINATION. This "
2008 "does not make sense when using DESTDIR. Specify local "
2009 "absolute path or remove DESTDIR environment variable."
2011 message
+= destination
;
2012 this->FileCommand
->SetError(message
.c_str());
2016 destination
= sdestdir
+ (destination
.c_str() + skip
);
2017 this->DestDirLength
= int(sdestdir
.size());
2020 if ( !cmSystemTools::FileExists(destination
.c_str()) )
2022 if ( !cmSystemTools::MakeDirectory(destination
.c_str()) )
2024 std::string errstring
= "cannot create directory: " + destination
+
2025 ". Maybe need administrative privileges.";
2026 this->FileCommand
->SetError(errstring
.c_str());
2030 if ( !cmSystemTools::FileIsDirectory(destination
.c_str()) )
2032 std::string errstring
= "INSTALL destination: " + destination
+
2033 " is not a directory.";
2034 this->FileCommand
->SetError(errstring
.c_str());
2040 //----------------------------------------------------------------------------
2042 cmFileCommand::HandleRPathChangeCommand(std::vector
<std::string
> const& args
)
2044 // Evaluate arguments.
2045 const char* file
= 0;
2046 const char* oldRPath
= 0;
2047 const char* newRPath
= 0;
2048 enum Doing
{ DoingNone
, DoingFile
, DoingOld
, DoingNew
};
2049 Doing doing
= DoingNone
;
2050 for(unsigned int i
=1; i
< args
.size(); ++i
)
2052 if(args
[i
] == "OLD_RPATH")
2056 else if(args
[i
] == "NEW_RPATH")
2060 else if(args
[i
] == "FILE")
2064 else if(doing
== DoingFile
)
2066 file
= args
[i
].c_str();
2069 else if(doing
== DoingOld
)
2071 oldRPath
= args
[i
].c_str();
2074 else if(doing
== DoingNew
)
2076 newRPath
= args
[i
].c_str();
2082 e
<< "RPATH_CHANGE given unknown argument " << args
[i
];
2083 this->SetError(e
.str().c_str());
2089 this->SetError("RPATH_CHANGE not given FILE option.");
2094 this->SetError("RPATH_CHANGE not given OLD_RPATH option.");
2099 this->SetError("RPATH_CHANGE not given NEW_RPATH option.");
2102 if(!cmSystemTools::FileExists(file
, true))
2105 e
<< "RPATH_CHANGE given FILE \"" << file
<< "\" that does not exist.";
2106 this->SetError(e
.str().c_str());
2109 bool success
= true;
2110 cmSystemToolsFileTime
* ft
= cmSystemTools::FileTimeNew();
2111 bool have_ft
= cmSystemTools::FileTimeGet(file
, ft
);
2114 if(!cmSystemTools::ChangeRPath(file
, oldRPath
, newRPath
, &emsg
, &changed
))
2117 e
<< "RPATH_CHANGE could not write new RPATH:\n"
2118 << " " << newRPath
<< "\n"
2120 << " " << file
<< "\n"
2122 this->SetError(e
.str().c_str());
2129 std::string message
= "Set runtime path of \"";
2131 message
+= "\" to \"";
2132 message
+= newRPath
;
2134 this->Makefile
->DisplayStatus(message
.c_str(), -1);
2138 cmSystemTools::FileTimeSet(file
, ft
);
2141 cmSystemTools::FileTimeDelete(ft
);
2145 //----------------------------------------------------------------------------
2147 cmFileCommand::HandleRPathRemoveCommand(std::vector
<std::string
> const& args
)
2149 // Evaluate arguments.
2150 const char* file
= 0;
2151 enum Doing
{ DoingNone
, DoingFile
};
2152 Doing doing
= DoingNone
;
2153 for(unsigned int i
=1; i
< args
.size(); ++i
)
2155 if(args
[i
] == "FILE")
2159 else if(doing
== DoingFile
)
2161 file
= args
[i
].c_str();
2167 e
<< "RPATH_REMOVE given unknown argument " << args
[i
];
2168 this->SetError(e
.str().c_str());
2174 this->SetError("RPATH_REMOVE not given FILE option.");
2177 if(!cmSystemTools::FileExists(file
, true))
2180 e
<< "RPATH_REMOVE given FILE \"" << file
<< "\" that does not exist.";
2181 this->SetError(e
.str().c_str());
2184 bool success
= true;
2185 cmSystemToolsFileTime
* ft
= cmSystemTools::FileTimeNew();
2186 bool have_ft
= cmSystemTools::FileTimeGet(file
, ft
);
2189 if(!cmSystemTools::RemoveRPath(file
, &emsg
, &removed
))
2192 e
<< "RPATH_REMOVE could not remove RPATH from file:\n"
2193 << " " << file
<< "\n"
2195 this->SetError(e
.str().c_str());
2202 std::string message
= "Removed runtime path from \"";
2205 this->Makefile
->DisplayStatus(message
.c_str(), -1);
2209 cmSystemTools::FileTimeSet(file
, ft
);
2212 cmSystemTools::FileTimeDelete(ft
);
2216 //----------------------------------------------------------------------------
2218 cmFileCommand::HandleRPathCheckCommand(std::vector
<std::string
> const& args
)
2220 // Evaluate arguments.
2221 const char* file
= 0;
2222 const char* rpath
= 0;
2223 enum Doing
{ DoingNone
, DoingFile
, DoingRPath
};
2224 Doing doing
= DoingNone
;
2225 for(unsigned int i
=1; i
< args
.size(); ++i
)
2227 if(args
[i
] == "RPATH")
2231 else if(args
[i
] == "FILE")
2235 else if(doing
== DoingFile
)
2237 file
= args
[i
].c_str();
2240 else if(doing
== DoingRPath
)
2242 rpath
= args
[i
].c_str();
2248 e
<< "RPATH_CHECK given unknown argument " << args
[i
];
2249 this->SetError(e
.str().c_str());
2255 this->SetError("RPATH_CHECK not given FILE option.");
2260 this->SetError("RPATH_CHECK not given RPATH option.");
2264 // If the file exists but does not have the desired RPath then
2265 // delete it. This is used during installation to re-install a file
2266 // if its RPath will change.
2267 if(cmSystemTools::FileExists(file
, true) &&
2268 !cmSystemTools::CheckRPath(file
, rpath
))
2270 cmSystemTools::RemoveFile(file
);
2276 //----------------------------------------------------------------------------
2277 bool cmFileCommand::HandleInstallCommand(std::vector
<std::string
> const& args
)
2279 cmFileInstaller
installer(this);
2280 return installer
.Run(args
);
2283 //----------------------------------------------------------------------------
2284 bool cmFileCommand::HandleRelativePathCommand(
2285 std::vector
<std::string
> const& args
)
2287 if(args
.size() != 4 )
2289 this->SetError("called with incorrect number of arguments");
2293 const std::string
& outVar
= args
[1];
2294 const std::string
& directoryName
= args
[2];
2295 const std::string
& fileName
= args
[3];
2297 if(!cmSystemTools::FileIsFullPath(directoryName
.c_str()))
2299 std::string errstring
=
2300 "RelativePath must be passed a full path to the directory: "
2302 this->SetError(errstring
.c_str());
2305 if(!cmSystemTools::FileIsFullPath(fileName
.c_str()))
2307 std::string errstring
=
2308 "RelativePath must be passed a full path to the file: "
2310 this->SetError(errstring
.c_str());
2314 std::string res
= cmSystemTools::RelativePath(directoryName
.c_str(),
2316 this->Makefile
->AddDefinition(outVar
.c_str(),
2322 //----------------------------------------------------------------------------
2323 bool cmFileCommand::HandleRename(std::vector
<std::string
> const& args
)
2325 if(args
.size() != 3)
2327 this->SetError("given incorrect number of arguments.");
2331 // Compute full path for old and new names.
2332 std::string oldname
= args
[1];
2333 if(!cmsys::SystemTools::FileIsFullPath(oldname
.c_str()))
2335 oldname
= this->Makefile
->GetCurrentDirectory();
2336 oldname
+= "/" + args
[1];
2338 std::string newname
= args
[2];
2339 if(!cmsys::SystemTools::FileIsFullPath(newname
.c_str()))
2341 newname
= this->Makefile
->GetCurrentDirectory();
2342 newname
+= "/" + args
[2];
2345 if(!cmSystemTools::RenameFile(oldname
.c_str(), newname
.c_str()))
2347 std::string err
= cmSystemTools::GetLastSystemError();
2349 e
<< "RENAME failed to rename\n"
2350 << " " << oldname
<< "\n"
2352 << " " << newname
<< "\n"
2353 << "because: " << err
<< "\n";
2354 this->SetError(e
.str().c_str());
2361 //----------------------------------------------------------------------------
2362 bool cmFileCommand::HandleRemove(std::vector
<std::string
> const& args
,
2366 std::string message
;
2367 std::vector
<std::string
>::const_iterator i
= args
.begin();
2369 i
++; // Get rid of subcommand
2370 for(;i
!= args
.end(); ++i
)
2372 std::string fileName
= *i
;
2373 if(!cmsys::SystemTools::FileIsFullPath(fileName
.c_str()))
2375 fileName
= this->Makefile
->GetCurrentDirectory();
2376 fileName
+= "/" + *i
;
2379 if(cmSystemTools::FileIsDirectory(fileName
.c_str()) && recurse
)
2381 cmSystemTools::RemoveADirectory(fileName
.c_str());
2385 cmSystemTools::RemoveFile(fileName
.c_str());
2391 //----------------------------------------------------------------------------
2392 bool cmFileCommand::HandleCMakePathCommand(std::vector
<std::string
>
2396 std::vector
<std::string
>::const_iterator i
= args
.begin();
2397 if(args
.size() != 3)
2399 this->SetError("FILE(SYSTEM_PATH ENV result) must be called with "
2400 "only three arguments.");
2403 i
++; // Get rid of subcommand
2404 #if defined(_WIN32) && !defined(__CYGWIN__)
2409 std::vector
<cmsys::String
> path
= cmSystemTools::SplitString(i
->c_str(),
2412 const char* var
= i
->c_str();
2414 for(std::vector
<cmsys::String
>::iterator j
= path
.begin();
2415 j
!= path
.end(); ++j
)
2417 if(j
!= path
.begin())
2423 cmSystemTools::ConvertToUnixSlashes(*j
);
2427 *j
= cmSystemTools::ConvertToOutputPath(j
->c_str());
2428 // remove double quotes in the path
2429 cmsys::String
& s
= *j
;
2431 if(s
.size() > 1 && s
[0] == '\"' && s
[s
.size()-1] == '\"')
2433 s
= s
.substr(1,s
.size()-2);
2438 this->Makefile
->AddDefinition(var
, value
.c_str());
2441 #if defined(CMAKE_BUILD_WITH_CMAKE)
2443 // Stuff for curl download
2444 typedef std::vector
<char> cmFileCommandVectorOfChar
;
2447 cmFileCommandWriteMemoryCallback(void *ptr
, size_t size
, size_t nmemb
,
2450 register int realsize
= (int)(size
* nmemb
);
2451 std::ofstream
* fout
= static_cast<std::ofstream
*>(data
);
2452 const char* chPtr
= static_cast<char*>(ptr
);
2453 fout
->write(chPtr
, realsize
);
2458 cmFileCommandCurlDebugCallback(CURL
*, curl_infotype
, char *chPtr
,
2459 size_t size
, void *data
)
2461 cmFileCommandVectorOfChar
*vec
2462 = static_cast<cmFileCommandVectorOfChar
*>(data
);
2463 vec
->insert(vec
->end(), chPtr
, chPtr
+ size
);
2474 cmFileCommand::HandleDownloadCommand(std::vector
<std::string
>
2477 #if defined(CMAKE_BUILD_WITH_CMAKE)
2478 std::vector
<std::string
>::const_iterator i
= args
.begin();
2481 this->SetError("FILE(DOWNLOAD url file) must be called with "
2482 "at least three arguments.");
2485 i
++; // Get rid of subcommand
2486 std::string url
= *i
;
2488 std::string file
= *i
;
2491 std::string verboseLog
;
2492 std::string statusVar
;
2493 while(i
!= args
.end())
2500 timeout
= atof(i
->c_str());
2504 this->SetError("FILE(DOWNLOAD url file TIMEOUT time) missing "
2505 "time for TIMEOUT.");
2509 else if(*i
== "LOG")
2512 if( i
== args
.end())
2514 this->SetError("FILE(DOWNLOAD url file LOG VAR) missing "
2520 else if(*i
== "STATUS")
2523 if( i
== args
.end())
2525 this->SetError("FILE(DOWNLOAD url file STATUS VAR) missing "
2534 std::string dir
= cmSystemTools::GetFilenamePath(file
.c_str());
2535 if(!cmSystemTools::FileExists(dir
.c_str()) &&
2536 !cmSystemTools::MakeDirectory(dir
.c_str()))
2538 std::string errstring
= "FILE(DOWNLOAD ) error; cannot create directory: "
2539 + dir
+ ". Maybe need administrative privileges.";
2540 this->SetError(errstring
.c_str());
2544 std::ofstream
fout(file
.c_str(), std::ios::binary
);
2547 this->SetError("FILE(DOWNLOAD url file TIMEOUT time) can not open "
2552 curl_global_init(CURL_GLOBAL_DEFAULT
);
2553 curl
= curl_easy_init();
2556 this->SetError("FILE(DOWNLOAD ) error "
2557 "initializing curl.");
2561 curl_easy_setopt(curl
, CURLOPT_URL
, url
.c_str());
2562 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
,
2563 cmFileCommandWriteMemoryCallback
);
2564 curl_easy_setopt(curl
, CURLOPT_DEBUGFUNCTION
,
2565 cmFileCommandCurlDebugCallback
);
2566 cmFileCommandVectorOfChar chunkDebug
;
2567 ::curl_easy_setopt(curl
, CURLOPT_FILE
, (void *)&fout
);
2568 ::curl_easy_setopt(curl
, CURLOPT_DEBUGDATA
, (void *)&chunkDebug
);
2569 if(verboseLog
.size())
2571 curl_easy_setopt(curl
, CURLOPT_VERBOSE
, 1);
2575 curl_easy_setopt(curl
, CURLOPT_TIMEOUT
, timeout
);
2577 CURLcode res
= curl_easy_perform(curl
);
2578 /* always cleanup */
2579 curl_easy_cleanup(curl
);
2580 if(statusVar
.size())
2582 cmOStringStream result
;
2583 result
<< (int)res
<< ";\"" << curl_easy_strerror(res
) << "\"";
2584 this->Makefile
->AddDefinition(statusVar
.c_str(),
2585 result
.str().c_str());
2587 curl_global_cleanup();
2588 if(chunkDebug
.size())
2590 chunkDebug
.push_back(0);
2591 if(CURLE_OPERATION_TIMEOUTED
== res
)
2593 std::string output
= &*chunkDebug
.begin();
2595 if(verboseLog
.size())
2597 this->Makefile
->AddDefinition(verboseLog
.c_str(),
2598 &*chunkDebug
.begin());
2602 this->Makefile
->AddDefinition(verboseLog
.c_str(),
2603 &*chunkDebug
.begin());
2607 this->SetError("FILE(DOWNLOAD ) "
2608 "not supported in bootstrap cmake ");