1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmFileCommand.cxx,v $
6 Date: $Date: 2009-04-15 13:58:13 $
7 Version: $Revision: 1.119 $
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
== "INSTALL" )
117 return this->HandleInstallCommand(args
);
119 else if ( subCommand
== "DIFFERENT" )
121 return this->HandleDifferentCommand(args
);
123 else if ( subCommand
== "RPATH_CHANGE" || subCommand
== "CHRPATH" )
125 return this->HandleRPathChangeCommand(args
);
127 else if ( subCommand
== "RPATH_CHECK" )
129 return this->HandleRPathCheckCommand(args
);
131 else if ( subCommand
== "RPATH_REMOVE" )
133 return this->HandleRPathRemoveCommand(args
);
135 else if ( subCommand
== "RELATIVE_PATH" )
137 return this->HandleRelativePathCommand(args
);
139 else if ( subCommand
== "TO_CMAKE_PATH" )
141 return this->HandleCMakePathCommand(args
, false);
143 else if ( subCommand
== "TO_NATIVE_PATH" )
145 return this->HandleCMakePathCommand(args
, true);
148 std::string e
= "does not recognize sub-command "+subCommand
;
149 this->SetError(e
.c_str());
153 //----------------------------------------------------------------------------
154 bool cmFileCommand::HandleWriteCommand(std::vector
<std::string
> const& args
,
158 std::vector
<std::string
>::const_iterator i
= args
.begin();
160 i
++; // Get rid of subcommand
162 std::string fileName
= *i
;
163 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
165 fileName
= this->Makefile
->GetCurrentDirectory();
166 fileName
+= "/" + *i
;
171 for(;i
!= args
.end(); ++i
)
175 if ( !this->Makefile
->CanIWriteThisFile(fileName
.c_str()) )
178 = "attempted to write a file: " + fileName
+
179 " into a source directory.";
180 this->SetError(e
.c_str());
181 cmSystemTools::SetFatalErrorOccured();
184 std::string dir
= cmSystemTools::GetFilenamePath(fileName
);
185 cmSystemTools::MakeDirectory(dir
.c_str());
188 #if defined( _MSC_VER ) || defined( __MINGW32__ )
190 #elif defined( __BORLANDC__ )
199 // Set permissions to writable
200 if ( cmSystemTools::GetPermissions(fileName
.c_str(), mode
) )
202 cmSystemTools::SetPermissions(fileName
.c_str(),
203 #if defined( _MSC_VER ) || defined( __MINGW32__ )
210 // If GetPermissions fails, pretend like it is ok. File open will fail if
211 // the file is not writable
212 std::ofstream
file(fileName
.c_str(), append
?std::ios::app
: std::ios::out
);
215 std::string error
= "Internal CMake error when trying to open file: ";
216 error
+= fileName
.c_str();
217 error
+= " for writing.";
218 this->SetError(error
.c_str());
223 cmSystemTools::SetPermissions(fileName
.c_str(), mode
);
227 //----------------------------------------------------------------------------
228 bool cmFileCommand::HandleReadCommand(std::vector
<std::string
> const& args
)
230 if ( args
.size() < 3 )
232 this->SetError("READ must be called with at least two additional "
237 cmCommandArgumentsHelper argHelper
;
238 cmCommandArgumentGroup group
;
240 cmCAString
readArg (&argHelper
, "READ");
241 cmCAString
fileNameArg (&argHelper
, 0);
242 cmCAString
resultArg (&argHelper
, 0);
244 cmCAString
offsetArg (&argHelper
, "OFFSET", &group
);
245 cmCAString
limitArg (&argHelper
, "LIMIT", &group
);
246 cmCAEnabler
hexOutputArg (&argHelper
, "HEX", &group
);
248 fileNameArg
.Follows(&readArg
);
249 resultArg
.Follows(&fileNameArg
);
250 group
.Follows(&resultArg
);
251 argHelper
.Parse(&args
, 0);
253 std::string fileName
= fileNameArg
.GetString();
254 if ( !cmsys::SystemTools::FileIsFullPath(fileName
.c_str()) )
256 fileName
= this->Makefile
->GetCurrentDirectory();
257 fileName
+= "/" + fileNameArg
.GetString();
260 std::string variable
= resultArg
.GetString();
262 // Open the specified file.
263 #if defined(_WIN32) || defined(__CYGWIN__)
264 std::ifstream
file(fileName
.c_str(), std::ios::in
|
265 (hexOutputArg
.IsEnabled() ? std::ios::binary
: std::ios::in
));
267 std::ifstream
file(fileName
.c_str(), std::ios::in
);
272 std::string error
= "Internal CMake error when trying to open file: ";
273 error
+= fileName
.c_str();
274 error
+= " for reading.";
275 this->SetError(error
.c_str());
281 if (limitArg
.GetString().size() > 0)
283 sizeLimit
= atoi(limitArg
.GetCString());
286 // is there an offset?
288 if (offsetArg
.GetString().size() > 0)
290 offset
= atoi(offsetArg
.GetCString());
297 if (hexOutputArg
.IsEnabled())
299 // Convert part of the file into hex code
301 while((sizeLimit
!= 0) && (c
= file
.get(), file
))
304 sprintf(hex
, "%x", c
&0xff);
315 bool has_newline
= false;
316 while (sizeLimit
!= 0 &&
317 cmSystemTools::GetLineFromStream(file
, line
, &has_newline
,
322 sizeLimit
= sizeLimit
- static_cast<long>(line
.size());
339 this->Makefile
->AddDefinition(variable
.c_str(), output
.c_str());
343 //----------------------------------------------------------------------------
344 bool cmFileCommand::HandleStringsCommand(std::vector
<std::string
> const& args
)
348 this->SetError("STRINGS requires a file name and output variable");
352 // Get the file to read.
353 std::string fileName
= args
[1];
354 if(!cmsys::SystemTools::FileIsFullPath(fileName
.c_str()))
356 fileName
= this->Makefile
->GetCurrentDirectory();
357 fileName
+= "/" + args
[1];
360 // Get the variable in which to store the results.
361 std::string outVar
= args
[2];
363 // Parse the options.
372 unsigned int minlen
= 0;
373 unsigned int maxlen
= 0;
374 int limit_input
= -1;
375 int limit_output
= -1;
376 unsigned int limit_count
= 0;
377 cmsys::RegularExpression regex
;
378 bool have_regex
= false;
379 bool newline_consume
= false;
380 bool hex_conversion_enabled
= true;
381 int arg_mode
= arg_none
;
382 for(unsigned int i
=3; i
< args
.size(); ++i
)
384 if(args
[i
] == "LIMIT_INPUT")
386 arg_mode
= arg_limit_input
;
388 else if(args
[i
] == "LIMIT_OUTPUT")
390 arg_mode
= arg_limit_output
;
392 else if(args
[i
] == "LIMIT_COUNT")
394 arg_mode
= arg_limit_count
;
396 else if(args
[i
] == "LENGTH_MINIMUM")
398 arg_mode
= arg_length_minimum
;
400 else if(args
[i
] == "LENGTH_MAXIMUM")
402 arg_mode
= arg_length_maximum
;
404 else if(args
[i
] == "REGEX")
406 arg_mode
= arg_regex
;
408 else if(args
[i
] == "NEWLINE_CONSUME")
410 newline_consume
= true;
413 else if(args
[i
] == "NO_HEX_CONVERSION")
415 hex_conversion_enabled
= false;
418 else if(arg_mode
== arg_limit_input
)
420 if(sscanf(args
[i
].c_str(), "%d", &limit_input
) != 1 ||
424 e
<< "STRINGS option LIMIT_INPUT value \""
425 << args
[i
] << "\" is not an unsigned integer.";
426 this->SetError(e
.str().c_str());
431 else if(arg_mode
== arg_limit_output
)
433 if(sscanf(args
[i
].c_str(), "%d", &limit_output
) != 1 ||
437 e
<< "STRINGS option LIMIT_OUTPUT value \""
438 << args
[i
] << "\" is not an unsigned integer.";
439 this->SetError(e
.str().c_str());
444 else if(arg_mode
== arg_limit_count
)
447 if(sscanf(args
[i
].c_str(), "%d", &count
) != 1 || count
< 0)
450 e
<< "STRINGS option LIMIT_COUNT value \""
451 << args
[i
] << "\" is not an unsigned integer.";
452 this->SetError(e
.str().c_str());
458 else if(arg_mode
== arg_length_minimum
)
461 if(sscanf(args
[i
].c_str(), "%d", &len
) != 1 || len
< 0)
464 e
<< "STRINGS option LENGTH_MINIMUM value \""
465 << args
[i
] << "\" is not an unsigned integer.";
466 this->SetError(e
.str().c_str());
472 else if(arg_mode
== arg_length_maximum
)
475 if(sscanf(args
[i
].c_str(), "%d", &len
) != 1 || len
< 0)
478 e
<< "STRINGS option LENGTH_MAXIMUM value \""
479 << args
[i
] << "\" is not an unsigned integer.";
480 this->SetError(e
.str().c_str());
486 else if(arg_mode
== arg_regex
)
488 if(!regex
.compile(args
[i
].c_str()))
491 e
<< "STRINGS option REGEX value \""
492 << args
[i
] << "\" could not be compiled.";
493 this->SetError(e
.str().c_str());
502 e
<< "STRINGS given unknown argument \""
504 this->SetError(e
.str().c_str());
509 if (hex_conversion_enabled
)
511 // TODO: should work without temp file, but just on a memory buffer
512 std::string binaryFileName
= this->Makefile
->GetCurrentOutputDirectory();
513 binaryFileName
+= cmake::GetCMakeFilesDirectory();
514 binaryFileName
+= "/FileCommandStringsBinaryFile";
515 if(cmHexFileConverter::TryConvert(fileName
.c_str(),binaryFileName
.c_str()))
517 fileName
= binaryFileName
;
521 // Open the specified file.
522 #if defined(_WIN32) || defined(__CYGWIN__)
523 std::ifstream
fin(fileName
.c_str(), std::ios::in
| std::ios::binary
);
525 std::ifstream
fin(fileName
.c_str(), std::ios::in
);
530 e
<< "STRINGS file \"" << fileName
<< "\" cannot be read.";
531 this->SetError(e
.str().c_str());
535 // Parse strings out of the file.
537 std::vector
<std::string
> strings
;
540 while((!limit_count
|| strings
.size() < limit_count
) &&
541 (limit_input
< 0 || static_cast<int>(fin
.tellg()) < limit_input
) &&
542 (c
= fin
.get(), fin
))
546 // A terminating null character has been found. Check if the
547 // current string matches the requirements. Since it was
548 // terminated by a null character, we require that the length be
549 // at least one no matter what the user specified.
550 if(s
.length() >= minlen
&& s
.length() >= 1 &&
551 (!have_regex
|| regex
.find(s
.c_str())))
553 output_size
+= static_cast<int>(s
.size()) + 1;
554 if(limit_output
>= 0 && output_size
>= limit_output
)
559 strings
.push_back(s
);
562 // Reset the string to empty.
565 else if(c
== '\n' && !newline_consume
)
567 // The current line has been terminated. Check if the current
568 // string matches the requirements. The length may now be as
569 // low as zero since blank lines are allowed.
570 if(s
.length() >= minlen
&&
571 (!have_regex
|| regex
.find(s
.c_str())))
573 output_size
+= static_cast<int>(s
.size()) + 1;
574 if(limit_output
>= 0 && output_size
>= limit_output
)
579 strings
.push_back(s
);
582 // Reset the string to empty.
587 // Ignore CR character to make output always have UNIX newlines.
589 else if(c
>= 0x20 && c
< 0x7F || c
== '\t' || c
== '\f' ||
590 (c
== '\n' && newline_consume
))
592 // This is an ASCII character that may be part of a string.
597 // This is a non-string character. Reset the string to emtpy.
601 // Terminate a string if the maximum length is reached.
602 if(maxlen
> 0 && s
.size() == maxlen
)
604 if(s
.length() >= minlen
&&
605 (!have_regex
|| regex
.find(s
.c_str())))
607 output_size
+= static_cast<int>(s
.size()) + 1;
608 if(limit_output
>= 0 && output_size
>= limit_output
)
613 strings
.push_back(s
);
619 // If there is a non-empty current string we have hit the end of the
620 // input file or the input size limit. Check if the current string
621 // matches the requirements.
622 if((!limit_count
|| strings
.size() < limit_count
) &&
623 !s
.empty() && s
.length() >= minlen
&&
624 (!have_regex
|| regex
.find(s
.c_str())))
626 output_size
+= static_cast<int>(s
.size()) + 1;
627 if(limit_output
< 0 || output_size
< limit_output
)
629 strings
.push_back(s
);
633 // Encode the result in a CMake list.
634 const char* sep
= "";
636 for(std::vector
<std::string
>::const_iterator si
= strings
.begin();
637 si
!= strings
.end(); ++si
)
639 // Separate the strings in the output to make it a list.
643 // Store the string in the output, but escape semicolons to
644 // make sure it is a list.
645 std::string
const& sr
= *si
;
646 for(unsigned int i
=0; i
< sr
.size(); ++i
)
656 // Save the output in a makefile variable.
657 this->Makefile
->AddDefinition(outVar
.c_str(), output
.c_str());
661 //----------------------------------------------------------------------------
662 bool cmFileCommand::HandleGlobCommand(std::vector
<std::string
> const& args
,
665 if ( args
.size() < 2 )
667 this->SetError("GLOB requires at least a variable name");
671 std::vector
<std::string
>::const_iterator i
= args
.begin();
673 i
++; // Get rid of subcommand
675 std::string variable
= *i
;
678 g
.SetRecurse(recurse
);
680 bool explicitFollowSymlinks
= false;
681 cmPolicies::PolicyStatus status
=
682 this->Makefile
->GetPolicyStatus(cmPolicies::CMP0009
);
687 case cmPolicies::NEW
:
688 g
.RecurseThroughSymlinksOff();
690 case cmPolicies::OLD
:
691 case cmPolicies::WARN
:
692 case cmPolicies::REQUIRED_IF_USED
:
693 case cmPolicies::REQUIRED_ALWAYS
:
694 g
.RecurseThroughSymlinksOn();
699 std::string output
= "";
701 for ( ; i
!= args
.end(); ++i
)
703 if ( recurse
&& (*i
== "FOLLOW_SYMLINKS") )
705 explicitFollowSymlinks
= true;
706 g
.RecurseThroughSymlinksOn();
708 if ( i
== args
.end() )
711 "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS");
716 if ( *i
== "RELATIVE" )
718 ++i
; // skip RELATIVE
719 if ( i
== args
.end() )
721 this->SetError("GLOB requires a directory after the RELATIVE tag");
724 g
.SetRelative(i
->c_str());
728 this->SetError("GLOB requires a glob expression after the directory");
733 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
735 std::string expr
= this->Makefile
->GetCurrentDirectory();
736 // Handle script mode
737 if ( expr
.size() > 0 )
752 std::vector
<std::string
>::size_type cc
;
753 std::vector
<std::string
>& files
= g
.GetFiles();
754 for ( cc
= 0; cc
< files
.size(); cc
++ )
765 if(recurse
&& !explicitFollowSymlinks
)
769 case cmPolicies::NEW
:
770 // Correct behavior, yay!
772 case cmPolicies::OLD
:
773 // Probably not really the expected behavior, but the author explicitly
774 // asked for the old behavior... no warning.
775 case cmPolicies::WARN
:
776 // Possibly unexpected old behavior *and* we actually traversed
777 // symlinks without being explicitly asked to: warn the author.
778 if(g
.GetFollowedSymlinkCount() != 0)
780 this->Makefile
->IssueMessage(cmake::AUTHOR_WARNING
,
781 this->Makefile
->GetPolicies()->
782 GetPolicyWarning(cmPolicies::CMP0009
));
785 case cmPolicies::REQUIRED_IF_USED
:
786 case cmPolicies::REQUIRED_ALWAYS
:
787 this->SetError("policy CMP0009 error");
788 this->Makefile
->IssueMessage(cmake::FATAL_ERROR
,
789 this->Makefile
->GetPolicies()->
790 GetRequiredPolicyError(cmPolicies::CMP0009
));
795 this->Makefile
->AddDefinition(variable
.c_str(), output
.c_str());
799 //----------------------------------------------------------------------------
800 bool cmFileCommand::HandleMakeDirectoryCommand(
801 std::vector
<std::string
> const& args
)
805 this->SetError("called with incorrect number of arguments");
809 std::vector
<std::string
>::const_iterator i
= args
.begin();
811 i
++; // Get rid of subcommand
814 for ( ; i
!= args
.end(); ++i
)
816 const std::string
* cdir
= &(*i
);
817 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
819 expr
= this->Makefile
->GetCurrentDirectory();
823 if ( !this->Makefile
->CanIWriteThisFile(cdir
->c_str()) )
825 std::string e
= "attempted to create a directory: " + *cdir
826 + " into a source directory.";
827 this->SetError(e
.c_str());
828 cmSystemTools::SetFatalErrorOccured();
831 if ( !cmSystemTools::MakeDirectory(cdir
->c_str()) )
833 std::string error
= "problem creating directory: " + *cdir
;
834 this->SetError(error
.c_str());
841 //----------------------------------------------------------------------------
843 cmFileCommand::HandleDifferentCommand(std::vector
<std::string
> const& args
)
846 FILE(DIFFERENT <variable> FILES <lhs> <rhs>)
849 // Evaluate arguments.
850 const char* file_lhs
= 0;
851 const char* file_rhs
= 0;
853 enum Doing
{ DoingNone
, DoingVar
, DoingFileLHS
, DoingFileRHS
};
854 Doing doing
= DoingVar
;
855 for(unsigned int i
=1; i
< args
.size(); ++i
)
857 if(args
[i
] == "FILES")
859 doing
= DoingFileLHS
;
861 else if(doing
== DoingVar
)
863 var
= args
[i
].c_str();
866 else if(doing
== DoingFileLHS
)
868 file_lhs
= args
[i
].c_str();
869 doing
= DoingFileRHS
;
871 else if(doing
== DoingFileRHS
)
873 file_rhs
= args
[i
].c_str();
879 e
<< "DIFFERENT given unknown argument " << args
[i
];
880 this->SetError(e
.str().c_str());
886 this->SetError("DIFFERENT not given result variable name.");
889 if(!file_lhs
|| !file_rhs
)
891 this->SetError("DIFFERENT not given FILES option with two file names.");
895 // Compare the files.
897 cmSystemTools::FilesDiffer(file_lhs
, file_rhs
)? "1" : "0";
898 this->Makefile
->AddDefinition(var
, result
);
902 //----------------------------------------------------------------------------
903 // File installation helper class.
904 struct cmFileInstaller
906 // Methods to actually install files.
907 bool InstallFile(const char* fromFile
, const char* toFile
, bool always
);
908 bool InstallDirectory(const char* source
, const char* destination
,
911 // All instances need the file command and makefile using them.
912 cmFileInstaller(cmFileCommand
* fc
, cmMakefile
* mf
):
913 FileCommand(fc
), Makefile(mf
), DestDirLength(0), MatchlessFiles(true)
915 // Get the current manifest.
917 this->Makefile
->GetSafeDefinition("CMAKE_INSTALL_MANIFEST_FILES");
921 // Save the updated install manifest.
922 this->Makefile
->AddDefinition("CMAKE_INSTALL_MANIFEST_FILES",
923 this->Manifest
.c_str());
927 cmFileCommand
* FileCommand
;
928 cmMakefile
* Makefile
;
929 cmFileTimeComparison FileTimes
;
932 // The length of the destdir setting.
935 // Whether to install a file not matching any expression.
938 // The current file manifest (semicolon separated list).
939 std::string Manifest
;
941 // Permissions for files and directories installed by this object.
942 mode_t FilePermissions
;
943 mode_t DirPermissions
;
945 // Properties set by pattern and regex match rules.
946 struct MatchProperties
950 MatchProperties(): Exclude(false), Permissions(0) {}
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
,
966 // Match rules are case-insensitive on some platforms.
967 #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
968 std::string lower
= cmSystemTools::LowerCase(file
);
969 file
= lower
.c_str();
972 // Collect properties from all matching rules.
973 bool matched
= false;
974 MatchProperties result
;
975 for(std::vector
<MatchRule
>::iterator mr
= this->MatchRules
.begin();
976 mr
!= this->MatchRules
.end(); ++mr
)
978 if(mr
->Regex
.find(file
))
981 result
.Exclude
|= mr
->Properties
.Exclude
;
982 result
.Permissions
|= mr
->Properties
.Permissions
;
985 if(!matched
&& !this->MatchlessFiles
&& !isDirectory
)
987 result
.Exclude
= true;
992 // Append a file to the installation manifest.
993 void ManifestAppend(std::string
const& file
)
995 this->Manifest
+= ";";
996 this->Manifest
+= file
.substr(this->DestDirLength
);
999 // Translate an argument to a permissions bit.
1000 bool CheckPermissions(std::string
const& arg
, mode_t
& permissions
)
1002 if(arg
== "OWNER_READ") { permissions
|= mode_owner_read
; }
1003 else if(arg
== "OWNER_WRITE") { permissions
|= mode_owner_write
; }
1004 else if(arg
== "OWNER_EXECUTE") { permissions
|= mode_owner_execute
; }
1005 else if(arg
== "GROUP_READ") { permissions
|= mode_group_read
; }
1006 else if(arg
== "GROUP_WRITE") { permissions
|= mode_group_write
; }
1007 else if(arg
== "GROUP_EXECUTE") { permissions
|= mode_group_execute
; }
1008 else if(arg
== "WORLD_READ") { permissions
|= mode_world_read
; }
1009 else if(arg
== "WORLD_WRITE") { permissions
|= mode_world_write
; }
1010 else if(arg
== "WORLD_EXECUTE") { permissions
|= mode_world_execute
; }
1011 else if(arg
== "SETUID") { permissions
|= mode_setuid
; }
1012 else if(arg
== "SETGID") { permissions
|= mode_setgid
; }
1016 e
<< "INSTALL given invalid permission \"" << arg
<< "\".";
1017 this->FileCommand
->SetError(e
.str().c_str());
1024 bool InstallSymlink(const char* fromFile
, const char* toFile
, bool always
);
1027 //----------------------------------------------------------------------------
1028 bool cmFileInstaller::InstallSymlink(const char* fromFile
, const char* toFile
,
1031 // Read the original symlink.
1032 std::string symlinkTarget
;
1033 if(!cmSystemTools::ReadSymlink(fromFile
, symlinkTarget
))
1036 e
<< "INSTALL cannot read symlink \"" << fromFile
1037 << "\" to duplicate at \"" << toFile
<< "\".";
1038 this->FileCommand
->SetError(e
.str().c_str());
1042 // Compare the symlink value to that at the destination if not
1043 // always installing.
1047 std::string oldSymlinkTarget
;
1048 if(cmSystemTools::ReadSymlink(toFile
, oldSymlinkTarget
))
1050 if(symlinkTarget
== oldSymlinkTarget
)
1057 // Inform the user about this file installation.
1058 std::string message
= (copy
? "Installing: " : "Up-to-date: ");
1060 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1064 // Remove the destination file so we can always create the symlink.
1065 cmSystemTools::RemoveFile(toFile
);
1067 // Create the symlink.
1068 if(!cmSystemTools::CreateSymlink(symlinkTarget
.c_str(), toFile
))
1071 e
<< "INSTALL cannot duplicate symlink \"" << fromFile
1072 << "\" at \"" << toFile
<< "\".";
1073 this->FileCommand
->SetError(e
.str().c_str());
1078 // Add the file to the manifest.
1079 this->ManifestAppend(toFile
);
1084 //----------------------------------------------------------------------------
1085 bool cmFileInstaller::InstallFile(const char* fromFile
, const char* toFile
,
1088 // Collect any properties matching this file name.
1089 MatchProperties match_properties
=
1090 this->CollectMatchProperties(fromFile
, false);
1092 // Skip the file if it is excluded.
1093 if(match_properties
.Exclude
)
1098 // Short-circuit for symbolic links.
1099 if(cmSystemTools::FileIsSymlink(fromFile
))
1101 return this->InstallSymlink(fromFile
, toFile
, always
);
1104 // Determine whether we will copy the file.
1108 // If both files exist with the same time do not copy.
1109 if(!this->FileTimes
.FileTimesDiffer(fromFile
, toFile
))
1115 // Inform the user about this file installation.
1116 std::string message
= (copy
? "Installing: " : "Up-to-date: ");
1118 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1121 if(copy
&& !cmSystemTools::CopyAFile(fromFile
, toFile
, true, false))
1124 e
<< "INSTALL cannot copy file \"" << fromFile
1125 << "\" to \"" << toFile
<< "\".";
1126 this->FileCommand
->SetError(e
.str().c_str());
1130 // Add the file to the manifest.
1131 this->ManifestAppend(toFile
);
1133 // Set the file modification time of the destination file.
1136 if (!cmSystemTools::CopyFileTime(fromFile
, toFile
))
1139 e
<< "Problem setting modification time on file \"" << toFile
<< "\"";
1140 this->FileCommand
->SetError(e
.str().c_str());
1145 // Set permissions of the destination file.
1146 mode_t permissions
= (match_properties
.Permissions
?
1147 match_properties
.Permissions
: this->FilePermissions
);
1150 // No permissions were explicitly provided but the user requested
1151 // that the source file permissions be used.
1152 cmSystemTools::GetPermissions(fromFile
, permissions
);
1154 if(permissions
&& !cmSystemTools::SetPermissions(toFile
, permissions
))
1157 e
<< "Problem setting permissions on file \"" << toFile
<< "\"";
1158 this->FileCommand
->SetError(e
.str().c_str());
1165 //----------------------------------------------------------------------------
1166 bool cmFileInstaller::InstallDirectory(const char* source
,
1167 const char* destination
,
1170 // Collect any properties matching this directory name.
1171 MatchProperties match_properties
=
1172 this->CollectMatchProperties(source
, true);
1174 // Skip the directory if it is excluded.
1175 if(match_properties
.Exclude
)
1180 // Short-circuit for symbolic links.
1181 if(cmSystemTools::FileIsSymlink(source
))
1183 return this->InstallSymlink(source
, destination
, always
);
1186 // Inform the user about this directory installation.
1187 std::string message
= "Installing: ";
1188 message
+= destination
;
1189 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1191 // Make sure the destination directory exists.
1192 if(!cmSystemTools::MakeDirectory(destination
))
1197 // Compute the requested permissions for the destination directory.
1198 mode_t permissions
= (match_properties
.Permissions
?
1199 match_properties
.Permissions
: this->DirPermissions
);
1202 // No permissions were explicitly provided but the user requested
1203 // that the source directory permissions be used.
1204 cmSystemTools::GetPermissions(source
, permissions
);
1207 // Compute the set of permissions required on this directory to
1208 // recursively install files and subdirectories safely.
1209 mode_t required_permissions
=
1210 mode_owner_read
| mode_owner_write
| mode_owner_execute
;
1212 // If the required permissions are specified it is safe to set the
1213 // final permissions now. Otherwise we must add the required
1214 // permissions temporarily during file installation.
1215 mode_t permissions_before
= 0;
1216 mode_t permissions_after
= 0;
1217 if(permissions
& required_permissions
)
1219 permissions_before
= permissions
;
1223 permissions_before
= permissions
| required_permissions
;
1224 permissions_after
= permissions
;
1227 // Set the required permissions of the destination directory.
1228 if(permissions_before
&&
1229 !cmSystemTools::SetPermissions(destination
, permissions_before
))
1232 e
<< "Problem setting permissions on directory \""
1233 << destination
<< "\"";
1234 this->FileCommand
->SetError(e
.str().c_str());
1238 // Load the directory contents to traverse it recursively.
1239 cmsys::Directory dir
;
1240 if(source
&& *source
)
1244 unsigned long numFiles
= static_cast<unsigned long>(dir
.GetNumberOfFiles());
1245 for(unsigned long fileNum
= 0; fileNum
< numFiles
; ++fileNum
)
1247 if(!(strcmp(dir
.GetFile(fileNum
), ".") == 0 ||
1248 strcmp(dir
.GetFile(fileNum
), "..") == 0))
1250 cmsys_stl::string fromPath
= source
;
1252 fromPath
+= dir
.GetFile(fileNum
);
1253 if(cmSystemTools::FileIsDirectory(fromPath
.c_str()))
1255 cmsys_stl::string toDir
= destination
;
1257 toDir
+= dir
.GetFile(fileNum
);
1258 if(!this->InstallDirectory(fromPath
.c_str(), toDir
.c_str(), always
))
1265 // Install this file.
1266 std::string toFile
= destination
;
1268 toFile
+= dir
.GetFile(fileNum
);
1269 if(!this->InstallFile(fromPath
.c_str(), toFile
.c_str(), always
))
1277 // Set the requested permissions of the destination directory.
1278 if(permissions_after
&&
1279 !cmSystemTools::SetPermissions(destination
, permissions_after
))
1282 e
<< "Problem setting permissions on directory \"" << destination
<< "\"";
1283 this->FileCommand
->SetError(e
.str().c_str());
1290 //----------------------------------------------------------------------------
1291 void cmFileCommand::HandleInstallPermissions(cmFileInstaller
& installer
,
1292 mode_t
& permissions_file
,
1293 mode_t
& permissions_dir
,
1295 bool use_given_permissions_file
,
1296 bool use_given_permissions_dir
,
1297 bool use_source_permissions
) const
1299 // Choose a default for shared library permissions.
1300 bool install_so_no_exe
= this->Makefile
->IsOn("CMAKE_INSTALL_SO_NO_EXE");
1301 // If file permissions were not specified set default permissions
1302 // for this target type.
1303 if(!use_given_permissions_file
&& !use_source_permissions
)
1307 case cmTarget::SHARED_LIBRARY
:
1308 case cmTarget::MODULE_LIBRARY
:
1309 if(install_so_no_exe
)
1311 // Use read/write permissions.
1312 permissions_file
= 0;
1313 permissions_file
|= mode_owner_read
;
1314 permissions_file
|= mode_owner_write
;
1315 permissions_file
|= mode_group_read
;
1316 permissions_file
|= mode_world_read
;
1319 case cmTarget::EXECUTABLE
:
1320 case cmTarget::INSTALL_PROGRAMS
:
1321 // Use read/write/executable permissions.
1322 permissions_file
= 0;
1323 permissions_file
|= mode_owner_read
;
1324 permissions_file
|= mode_owner_write
;
1325 permissions_file
|= mode_owner_execute
;
1326 permissions_file
|= mode_group_read
;
1327 permissions_file
|= mode_group_execute
;
1328 permissions_file
|= mode_world_read
;
1329 permissions_file
|= mode_world_execute
;
1332 // Use read/write permissions.
1333 permissions_file
= 0;
1334 permissions_file
|= mode_owner_read
;
1335 permissions_file
|= mode_owner_write
;
1336 permissions_file
|= mode_group_read
;
1337 permissions_file
|= mode_world_read
;
1342 // If directory permissions were not specified set default permissions.
1343 if(!use_given_permissions_dir
&& !use_source_permissions
)
1345 // Use read/write/executable permissions.
1346 permissions_dir
= 0;
1347 permissions_dir
|= mode_owner_read
;
1348 permissions_dir
|= mode_owner_write
;
1349 permissions_dir
|= mode_owner_execute
;
1350 permissions_dir
|= mode_group_read
;
1351 permissions_dir
|= mode_group_execute
;
1352 permissions_dir
|= mode_world_read
;
1353 permissions_dir
|= mode_world_execute
;
1355 // Set the installer permissions.
1356 installer
.FilePermissions
= permissions_file
;
1357 installer
.DirPermissions
= permissions_dir
;
1360 //----------------------------------------------------------------------------
1362 ::GetTargetTypeFromString(const std::string
& stype
, int& itype
) const
1364 if ( stype
== "EXECUTABLE" )
1366 itype
= cmTarget::EXECUTABLE
;
1368 else if ( stype
== "PROGRAM" )
1370 itype
= cmTarget::INSTALL_PROGRAMS
;
1372 else if ( stype
== "STATIC_LIBRARY" )
1374 itype
= cmTarget::STATIC_LIBRARY
;
1376 else if ( stype
== "SHARED_LIBRARY" )
1378 itype
= cmTarget::SHARED_LIBRARY
;
1380 else if ( stype
== "MODULE" )
1382 itype
= cmTarget::MODULE_LIBRARY
;
1384 else if ( stype
== "DIRECTORY" )
1386 itype
= cmTarget::INSTALL_DIRECTORY
;
1391 //----------------------------------------------------------------------------
1392 bool cmFileCommand::HandleInstallDestination(cmFileInstaller
& installer
,
1393 std::string
& destination
)
1395 // allow for / to be a valid destination
1396 if ( destination
.size() < 2 && destination
!= "/" )
1398 this->SetError("called with inapropriate arguments. "
1399 "No DESTINATION provided or .");
1403 const char* destdir
= cmSystemTools::GetEnv("DESTDIR");
1404 if ( destdir
&& *destdir
)
1406 std::string sdestdir
= destdir
;
1407 cmSystemTools::ConvertToUnixSlashes(sdestdir
);
1408 char ch1
= destination
[0];
1409 char ch2
= destination
[1];
1411 if ( destination
.size() > 2 )
1413 ch3
= destination
[2];
1419 if ( ( ch1
>= 'a' && ch1
<= 'z' || ch1
>= 'A' && ch1
<= 'Z' ) &&
1423 // let's do some destdir magic:
1436 // This is relative path on unix or windows. Since we are doing
1437 // destdir, this case does not make sense.
1438 this->SetError("called with relative DESTINATION. This "
1439 "does not make sense when using DESTDIR. Specify "
1440 "absolute path or remove DESTDIR environment variable.");
1448 // looks like a network path.
1449 std::string message
= "called with network path DESTINATION. This "
1450 "does not make sense when using DESTDIR. Specify local "
1451 "absolute path or remove DESTDIR environment variable."
1453 message
+= destination
;
1454 this->SetError(message
.c_str());
1458 destination
= sdestdir
+ (destination
.c_str() + skip
);
1459 installer
.DestDirLength
= int(sdestdir
.size());
1462 if ( !cmSystemTools::FileExists(destination
.c_str()) )
1464 if ( !cmSystemTools::MakeDirectory(destination
.c_str()) )
1466 std::string errstring
= "cannot create directory: " + destination
+
1467 ". Maybe need administrative privileges.";
1468 this->SetError(errstring
.c_str());
1472 if ( !cmSystemTools::FileIsDirectory(destination
.c_str()) )
1474 std::string errstring
= "INSTALL destination: " + destination
+
1475 " is not a directory.";
1476 this->SetError(errstring
.c_str());
1482 //----------------------------------------------------------------------------
1484 cmFileCommand::HandleRPathChangeCommand(std::vector
<std::string
> const& args
)
1486 // Evaluate arguments.
1487 const char* file
= 0;
1488 const char* oldRPath
= 0;
1489 const char* newRPath
= 0;
1490 enum Doing
{ DoingNone
, DoingFile
, DoingOld
, DoingNew
};
1491 Doing doing
= DoingNone
;
1492 for(unsigned int i
=1; i
< args
.size(); ++i
)
1494 if(args
[i
] == "OLD_RPATH")
1498 else if(args
[i
] == "NEW_RPATH")
1502 else if(args
[i
] == "FILE")
1506 else if(doing
== DoingFile
)
1508 file
= args
[i
].c_str();
1511 else if(doing
== DoingOld
)
1513 oldRPath
= args
[i
].c_str();
1516 else if(doing
== DoingNew
)
1518 newRPath
= args
[i
].c_str();
1524 e
<< "RPATH_CHANGE given unknown argument " << args
[i
];
1525 this->SetError(e
.str().c_str());
1531 this->SetError("RPATH_CHANGE not given FILE option.");
1536 this->SetError("RPATH_CHANGE not given OLD_RPATH option.");
1541 this->SetError("RPATH_CHANGE not given NEW_RPATH option.");
1544 if(!cmSystemTools::FileExists(file
, true))
1547 e
<< "RPATH_CHANGE given FILE \"" << file
<< "\" that does not exist.";
1548 this->SetError(e
.str().c_str());
1551 bool success
= true;
1552 cmSystemToolsFileTime
* ft
= cmSystemTools::FileTimeNew();
1553 bool have_ft
= cmSystemTools::FileTimeGet(file
, ft
);
1556 if(!cmSystemTools::ChangeRPath(file
, oldRPath
, newRPath
, &emsg
, &changed
))
1559 e
<< "RPATH_CHANGE could not write new RPATH:\n"
1560 << " " << newRPath
<< "\n"
1562 << " " << file
<< "\n"
1564 this->SetError(e
.str().c_str());
1571 std::string message
= "Set runtime path of \"";
1573 message
+= "\" to \"";
1574 message
+= newRPath
;
1576 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1580 cmSystemTools::FileTimeSet(file
, ft
);
1583 cmSystemTools::FileTimeDelete(ft
);
1587 //----------------------------------------------------------------------------
1589 cmFileCommand::HandleRPathRemoveCommand(std::vector
<std::string
> const& args
)
1591 // Evaluate arguments.
1592 const char* file
= 0;
1593 enum Doing
{ DoingNone
, DoingFile
};
1594 Doing doing
= DoingNone
;
1595 for(unsigned int i
=1; i
< args
.size(); ++i
)
1597 if(args
[i
] == "FILE")
1601 else if(doing
== DoingFile
)
1603 file
= args
[i
].c_str();
1609 e
<< "RPATH_REMOVE given unknown argument " << args
[i
];
1610 this->SetError(e
.str().c_str());
1616 this->SetError("RPATH_REMOVE not given FILE option.");
1619 if(!cmSystemTools::FileExists(file
, true))
1622 e
<< "RPATH_REMOVE given FILE \"" << file
<< "\" that does not exist.";
1623 this->SetError(e
.str().c_str());
1626 bool success
= true;
1627 cmSystemToolsFileTime
* ft
= cmSystemTools::FileTimeNew();
1628 bool have_ft
= cmSystemTools::FileTimeGet(file
, ft
);
1631 if(!cmSystemTools::RemoveRPath(file
, &emsg
, &removed
))
1634 e
<< "RPATH_REMOVE could not remove RPATH from file:\n"
1635 << " " << file
<< "\n"
1637 this->SetError(e
.str().c_str());
1644 std::string message
= "Removed runtime path from \"";
1647 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1651 cmSystemTools::FileTimeSet(file
, ft
);
1654 cmSystemTools::FileTimeDelete(ft
);
1658 //----------------------------------------------------------------------------
1660 cmFileCommand::HandleRPathCheckCommand(std::vector
<std::string
> const& args
)
1662 // Evaluate arguments.
1663 const char* file
= 0;
1664 const char* rpath
= 0;
1665 enum Doing
{ DoingNone
, DoingFile
, DoingRPath
};
1666 Doing doing
= DoingNone
;
1667 for(unsigned int i
=1; i
< args
.size(); ++i
)
1669 if(args
[i
] == "RPATH")
1673 else if(args
[i
] == "FILE")
1677 else if(doing
== DoingFile
)
1679 file
= args
[i
].c_str();
1682 else if(doing
== DoingRPath
)
1684 rpath
= args
[i
].c_str();
1690 e
<< "RPATH_CHECK given unknown argument " << args
[i
];
1691 this->SetError(e
.str().c_str());
1697 this->SetError("RPATH_CHECK not given FILE option.");
1702 this->SetError("RPATH_CHECK not given RPATH option.");
1706 // If the file exists but does not have the desired RPath then
1707 // delete it. This is used during installation to re-install a file
1708 // if its RPath will change.
1709 if(cmSystemTools::FileExists(file
, true) &&
1710 !cmSystemTools::CheckRPath(file
, rpath
))
1712 cmSystemTools::RemoveFile(file
);
1718 //----------------------------------------------------------------------------
1719 bool cmFileCommand::HandleInstallCommand(std::vector
<std::string
> const& args
)
1721 if ( args
.size() < 6 )
1723 this->SetError("called with incorrect number of arguments");
1727 // Construct a file installer object.
1728 cmFileInstaller
installer(this, this->Makefile
);
1730 std::string rename
= "";
1731 std::string destination
= "";
1733 std::vector
<std::string
> files
;
1734 int itype
= cmTarget::INSTALL_FILES
;
1736 std::map
<cmStdString
, const char*> properties
;
1737 bool optional
= false;
1738 bool result
= this->ParseInstallArgs(args
, installer
, properties
,
1739 itype
, rename
, destination
, files
,
1743 result
= this->DoInstall(installer
,
1744 itype
, rename
, destination
, files
, optional
);
1749 //----------------------------------------------------------------------------
1750 bool cmFileCommand::ParseInstallArgs(std::vector
<std::string
> const& args
,
1751 cmFileInstaller
& installer
,
1752 std::map
<cmStdString
, const char*>& properties
,
1754 std::string
& rename
,
1755 std::string
& destination
,
1756 std::vector
<std::string
>& files
,
1759 std::string stype
= "FILES";
1760 enum Doing
{ DoingNone
, DoingFiles
, DoingProperties
,
1761 DoingPermissionsFile
, DoingPermissionsDir
,
1762 DoingPermissionsMatch
, DoingSelf24
};
1763 Doing doing
= DoingNone
;
1764 bool use_given_permissions_file
= false;
1765 bool use_given_permissions_dir
= false;
1766 bool use_source_permissions
= false;
1767 mode_t permissions_file
= 0;
1768 mode_t permissions_dir
= 0;
1770 cmFileInstaller::MatchRule
* current_match_rule
= 0;
1771 std::vector
<std::string
>::size_type i
= 0;
1772 i
++; // Get rid of subcommand
1773 for ( ; i
!= args
.size(); ++i
)
1775 const std::string
* cstr
= &args
[i
];
1776 if ( *cstr
== "DESTINATION" && i
< args
.size()-1 )
1778 if(current_match_rule
)
1781 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1782 this->SetError(e
.str().c_str());
1787 destination
= args
[i
];
1790 else if ( *cstr
== "TYPE" && i
< args
.size()-1 )
1792 if(current_match_rule
)
1795 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1796 this->SetError(e
.str().c_str());
1802 if ( args
[i
+1] == "OPTIONAL" )
1809 else if ( *cstr
== "RENAME" && i
< args
.size()-1 )
1811 if(current_match_rule
)
1814 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1815 this->SetError(e
.str().c_str());
1823 else if ( *cstr
== "REGEX" && i
< args
.size()-1 )
1826 installer
.MatchRules
.push_back(cmFileInstaller::MatchRule(args
[i
]));
1827 current_match_rule
= &*(installer
.MatchRules
.end()-1);
1828 if(!current_match_rule
->Regex
.is_valid())
1831 e
<< "INSTALL could not compile REGEX \"" << args
[i
] << "\".";
1832 this->SetError(e
.str().c_str());
1837 else if ( *cstr
== "EXCLUDE" )
1839 // Add this property to the current match rule.
1840 if(!current_match_rule
)
1843 e
<< "INSTALL does not allow \""
1844 << *cstr
<< "\" before a REGEX is given.";
1845 this->SetError(e
.str().c_str());
1848 current_match_rule
->Properties
.Exclude
= true;
1849 doing
= DoingPermissionsMatch
;
1851 else if ( *cstr
== "PROPERTIES" )
1853 if(current_match_rule
)
1856 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1857 this->SetError(e
.str().c_str());
1861 doing
= DoingProperties
;
1863 else if ( *cstr
== "PERMISSIONS" )
1865 if(current_match_rule
)
1867 doing
= DoingPermissionsMatch
;
1871 doing
= DoingPermissionsFile
;
1872 use_given_permissions_file
= true;
1875 else if ( *cstr
== "DIR_PERMISSIONS" )
1877 if(current_match_rule
)
1880 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1881 this->SetError(e
.str().c_str());
1885 use_given_permissions_dir
= true;
1886 doing
= DoingPermissionsDir
;
1888 else if ( *cstr
== "USE_SOURCE_PERMISSIONS" )
1890 if(current_match_rule
)
1893 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1894 this->SetError(e
.str().c_str());
1899 use_source_permissions
= true;
1901 else if ( *cstr
== "FILES_MATCHING" )
1903 if(current_match_rule
)
1906 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1907 this->SetError(e
.str().c_str());
1912 installer
.MatchlessFiles
= false;
1914 else if ( *cstr
== "COMPONENTS" )
1916 if(this->Makefile
->IsOn("CMAKE_INSTALL_SELF_2_4"))
1918 // When CMake 2.4 builds this CMake version we need to support
1919 // the install scripts it generates since it asks this CMake
1920 // to install itself using the rules it generated.
1921 doing
= DoingSelf24
;
1925 e
<< "INSTALL called with old-style COMPONENTS argument. "
1926 << "This script was generated with an older version of CMake. "
1927 << "Re-run this cmake version on your build tree.";
1928 this->SetError(e
.str().c_str());
1931 else if ( *cstr
== "CONFIGURATIONS" )
1934 e
<< "INSTALL called with old-style CONFIGURATIONS argument. "
1935 << "This script was generated with an older version of CMake. "
1936 << "Re-run this cmake version on your build tree.";
1937 this->SetError(e
.str().c_str());
1940 else if(*cstr
== "FILES" && doing
!= DoingFiles
)
1942 if(current_match_rule
)
1945 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1946 this->SetError(e
.str().c_str());
1952 else if(doing
== DoingProperties
&& i
< args
.size()-1)
1954 properties
[args
[i
]] = args
[i
+1].c_str();
1957 else if(doing
== DoingFiles
)
1959 files
.push_back(*cstr
);
1961 else if(doing
== DoingPermissionsFile
)
1963 if(!installer
.CheckPermissions(args
[i
], permissions_file
))
1968 else if(doing
== DoingPermissionsDir
)
1970 if(!installer
.CheckPermissions(args
[i
], permissions_dir
))
1975 else if(doing
== DoingPermissionsMatch
)
1977 if(!installer
.CheckPermissions(
1978 args
[i
], current_match_rule
->Properties
.Permissions
))
1983 else if(doing
== DoingSelf24
)
1985 // Ignore these arguments for compatibility. This should be
1986 // reached only when CMake 2.4 is installing the current
1987 // CMake. It can be removed when CMake 2.6 or higher is
1988 // required to build CMake.
1992 this->SetError("called with inappropriate arguments");
1997 // now check and postprocess what has been parsed
1998 if ( files
.size() == 0 )
2000 // nothing to do, no files were listed.
2001 // if this is handled as error, INSTALL_FILES() creates an invalid
2002 // cmake_install.cmake script with no FILES() arguments if no files were
2003 // given to INSTALL_FILES(). This was accepted with CMake 2.4.x.
2007 // Check rename form.
2010 if(itype
!= cmTarget::INSTALL_FILES
&&
2011 itype
!= cmTarget::INSTALL_PROGRAMS
)
2013 this->SetError("INSTALL option RENAME may be used only with "
2014 "FILES or PROGRAMS.");
2017 if(files
.size() > 1)
2019 this->SetError("INSTALL option RENAME may be used only with "
2025 if (this->HandleInstallDestination(installer
, destination
) == false)
2030 if(properties
.find("VERSION") != properties
.end())
2033 e
<< "INSTALL called with old-style VERSION property. "
2034 << "This script was generated with an older version of CMake. "
2035 << "Re-run this cmake version on your build tree.";
2036 this->SetError(e
.str().c_str());
2039 if(properties
.find("SOVERSION") != properties
.end())
2042 e
<< "INSTALL called with old-style SOVERSION property. "
2043 << "This script was generated with an older version of CMake. "
2044 << "Re-run this cmake version on your build tree.";
2045 this->SetError(e
.str().c_str());
2049 this->GetTargetTypeFromString(stype
, itype
);
2051 this->HandleInstallPermissions(installer
,
2055 use_given_permissions_file
,
2056 use_given_permissions_dir
,
2057 use_source_permissions
);
2062 //----------------------------------------------------------------------------
2063 bool cmFileCommand::DoInstall( cmFileInstaller
& installer
,
2065 const std::string
& rename
,
2066 const std::string
& destination
,
2067 const std::vector
<std::string
>& files
,
2068 const bool optional
)
2070 typedef std::set
<cmStdString
>::const_iterator iter_type
;
2072 // Check whether files should be copied always or only if they have
2075 cmSystemTools::IsOn(cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS"));
2077 // Handle each file listed.
2078 for (std::vector
<std::string
>::size_type i
= 0; i
< files
.size(); i
++ )
2080 // Split the input file into its directory and name components.
2081 std::vector
<std::string
> fromPathComponents
;
2082 cmSystemTools::SplitPath(files
[i
].c_str(), fromPathComponents
);
2083 std::string fromName
= *(fromPathComponents
.end()-1);
2084 std::string fromDir
= cmSystemTools::JoinPath(fromPathComponents
.begin(),
2085 fromPathComponents
.end()-1);
2087 // Compute the full path to the destination file.
2088 std::string toFile
= destination
;
2089 std::string
const& toName
= rename
.empty()? fromName
: rename
;
2096 // Construct the full path to the source file. The file name may
2097 // have been changed above.
2098 std::string fromFile
= fromDir
;
2099 if(!fromName
.empty())
2102 fromFile
+= fromName
;
2105 std::string message
;
2106 if(!cmSystemTools::SameFile(fromFile
.c_str(), toFile
.c_str()))
2108 if(itype
== cmTarget::INSTALL_DIRECTORY
&&
2109 (fromFile
.empty() ||
2110 cmSystemTools::FileIsDirectory(fromFile
.c_str())))
2112 // Try installing this directory.
2113 if(!installer
.InstallDirectory(fromFile
.c_str(), toFile
.c_str(),
2119 else if(cmSystemTools::FileExists(fromFile
.c_str()))
2121 // Install this file.
2122 if(!installer
.InstallFile(fromFile
.c_str(), toFile
.c_str(),
2130 // The input file does not exist and installation is not optional.
2132 e
<< "INSTALL cannot find file \"" << fromFile
<< "\" to install.";
2133 this->SetError(e
.str().c_str());
2142 //----------------------------------------------------------------------------
2143 bool cmFileCommand::HandleRelativePathCommand(
2144 std::vector
<std::string
> const& args
)
2146 if(args
.size() != 4 )
2148 this->SetError("called with incorrect number of arguments");
2152 const std::string
& outVar
= args
[1];
2153 const std::string
& directoryName
= args
[2];
2154 const std::string
& fileName
= args
[3];
2156 if(!cmSystemTools::FileIsFullPath(directoryName
.c_str()))
2158 std::string errstring
=
2159 "RelativePath must be passed a full path to the directory: "
2161 this->SetError(errstring
.c_str());
2164 if(!cmSystemTools::FileIsFullPath(fileName
.c_str()))
2166 std::string errstring
=
2167 "RelativePath must be passed a full path to the file: "
2169 this->SetError(errstring
.c_str());
2173 std::string res
= cmSystemTools::RelativePath(directoryName
.c_str(),
2175 this->Makefile
->AddDefinition(outVar
.c_str(),
2181 //----------------------------------------------------------------------------
2182 bool cmFileCommand::HandleRename(std::vector
<std::string
> const& args
)
2184 if(args
.size() != 3)
2186 this->SetError("given incorrect number of arguments.");
2190 // Compute full path for old and new names.
2191 std::string oldname
= args
[1];
2192 if(!cmsys::SystemTools::FileIsFullPath(oldname
.c_str()))
2194 oldname
= this->Makefile
->GetCurrentDirectory();
2195 oldname
+= "/" + args
[1];
2197 std::string newname
= args
[2];
2198 if(!cmsys::SystemTools::FileIsFullPath(newname
.c_str()))
2200 newname
= this->Makefile
->GetCurrentDirectory();
2201 newname
+= "/" + args
[2];
2204 if(!cmSystemTools::RenameFile(oldname
.c_str(), newname
.c_str()))
2206 std::string err
= cmSystemTools::GetLastSystemError();
2208 e
<< "RENAME failed to rename\n"
2209 << " " << oldname
<< "\n"
2211 << " " << newname
<< "\n"
2212 << "because: " << err
<< "\n";
2213 this->SetError(e
.str().c_str());
2220 //----------------------------------------------------------------------------
2221 bool cmFileCommand::HandleRemove(std::vector
<std::string
> const& args
,
2225 std::string message
;
2226 std::vector
<std::string
>::const_iterator i
= args
.begin();
2228 i
++; // Get rid of subcommand
2229 for(;i
!= args
.end(); ++i
)
2231 std::string fileName
= *i
;
2232 if(!cmsys::SystemTools::FileIsFullPath(fileName
.c_str()))
2234 fileName
= this->Makefile
->GetCurrentDirectory();
2235 fileName
+= "/" + *i
;
2238 if(cmSystemTools::FileIsDirectory(fileName
.c_str()) && recurse
)
2240 cmSystemTools::RemoveADirectory(fileName
.c_str());
2244 cmSystemTools::RemoveFile(fileName
.c_str());
2250 //----------------------------------------------------------------------------
2251 bool cmFileCommand::HandleCMakePathCommand(std::vector
<std::string
>
2255 std::vector
<std::string
>::const_iterator i
= args
.begin();
2256 if(args
.size() != 3)
2258 this->SetError("FILE(SYSTEM_PATH ENV result) must be called with "
2259 "only three arguments.");
2262 i
++; // Get rid of subcommand
2263 #if defined(_WIN32) && !defined(__CYGWIN__)
2268 std::vector
<cmsys::String
> path
= cmSystemTools::SplitString(i
->c_str(),
2271 const char* var
= i
->c_str();
2273 for(std::vector
<cmsys::String
>::iterator j
= path
.begin();
2274 j
!= path
.end(); ++j
)
2276 if(j
!= path
.begin())
2282 cmSystemTools::ConvertToUnixSlashes(*j
);
2286 *j
= cmSystemTools::ConvertToOutputPath(j
->c_str());
2287 // remove double quotes in the path
2288 cmsys::String
& s
= *j
;
2290 if(s
.size() > 1 && s
[0] == '\"' && s
[s
.size()-1] == '\"')
2292 s
= s
.substr(1,s
.size()-2);
2297 this->Makefile
->AddDefinition(var
, value
.c_str());
2300 #if defined(CMAKE_BUILD_WITH_CMAKE)
2302 // Stuff for curl download
2303 typedef std::vector
<char> cmFileCommandVectorOfChar
;
2306 cmFileCommandWriteMemoryCallback(void *ptr
, size_t size
, size_t nmemb
,
2309 register int realsize
= (int)(size
* nmemb
);
2310 std::ofstream
* fout
= static_cast<std::ofstream
*>(data
);
2311 const char* chPtr
= static_cast<char*>(ptr
);
2312 fout
->write(chPtr
, realsize
);
2317 cmFileCommandCurlDebugCallback(CURL
*, curl_infotype
, char *chPtr
,
2318 size_t size
, void *data
)
2320 cmFileCommandVectorOfChar
*vec
2321 = static_cast<cmFileCommandVectorOfChar
*>(data
);
2322 vec
->insert(vec
->end(), chPtr
, chPtr
+ size
);
2333 cmFileCommand::HandleDownloadCommand(std::vector
<std::string
>
2336 #if defined(CMAKE_BUILD_WITH_CMAKE)
2337 std::vector
<std::string
>::const_iterator i
= args
.begin();
2340 this->SetError("FILE(DOWNLOAD url file) must be called with "
2341 "at least three arguments.");
2344 i
++; // Get rid of subcommand
2345 std::string url
= *i
;
2347 std::string file
= *i
;
2350 std::string verboseLog
;
2351 std::string statusVar
;
2352 while(i
!= args
.end())
2359 timeout
= atof(i
->c_str());
2363 this->SetError("FILE(DOWNLOAD url file TIMEOUT time) missing "
2364 "time for TIMEOUT.");
2368 else if(*i
== "LOG")
2371 if( i
== args
.end())
2373 this->SetError("FILE(DOWNLOAD url file LOG VAR) missing "
2379 else if(*i
== "STATUS")
2382 if( i
== args
.end())
2384 this->SetError("FILE(DOWNLOAD url file STATUS VAR) missing "
2393 std::string dir
= cmSystemTools::GetFilenamePath(file
.c_str());
2394 if(!cmSystemTools::FileExists(dir
.c_str()) &&
2395 !cmSystemTools::MakeDirectory(dir
.c_str()))
2397 std::string errstring
= "FILE(DOWNLOAD ) error; cannot create directory: "
2398 + dir
+ ". Maybe need administrative privileges.";
2399 this->SetError(errstring
.c_str());
2403 std::ofstream
fout(file
.c_str(), std::ios::binary
);
2406 this->SetError("FILE(DOWNLOAD url file TIMEOUT time) can not open "
2411 curl_global_init(CURL_GLOBAL_DEFAULT
);
2412 curl
= curl_easy_init();
2415 this->SetError("FILE(DOWNLOAD ) error "
2416 "initializing curl.");
2420 curl_easy_setopt(curl
, CURLOPT_URL
, url
.c_str());
2421 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
,
2422 cmFileCommandWriteMemoryCallback
);
2423 curl_easy_setopt(curl
, CURLOPT_DEBUGFUNCTION
,
2424 cmFileCommandCurlDebugCallback
);
2425 cmFileCommandVectorOfChar chunkDebug
;
2426 ::curl_easy_setopt(curl
, CURLOPT_FILE
, (void *)&fout
);
2427 ::curl_easy_setopt(curl
, CURLOPT_DEBUGDATA
, (void *)&chunkDebug
);
2428 if(verboseLog
.size())
2430 curl_easy_setopt(curl
, CURLOPT_VERBOSE
, 1);
2434 curl_easy_setopt(curl
, CURLOPT_TIMEOUT
, timeout
);
2436 CURLcode res
= curl_easy_perform(curl
);
2437 /* always cleanup */
2438 curl_easy_cleanup(curl
);
2439 if(statusVar
.size())
2441 cmOStringStream result
;
2442 result
<< (int)res
<< ";\"" << curl_easy_strerror(res
) << "\"";
2443 this->Makefile
->AddDefinition(statusVar
.c_str(),
2444 result
.str().c_str());
2446 curl_global_cleanup();
2447 if(chunkDebug
.size())
2449 chunkDebug
.push_back(0);
2450 if(CURLE_OPERATION_TIMEOUTED
== res
)
2452 std::string output
= &*chunkDebug
.begin();
2454 if(verboseLog
.size())
2456 this->Makefile
->AddDefinition(verboseLog
.c_str(),
2457 &*chunkDebug
.begin());
2461 this->Makefile
->AddDefinition(verboseLog
.c_str(),
2462 &*chunkDebug
.begin());
2466 this->SetError("FILE(DOWNLOAD ) "
2467 "not supported in bootstrap cmake ");