1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmFileCommand.cxx,v $
6 Date: $Date: 2008-09-11 18:34:04 $
7 Version: $Revision: 1.113 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmFileCommand.h"
19 #include "cmHexFileConverter.h"
20 #include "cmFileTimeComparison.h"
22 #if defined(CMAKE_BUILD_WITH_CMAKE)
26 #undef GetCurrentDirectory
27 #include <sys/types.h>
30 #include <cmsys/Directory.hxx>
31 #include <cmsys/Glob.hxx>
32 #include <cmsys/RegularExpression.hxx>
34 // Table of permissions flags.
35 #if defined(_WIN32) && !defined(__CYGWIN__)
36 static mode_t mode_owner_read
= S_IREAD
;
37 static mode_t mode_owner_write
= S_IWRITE
;
38 static mode_t mode_owner_execute
= S_IEXEC
;
39 static mode_t mode_group_read
= 0;
40 static mode_t mode_group_write
= 0;
41 static mode_t mode_group_execute
= 0;
42 static mode_t mode_world_read
= 0;
43 static mode_t mode_world_write
= 0;
44 static mode_t mode_world_execute
= 0;
45 static mode_t mode_setuid
= 0;
46 static mode_t mode_setgid
= 0;
48 static mode_t mode_owner_read
= S_IRUSR
;
49 static mode_t mode_owner_write
= S_IWUSR
;
50 static mode_t mode_owner_execute
= S_IXUSR
;
51 static mode_t mode_group_read
= S_IRGRP
;
52 static mode_t mode_group_write
= S_IWGRP
;
53 static mode_t mode_group_execute
= S_IXGRP
;
54 static mode_t mode_world_read
= S_IROTH
;
55 static mode_t mode_world_write
= S_IWOTH
;
56 static mode_t mode_world_execute
= S_IXOTH
;
57 static mode_t mode_setuid
= S_ISUID
;
58 static mode_t mode_setgid
= S_ISGID
;
63 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
67 this->SetError("must be called with at least two arguments.");
70 std::string subCommand
= args
[0];
71 if ( subCommand
== "WRITE" )
73 return this->HandleWriteCommand(args
, false);
75 else if ( subCommand
== "APPEND" )
77 return this->HandleWriteCommand(args
, true);
79 else if ( subCommand
== "DOWNLOAD" )
81 return this->HandleDownloadCommand(args
);
83 else if ( subCommand
== "READ" )
85 return this->HandleReadCommand(args
);
87 else if ( subCommand
== "STRINGS" )
89 return this->HandleStringsCommand(args
);
91 else if ( subCommand
== "GLOB" )
93 return this->HandleGlobCommand(args
, false);
95 else if ( subCommand
== "GLOB_RECURSE" )
97 return this->HandleGlobCommand(args
, true);
99 else if ( subCommand
== "MAKE_DIRECTORY" )
101 return this->HandleMakeDirectoryCommand(args
);
103 else if ( subCommand
== "REMOVE" )
105 return this->HandleRemove(args
, false);
107 else if ( subCommand
== "REMOVE_RECURSE" )
109 return this->HandleRemove(args
, true);
111 else if ( subCommand
== "INSTALL" )
113 return this->HandleInstallCommand(args
);
115 else if ( subCommand
== "RPATH_CHANGE" || subCommand
== "CHRPATH" )
117 return this->HandleRPathChangeCommand(args
);
119 else if ( subCommand
== "RPATH_CHECK" )
121 return this->HandleRPathCheckCommand(args
);
123 else if ( subCommand
== "RPATH_REMOVE" )
125 return this->HandleRPathRemoveCommand(args
);
127 else if ( subCommand
== "RELATIVE_PATH" )
129 return this->HandleRelativePathCommand(args
);
131 else if ( subCommand
== "TO_CMAKE_PATH" )
133 return this->HandleCMakePathCommand(args
, false);
135 else if ( subCommand
== "TO_NATIVE_PATH" )
137 return this->HandleCMakePathCommand(args
, true);
140 std::string e
= "does not recognize sub-command "+subCommand
;
141 this->SetError(e
.c_str());
145 //----------------------------------------------------------------------------
146 bool cmFileCommand::HandleWriteCommand(std::vector
<std::string
> const& args
,
150 std::vector
<std::string
>::const_iterator i
= args
.begin();
152 i
++; // Get rid of subcommand
154 std::string fileName
= *i
;
155 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
157 fileName
= this->Makefile
->GetCurrentDirectory();
158 fileName
+= "/" + *i
;
163 for(;i
!= args
.end(); ++i
)
167 if ( !this->Makefile
->CanIWriteThisFile(fileName
.c_str()) )
170 = "attempted to write a file: " + fileName
+
171 " into a source directory.";
172 this->SetError(e
.c_str());
173 cmSystemTools::SetFatalErrorOccured();
176 std::string dir
= cmSystemTools::GetFilenamePath(fileName
);
177 cmSystemTools::MakeDirectory(dir
.c_str());
180 #if defined( _MSC_VER ) || defined( __MINGW32__ )
182 #elif defined( __BORLANDC__ )
191 // Set permissions to writable
192 if ( cmSystemTools::GetPermissions(fileName
.c_str(), mode
) )
194 cmSystemTools::SetPermissions(fileName
.c_str(),
195 #if defined( _MSC_VER ) || defined( __MINGW32__ )
202 // If GetPermissions fails, pretend like it is ok. File open will fail if
203 // the file is not writable
204 std::ofstream
file(fileName
.c_str(), append
?std::ios::app
: std::ios::out
);
207 std::string error
= "Internal CMake error when trying to open file: ";
208 error
+= fileName
.c_str();
209 error
+= " for writing.";
210 this->SetError(error
.c_str());
215 cmSystemTools::SetPermissions(fileName
.c_str(), mode
);
219 //----------------------------------------------------------------------------
220 bool cmFileCommand::HandleReadCommand(std::vector
<std::string
> const& args
)
222 if ( args
.size() < 3 )
224 this->SetError("READ must be called with at least two additional "
229 cmCommandArgumentsHelper argHelper
;
230 cmCommandArgumentGroup group
;
232 cmCAString
readArg (&argHelper
, "READ");
233 cmCAString
fileNameArg (&argHelper
, 0);
234 cmCAString
resultArg (&argHelper
, 0);
236 cmCAString
offsetArg (&argHelper
, "OFFSET", &group
);
237 cmCAString
limitArg (&argHelper
, "LIMIT", &group
);
238 cmCAEnabler
hexOutputArg (&argHelper
, "HEX", &group
);
240 fileNameArg
.Follows(&readArg
);
241 resultArg
.Follows(&fileNameArg
);
242 group
.Follows(&resultArg
);
243 argHelper
.Parse(&args
, 0);
245 std::string fileName
= fileNameArg
.GetString();
246 if ( !cmsys::SystemTools::FileIsFullPath(fileName
.c_str()) )
248 fileName
= this->Makefile
->GetCurrentDirectory();
249 fileName
+= "/" + fileNameArg
.GetString();
252 std::string variable
= resultArg
.GetString();
254 // Open the specified file.
255 #if defined(_WIN32) || defined(__CYGWIN__)
256 std::ifstream
file(fileName
.c_str(), std::ios::in
|
257 (hexOutputArg
.IsEnabled() ? std::ios::binary
: std::ios::in
));
259 std::ifstream
file(fileName
.c_str(), std::ios::in
);
264 std::string error
= "Internal CMake error when trying to open file: ";
265 error
+= fileName
.c_str();
266 error
+= " for reading.";
267 this->SetError(error
.c_str());
273 if (limitArg
.GetString().size() > 0)
275 sizeLimit
= atoi(limitArg
.GetCString());
278 // is there an offset?
280 if (offsetArg
.GetString().size() > 0)
282 offset
= atoi(offsetArg
.GetCString());
289 if (hexOutputArg
.IsEnabled())
291 // Convert part of the file into hex code
293 while((sizeLimit
!= 0) && (c
= file
.get(), file
))
296 sprintf(hex
, "%x", c
&0xff);
307 bool has_newline
= false;
308 while (sizeLimit
!= 0 &&
309 cmSystemTools::GetLineFromStream(file
, line
, &has_newline
,
314 sizeLimit
= sizeLimit
- static_cast<long>(line
.size());
331 this->Makefile
->AddDefinition(variable
.c_str(), output
.c_str());
335 //----------------------------------------------------------------------------
336 bool cmFileCommand::HandleStringsCommand(std::vector
<std::string
> const& args
)
340 this->SetError("STRINGS requires a file name and output variable");
344 // Get the file to read.
345 std::string fileName
= args
[1];
346 if(!cmsys::SystemTools::FileIsFullPath(fileName
.c_str()))
348 fileName
= this->Makefile
->GetCurrentDirectory();
349 fileName
+= "/" + args
[1];
352 // Get the variable in which to store the results.
353 std::string outVar
= args
[2];
355 // Parse the options.
364 unsigned int minlen
= 0;
365 unsigned int maxlen
= 0;
366 int limit_input
= -1;
367 int limit_output
= -1;
368 unsigned int limit_count
= 0;
369 cmsys::RegularExpression regex
;
370 bool have_regex
= false;
371 bool newline_consume
= false;
372 bool hex_conversion_enabled
= true;
373 int arg_mode
= arg_none
;
374 for(unsigned int i
=3; i
< args
.size(); ++i
)
376 if(args
[i
] == "LIMIT_INPUT")
378 arg_mode
= arg_limit_input
;
380 else if(args
[i
] == "LIMIT_OUTPUT")
382 arg_mode
= arg_limit_output
;
384 else if(args
[i
] == "LIMIT_COUNT")
386 arg_mode
= arg_limit_count
;
388 else if(args
[i
] == "LENGTH_MINIMUM")
390 arg_mode
= arg_length_minimum
;
392 else if(args
[i
] == "LENGTH_MAXIMUM")
394 arg_mode
= arg_length_maximum
;
396 else if(args
[i
] == "REGEX")
398 arg_mode
= arg_regex
;
400 else if(args
[i
] == "NEWLINE_CONSUME")
402 newline_consume
= true;
405 else if(args
[i
] == "NO_HEX_CONVERSION")
407 hex_conversion_enabled
= false;
410 else if(arg_mode
== arg_limit_input
)
412 if(sscanf(args
[i
].c_str(), "%d", &limit_input
) != 1 ||
416 e
<< "STRINGS option LIMIT_INPUT value \""
417 << args
[i
] << "\" is not an unsigned integer.";
418 this->SetError(e
.str().c_str());
423 else if(arg_mode
== arg_limit_output
)
425 if(sscanf(args
[i
].c_str(), "%d", &limit_output
) != 1 ||
429 e
<< "STRINGS option LIMIT_OUTPUT value \""
430 << args
[i
] << "\" is not an unsigned integer.";
431 this->SetError(e
.str().c_str());
436 else if(arg_mode
== arg_limit_count
)
439 if(sscanf(args
[i
].c_str(), "%d", &count
) != 1 || count
< 0)
442 e
<< "STRINGS option LIMIT_COUNT value \""
443 << args
[i
] << "\" is not an unsigned integer.";
444 this->SetError(e
.str().c_str());
450 else if(arg_mode
== arg_length_minimum
)
453 if(sscanf(args
[i
].c_str(), "%d", &len
) != 1 || len
< 0)
456 e
<< "STRINGS option LENGTH_MINIMUM value \""
457 << args
[i
] << "\" is not an unsigned integer.";
458 this->SetError(e
.str().c_str());
464 else if(arg_mode
== arg_length_maximum
)
467 if(sscanf(args
[i
].c_str(), "%d", &len
) != 1 || len
< 0)
470 e
<< "STRINGS option LENGTH_MAXIMUM value \""
471 << args
[i
] << "\" is not an unsigned integer.";
472 this->SetError(e
.str().c_str());
478 else if(arg_mode
== arg_regex
)
480 if(!regex
.compile(args
[i
].c_str()))
483 e
<< "STRINGS option REGEX value \""
484 << args
[i
] << "\" could not be compiled.";
485 this->SetError(e
.str().c_str());
494 e
<< "STRINGS given unknown argument \""
496 this->SetError(e
.str().c_str());
501 if (hex_conversion_enabled
)
503 // TODO: should work without temp file, but just on a memory buffer
504 std::string binaryFileName
= this->Makefile
->GetCurrentOutputDirectory();
505 binaryFileName
+= cmake::GetCMakeFilesDirectory();
506 binaryFileName
+= "/FileCommandStringsBinaryFile";
507 if(cmHexFileConverter::TryConvert(fileName
.c_str(),binaryFileName
.c_str()))
509 fileName
= binaryFileName
;
513 // Open the specified file.
514 #if defined(_WIN32) || defined(__CYGWIN__)
515 std::ifstream
fin(fileName
.c_str(), std::ios::in
| std::ios::binary
);
517 std::ifstream
fin(fileName
.c_str(), std::ios::in
);
522 e
<< "STRINGS file \"" << fileName
<< "\" cannot be read.";
523 this->SetError(e
.str().c_str());
527 // Parse strings out of the file.
529 std::vector
<std::string
> strings
;
532 while((!limit_count
|| strings
.size() < limit_count
) &&
533 (limit_input
< 0 || static_cast<int>(fin
.tellg()) < limit_input
) &&
534 (c
= fin
.get(), fin
))
538 // A terminating null character has been found. Check if the
539 // current string matches the requirements. Since it was
540 // terminated by a null character, we require that the length be
541 // at least one no matter what the user specified.
542 if(s
.length() >= minlen
&& s
.length() >= 1 &&
543 (!have_regex
|| regex
.find(s
.c_str())))
545 output_size
+= static_cast<int>(s
.size()) + 1;
546 if(limit_output
>= 0 && output_size
>= limit_output
)
551 strings
.push_back(s
);
554 // Reset the string to empty.
557 else if(c
== '\n' && !newline_consume
)
559 // The current line has been terminated. Check if the current
560 // string matches the requirements. The length may now be as
561 // low as zero since blank lines are allowed.
562 if(s
.length() >= minlen
&&
563 (!have_regex
|| regex
.find(s
.c_str())))
565 output_size
+= static_cast<int>(s
.size()) + 1;
566 if(limit_output
>= 0 && output_size
>= limit_output
)
571 strings
.push_back(s
);
574 // Reset the string to empty.
579 // Ignore CR character to make output always have UNIX newlines.
581 else if(c
>= 0x20 && c
< 0x7F || c
== '\t' || c
== '\f' ||
582 (c
== '\n' && newline_consume
))
584 // This is an ASCII character that may be part of a string.
589 // This is a non-string character. Reset the string to emtpy.
593 // Terminate a string if the maximum length is reached.
594 if(maxlen
> 0 && s
.size() == maxlen
)
596 if(s
.length() >= minlen
&&
597 (!have_regex
|| regex
.find(s
.c_str())))
599 output_size
+= static_cast<int>(s
.size()) + 1;
600 if(limit_output
>= 0 && output_size
>= limit_output
)
605 strings
.push_back(s
);
611 // If there is a non-empty current string we have hit the end of the
612 // input file or the input size limit. Check if the current string
613 // matches the requirements.
614 if((!limit_count
|| strings
.size() < limit_count
) &&
615 !s
.empty() && s
.length() >= minlen
&&
616 (!have_regex
|| regex
.find(s
.c_str())))
618 output_size
+= static_cast<int>(s
.size()) + 1;
619 if(limit_output
< 0 || output_size
< limit_output
)
621 strings
.push_back(s
);
625 // Encode the result in a CMake list.
626 const char* sep
= "";
628 for(std::vector
<std::string
>::const_iterator si
= strings
.begin();
629 si
!= strings
.end(); ++si
)
631 // Separate the strings in the output to make it a list.
635 // Store the string in the output, but escape semicolons to
636 // make sure it is a list.
637 std::string
const& sr
= *si
;
638 for(unsigned int i
=0; i
< sr
.size(); ++i
)
648 // Save the output in a makefile variable.
649 this->Makefile
->AddDefinition(outVar
.c_str(), output
.c_str());
653 //----------------------------------------------------------------------------
654 bool cmFileCommand::HandleGlobCommand(std::vector
<std::string
> const& args
,
657 if ( args
.size() < 2 )
659 this->SetError("GLOB requires at least a variable name");
663 std::vector
<std::string
>::const_iterator i
= args
.begin();
665 i
++; // Get rid of subcommand
667 std::string variable
= *i
;
670 g
.SetRecurse(recurse
);
672 bool explicitFollowSymlinks
= false;
673 cmPolicies::PolicyStatus status
=
674 this->Makefile
->GetPolicyStatus(cmPolicies::CMP0009
);
679 case cmPolicies::NEW
:
680 g
.RecurseThroughSymlinksOff();
682 case cmPolicies::OLD
:
683 case cmPolicies::WARN
:
684 case cmPolicies::REQUIRED_IF_USED
:
685 case cmPolicies::REQUIRED_ALWAYS
:
686 g
.RecurseThroughSymlinksOn();
691 std::string output
= "";
693 for ( ; i
!= args
.end(); ++i
)
695 if ( recurse
&& (*i
== "FOLLOW_SYMLINKS") )
697 explicitFollowSymlinks
= true;
698 g
.RecurseThroughSymlinksOn();
700 if ( i
== args
.end() )
703 "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS");
708 if ( *i
== "RELATIVE" )
710 ++i
; // skip RELATIVE
711 if ( i
== args
.end() )
713 this->SetError("GLOB requires a directory after the RELATIVE tag");
716 g
.SetRelative(i
->c_str());
720 this->SetError("GLOB requires a glob expression after the directory");
725 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
727 std::string expr
= this->Makefile
->GetCurrentDirectory();
728 // Handle script mode
729 if ( expr
.size() > 0 )
744 std::vector
<std::string
>::size_type cc
;
745 std::vector
<std::string
>& files
= g
.GetFiles();
746 for ( cc
= 0; cc
< files
.size(); cc
++ )
757 if(recurse
&& !explicitFollowSymlinks
)
761 case cmPolicies::NEW
:
762 // Correct behavior, yay!
764 case cmPolicies::OLD
:
765 // Probably not really the expected behavior, but the author explicitly
766 // asked for the old behavior... no warning.
767 case cmPolicies::WARN
:
768 // Possibly unexpected old behavior *and* we actually traversed
769 // symlinks without being explicitly asked to: warn the author.
770 if(g
.GetFollowedSymlinkCount() != 0)
772 this->Makefile
->IssueMessage(cmake::AUTHOR_WARNING
,
773 this->Makefile
->GetPolicies()->
774 GetPolicyWarning(cmPolicies::CMP0009
));
777 case cmPolicies::REQUIRED_IF_USED
:
778 case cmPolicies::REQUIRED_ALWAYS
:
779 this->SetError("policy CMP0009 error");
780 this->Makefile
->IssueMessage(cmake::FATAL_ERROR
,
781 this->Makefile
->GetPolicies()->
782 GetRequiredPolicyError(cmPolicies::CMP0009
));
787 this->Makefile
->AddDefinition(variable
.c_str(), output
.c_str());
791 //----------------------------------------------------------------------------
792 bool cmFileCommand::HandleMakeDirectoryCommand(
793 std::vector
<std::string
> const& args
)
797 this->SetError("called with incorrect number of arguments");
801 std::vector
<std::string
>::const_iterator i
= args
.begin();
803 i
++; // Get rid of subcommand
806 for ( ; i
!= args
.end(); ++i
)
808 const std::string
* cdir
= &(*i
);
809 if ( !cmsys::SystemTools::FileIsFullPath(i
->c_str()) )
811 expr
= this->Makefile
->GetCurrentDirectory();
815 if ( !this->Makefile
->CanIWriteThisFile(cdir
->c_str()) )
817 std::string e
= "attempted to create a directory: " + *cdir
818 + " into a source directory.";
819 this->SetError(e
.c_str());
820 cmSystemTools::SetFatalErrorOccured();
823 if ( !cmSystemTools::MakeDirectory(cdir
->c_str()) )
825 std::string error
= "problem creating directory: " + *cdir
;
826 this->SetError(error
.c_str());
833 //----------------------------------------------------------------------------
834 // File installation helper class.
835 struct cmFileInstaller
837 // Methods to actually install files.
838 bool InstallFile(const char* fromFile
, const char* toFile
, bool always
);
839 bool InstallDirectory(const char* source
, const char* destination
,
842 // All instances need the file command and makefile using them.
843 cmFileInstaller(cmFileCommand
* fc
, cmMakefile
* mf
):
844 FileCommand(fc
), Makefile(mf
), DestDirLength(0), MatchlessFiles(true)
846 // Get the current manifest.
848 this->Makefile
->GetSafeDefinition("CMAKE_INSTALL_MANIFEST_FILES");
852 // Save the updated install manifest.
853 this->Makefile
->AddDefinition("CMAKE_INSTALL_MANIFEST_FILES",
854 this->Manifest
.c_str());
858 cmFileCommand
* FileCommand
;
859 cmMakefile
* Makefile
;
860 cmFileTimeComparison FileTimes
;
863 // The length of the destdir setting.
866 // Whether to install a file not matching any expression.
869 // The current file manifest (semicolon separated list).
870 std::string Manifest
;
872 // Permissions for files and directories installed by this object.
873 mode_t FilePermissions
;
874 mode_t DirPermissions
;
876 // Properties set by pattern and regex match rules.
877 struct MatchProperties
881 MatchProperties(): Exclude(false), Permissions(0) {}
885 cmsys::RegularExpression Regex
;
886 MatchProperties Properties
;
887 std::string RegexString
;
888 MatchRule(std::string
const& regex
):
889 Regex(regex
.c_str()), RegexString(regex
) {}
891 std::vector
<MatchRule
> MatchRules
;
893 // Get the properties from rules matching this input file.
894 MatchProperties
CollectMatchProperties(const char* file
,
897 // Match rules are case-insensitive on some platforms.
898 #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
899 std::string lower
= cmSystemTools::LowerCase(file
);
900 file
= lower
.c_str();
903 // Collect properties from all matching rules.
904 bool matched
= false;
905 MatchProperties result
;
906 for(std::vector
<MatchRule
>::iterator mr
= this->MatchRules
.begin();
907 mr
!= this->MatchRules
.end(); ++mr
)
909 if(mr
->Regex
.find(file
))
912 result
.Exclude
|= mr
->Properties
.Exclude
;
913 result
.Permissions
|= mr
->Properties
.Permissions
;
916 if(!matched
&& !this->MatchlessFiles
&& !isDirectory
)
918 result
.Exclude
= true;
923 // Append a file to the installation manifest.
924 void ManifestAppend(std::string
const& file
)
926 this->Manifest
+= ";";
927 this->Manifest
+= file
.substr(this->DestDirLength
);
930 // Translate an argument to a permissions bit.
931 bool CheckPermissions(std::string
const& arg
, mode_t
& permissions
)
933 if(arg
== "OWNER_READ") { permissions
|= mode_owner_read
; }
934 else if(arg
== "OWNER_WRITE") { permissions
|= mode_owner_write
; }
935 else if(arg
== "OWNER_EXECUTE") { permissions
|= mode_owner_execute
; }
936 else if(arg
== "GROUP_READ") { permissions
|= mode_group_read
; }
937 else if(arg
== "GROUP_WRITE") { permissions
|= mode_group_write
; }
938 else if(arg
== "GROUP_EXECUTE") { permissions
|= mode_group_execute
; }
939 else if(arg
== "WORLD_READ") { permissions
|= mode_world_read
; }
940 else if(arg
== "WORLD_WRITE") { permissions
|= mode_world_write
; }
941 else if(arg
== "WORLD_EXECUTE") { permissions
|= mode_world_execute
; }
942 else if(arg
== "SETUID") { permissions
|= mode_setuid
; }
943 else if(arg
== "SETGID") { permissions
|= mode_setgid
; }
947 e
<< "INSTALL given invalid permission \"" << arg
<< "\".";
948 this->FileCommand
->SetError(e
.str().c_str());
955 bool InstallSymlink(const char* fromFile
, const char* toFile
, bool always
);
958 //----------------------------------------------------------------------------
959 bool cmFileInstaller::InstallSymlink(const char* fromFile
, const char* toFile
,
962 // Read the original symlink.
963 std::string symlinkTarget
;
964 if(!cmSystemTools::ReadSymlink(fromFile
, symlinkTarget
))
967 e
<< "INSTALL cannot read symlink \"" << fromFile
968 << "\" to duplicate at \"" << toFile
<< "\".";
969 this->FileCommand
->SetError(e
.str().c_str());
973 // Compare the symlink value to that at the destination if not
974 // always installing.
978 std::string oldSymlinkTarget
;
979 if(cmSystemTools::ReadSymlink(toFile
, oldSymlinkTarget
))
981 if(symlinkTarget
== oldSymlinkTarget
)
988 // Inform the user about this file installation.
989 std::string message
= (copy
? "Installing: " : "Up-to-date: ");
991 this->Makefile
->DisplayStatus(message
.c_str(), -1);
995 // Remove the destination file so we can always create the symlink.
996 cmSystemTools::RemoveFile(toFile
);
998 // Create the symlink.
999 if(!cmSystemTools::CreateSymlink(symlinkTarget
.c_str(), toFile
))
1002 e
<< "INSTALL cannot duplicate symlink \"" << fromFile
1003 << "\" at \"" << toFile
<< "\".";
1004 this->FileCommand
->SetError(e
.str().c_str());
1009 // Add the file to the manifest.
1010 this->ManifestAppend(toFile
);
1015 //----------------------------------------------------------------------------
1016 bool cmFileInstaller::InstallFile(const char* fromFile
, const char* toFile
,
1019 // Collect any properties matching this file name.
1020 MatchProperties match_properties
=
1021 this->CollectMatchProperties(fromFile
, false);
1023 // Skip the file if it is excluded.
1024 if(match_properties
.Exclude
)
1029 // Short-circuit for symbolic links.
1030 if(cmSystemTools::FileIsSymlink(fromFile
))
1032 return this->InstallSymlink(fromFile
, toFile
, always
);
1035 // Determine whether we will copy the file.
1039 // If both files exist with the same time do not copy.
1040 if(!this->FileTimes
.FileTimesDiffer(fromFile
, toFile
))
1046 // Inform the user about this file installation.
1047 std::string message
= (copy
? "Installing: " : "Up-to-date: ");
1049 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1052 if(copy
&& !cmSystemTools::CopyAFile(fromFile
, toFile
, true))
1055 e
<< "INSTALL cannot copy file \"" << fromFile
1056 << "\" to \"" << toFile
<< "\".";
1057 this->FileCommand
->SetError(e
.str().c_str());
1061 // Add the file to the manifest.
1062 this->ManifestAppend(toFile
);
1064 // Set the file modification time of the destination file.
1067 cmSystemTools::CopyFileTime(fromFile
, toFile
);
1070 // Set permissions of the destination file.
1071 mode_t permissions
= (match_properties
.Permissions
?
1072 match_properties
.Permissions
: this->FilePermissions
);
1075 // No permissions were explicitly provided but the user requested
1076 // that the source file permissions be used.
1077 cmSystemTools::GetPermissions(fromFile
, permissions
);
1079 if(permissions
&& !cmSystemTools::SetPermissions(toFile
, permissions
))
1082 e
<< "Problem setting permissions on file \"" << toFile
<< "\"";
1083 this->FileCommand
->SetError(e
.str().c_str());
1090 //----------------------------------------------------------------------------
1091 bool cmFileInstaller::InstallDirectory(const char* source
,
1092 const char* destination
,
1095 // Collect any properties matching this directory name.
1096 MatchProperties match_properties
=
1097 this->CollectMatchProperties(source
, true);
1099 // Skip the directory if it is excluded.
1100 if(match_properties
.Exclude
)
1105 // Short-circuit for symbolic links.
1106 if(cmSystemTools::FileIsSymlink(source
))
1108 return this->InstallSymlink(source
, destination
, always
);
1111 // Inform the user about this directory installation.
1112 std::string message
= "Installing: ";
1113 message
+= destination
;
1114 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1116 // Make sure the destination directory exists.
1117 if(!cmSystemTools::MakeDirectory(destination
))
1122 // Compute the requested permissions for the destination directory.
1123 mode_t permissions
= (match_properties
.Permissions
?
1124 match_properties
.Permissions
: this->DirPermissions
);
1127 // No permissions were explicitly provided but the user requested
1128 // that the source directory permissions be used.
1129 cmSystemTools::GetPermissions(source
, permissions
);
1132 // Compute the set of permissions required on this directory to
1133 // recursively install files and subdirectories safely.
1134 mode_t required_permissions
=
1135 mode_owner_read
| mode_owner_write
| mode_owner_execute
;
1137 // If the required permissions are specified it is safe to set the
1138 // final permissions now. Otherwise we must add the required
1139 // permissions temporarily during file installation.
1140 mode_t permissions_before
= 0;
1141 mode_t permissions_after
= 0;
1142 if(permissions
& required_permissions
)
1144 permissions_before
= permissions
;
1148 permissions_before
= permissions
| required_permissions
;
1149 permissions_after
= permissions
;
1152 // Set the required permissions of the destination directory.
1153 if(permissions_before
&&
1154 !cmSystemTools::SetPermissions(destination
, permissions_before
))
1157 e
<< "Problem setting permissions on directory \""
1158 << destination
<< "\"";
1159 this->FileCommand
->SetError(e
.str().c_str());
1163 // Load the directory contents to traverse it recursively.
1164 cmsys::Directory dir
;
1165 if(source
&& *source
)
1169 unsigned long numFiles
= static_cast<unsigned long>(dir
.GetNumberOfFiles());
1170 for(unsigned long fileNum
= 0; fileNum
< numFiles
; ++fileNum
)
1172 if(!(strcmp(dir
.GetFile(fileNum
), ".") == 0 ||
1173 strcmp(dir
.GetFile(fileNum
), "..") == 0))
1175 cmsys_stl::string fromPath
= source
;
1177 fromPath
+= dir
.GetFile(fileNum
);
1178 if(cmSystemTools::FileIsDirectory(fromPath
.c_str()))
1180 cmsys_stl::string toDir
= destination
;
1182 toDir
+= dir
.GetFile(fileNum
);
1183 if(!this->InstallDirectory(fromPath
.c_str(), toDir
.c_str(), always
))
1190 // Install this file.
1191 std::string toFile
= destination
;
1193 toFile
+= dir
.GetFile(fileNum
);
1194 if(!this->InstallFile(fromPath
.c_str(), toFile
.c_str(), always
))
1202 // Set the requested permissions of the destination directory.
1203 if(permissions_after
&&
1204 !cmSystemTools::SetPermissions(destination
, permissions_after
))
1207 e
<< "Problem setting permissions on directory \"" << destination
<< "\"";
1208 this->FileCommand
->SetError(e
.str().c_str());
1215 //----------------------------------------------------------------------------
1216 void cmFileCommand::HandleInstallPermissions(cmFileInstaller
& installer
,
1217 mode_t
& permissions_file
,
1218 mode_t
& permissions_dir
,
1220 bool use_given_permissions_file
,
1221 bool use_given_permissions_dir
,
1222 bool use_source_permissions
) const
1224 // Choose a default for shared library permissions.
1225 bool install_so_no_exe
= this->Makefile
->IsOn("CMAKE_INSTALL_SO_NO_EXE");
1226 // If file permissions were not specified set default permissions
1227 // for this target type.
1228 if(!use_given_permissions_file
&& !use_source_permissions
)
1232 case cmTarget::SHARED_LIBRARY
:
1233 case cmTarget::MODULE_LIBRARY
:
1234 if(install_so_no_exe
)
1236 // Use read/write permissions.
1237 permissions_file
= 0;
1238 permissions_file
|= mode_owner_read
;
1239 permissions_file
|= mode_owner_write
;
1240 permissions_file
|= mode_group_read
;
1241 permissions_file
|= mode_world_read
;
1244 case cmTarget::EXECUTABLE
:
1245 case cmTarget::INSTALL_PROGRAMS
:
1246 // Use read/write/executable permissions.
1247 permissions_file
= 0;
1248 permissions_file
|= mode_owner_read
;
1249 permissions_file
|= mode_owner_write
;
1250 permissions_file
|= mode_owner_execute
;
1251 permissions_file
|= mode_group_read
;
1252 permissions_file
|= mode_group_execute
;
1253 permissions_file
|= mode_world_read
;
1254 permissions_file
|= mode_world_execute
;
1257 // Use read/write permissions.
1258 permissions_file
= 0;
1259 permissions_file
|= mode_owner_read
;
1260 permissions_file
|= mode_owner_write
;
1261 permissions_file
|= mode_group_read
;
1262 permissions_file
|= mode_world_read
;
1267 // If directory permissions were not specified set default permissions.
1268 if(!use_given_permissions_dir
&& !use_source_permissions
)
1270 // Use read/write/executable permissions.
1271 permissions_dir
= 0;
1272 permissions_dir
|= mode_owner_read
;
1273 permissions_dir
|= mode_owner_write
;
1274 permissions_dir
|= mode_owner_execute
;
1275 permissions_dir
|= mode_group_read
;
1276 permissions_dir
|= mode_group_execute
;
1277 permissions_dir
|= mode_world_read
;
1278 permissions_dir
|= mode_world_execute
;
1280 // Set the installer permissions.
1281 installer
.FilePermissions
= permissions_file
;
1282 installer
.DirPermissions
= permissions_dir
;
1285 //----------------------------------------------------------------------------
1287 ::GetTargetTypeFromString(const std::string
& stype
, int& itype
) const
1289 if ( stype
== "EXECUTABLE" )
1291 itype
= cmTarget::EXECUTABLE
;
1293 else if ( stype
== "PROGRAM" )
1295 itype
= cmTarget::INSTALL_PROGRAMS
;
1297 else if ( stype
== "STATIC_LIBRARY" )
1299 itype
= cmTarget::STATIC_LIBRARY
;
1301 else if ( stype
== "SHARED_LIBRARY" )
1303 itype
= cmTarget::SHARED_LIBRARY
;
1305 else if ( stype
== "MODULE" )
1307 itype
= cmTarget::MODULE_LIBRARY
;
1309 else if ( stype
== "DIRECTORY" )
1311 itype
= cmTarget::INSTALL_DIRECTORY
;
1316 //----------------------------------------------------------------------------
1317 bool cmFileCommand::HandleInstallDestination(cmFileInstaller
& installer
,
1318 std::string
& destination
)
1320 // allow for / to be a valid destination
1321 if ( destination
.size() < 2 && destination
!= "/" )
1323 this->SetError("called with inapropriate arguments. "
1324 "No DESTINATION provided or .");
1328 const char* destdir
= cmSystemTools::GetEnv("DESTDIR");
1329 if ( destdir
&& *destdir
)
1331 std::string sdestdir
= destdir
;
1332 cmSystemTools::ConvertToUnixSlashes(sdestdir
);
1333 char ch1
= destination
[0];
1334 char ch2
= destination
[1];
1336 if ( destination
.size() > 2 )
1338 ch3
= destination
[2];
1344 if ( ( ch1
>= 'a' && ch1
<= 'z' || ch1
>= 'A' && ch1
<= 'Z' ) &&
1348 // let's do some destdir magic:
1361 // This is relative path on unix or windows. Since we are doing
1362 // destdir, this case does not make sense.
1363 this->SetError("called with relative DESTINATION. This "
1364 "does not make sense when using DESTDIR. Specify "
1365 "absolute path or remove DESTDIR environment variable.");
1373 // looks like a network path.
1374 std::string message
= "called with network path DESTINATION. This "
1375 "does not make sense when using DESTDIR. Specify local "
1376 "absolute path or remove DESTDIR environment variable."
1378 message
+= destination
;
1379 this->SetError(message
.c_str());
1383 destination
= sdestdir
+ (destination
.c_str() + skip
);
1384 installer
.DestDirLength
= int(sdestdir
.size());
1387 if ( !cmSystemTools::FileExists(destination
.c_str()) )
1389 if ( !cmSystemTools::MakeDirectory(destination
.c_str()) )
1391 std::string errstring
= "cannot create directory: " + destination
+
1392 ". Maybe need administrative privileges.";
1393 this->SetError(errstring
.c_str());
1397 if ( !cmSystemTools::FileIsDirectory(destination
.c_str()) )
1399 std::string errstring
= "INSTALL destination: " + destination
+
1400 " is not a directory.";
1401 this->SetError(errstring
.c_str());
1407 //----------------------------------------------------------------------------
1409 cmFileCommand::HandleRPathChangeCommand(std::vector
<std::string
> const& args
)
1411 // Evaluate arguments.
1412 const char* file
= 0;
1413 const char* oldRPath
= 0;
1414 const char* newRPath
= 0;
1415 enum Doing
{ DoingNone
, DoingFile
, DoingOld
, DoingNew
};
1416 Doing doing
= DoingNone
;
1417 for(unsigned int i
=1; i
< args
.size(); ++i
)
1419 if(args
[i
] == "OLD_RPATH")
1423 else if(args
[i
] == "NEW_RPATH")
1427 else if(args
[i
] == "FILE")
1431 else if(doing
== DoingFile
)
1433 file
= args
[i
].c_str();
1436 else if(doing
== DoingOld
)
1438 oldRPath
= args
[i
].c_str();
1441 else if(doing
== DoingNew
)
1443 newRPath
= args
[i
].c_str();
1449 e
<< "RPATH_CHANGE given unknown argument " << args
[i
];
1450 this->SetError(e
.str().c_str());
1456 this->SetError("RPATH_CHANGE not given FILE option.");
1461 this->SetError("RPATH_CHANGE not given OLD_RPATH option.");
1466 this->SetError("RPATH_CHANGE not given NEW_RPATH option.");
1469 if(!cmSystemTools::FileExists(file
, true))
1472 e
<< "RPATH_CHANGE given FILE \"" << file
<< "\" that does not exist.";
1473 this->SetError(e
.str().c_str());
1476 bool success
= true;
1477 cmSystemToolsFileTime
* ft
= cmSystemTools::FileTimeNew();
1478 bool have_ft
= cmSystemTools::FileTimeGet(file
, ft
);
1481 if(!cmSystemTools::ChangeRPath(file
, oldRPath
, newRPath
, &emsg
, &changed
))
1484 e
<< "RPATH_CHANGE could not write new RPATH:\n"
1485 << " " << newRPath
<< "\n"
1487 << " " << file
<< "\n"
1489 this->SetError(e
.str().c_str());
1496 std::string message
= "Set runtime path of \"";
1498 message
+= "\" to \"";
1499 message
+= newRPath
;
1501 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1505 cmSystemTools::FileTimeSet(file
, ft
);
1508 cmSystemTools::FileTimeDelete(ft
);
1512 //----------------------------------------------------------------------------
1514 cmFileCommand::HandleRPathRemoveCommand(std::vector
<std::string
> const& args
)
1516 // Evaluate arguments.
1517 const char* file
= 0;
1518 enum Doing
{ DoingNone
, DoingFile
};
1519 Doing doing
= DoingNone
;
1520 for(unsigned int i
=1; i
< args
.size(); ++i
)
1522 if(args
[i
] == "FILE")
1526 else if(doing
== DoingFile
)
1528 file
= args
[i
].c_str();
1534 e
<< "RPATH_REMOVE given unknown argument " << args
[i
];
1535 this->SetError(e
.str().c_str());
1541 this->SetError("RPATH_REMOVE not given FILE option.");
1544 if(!cmSystemTools::FileExists(file
, true))
1547 e
<< "RPATH_REMOVE 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::RemoveRPath(file
, &emsg
, &removed
))
1559 e
<< "RPATH_REMOVE could not remove RPATH from file:\n"
1560 << " " << file
<< "\n"
1562 this->SetError(e
.str().c_str());
1569 std::string message
= "Removed runtime path from \"";
1572 this->Makefile
->DisplayStatus(message
.c_str(), -1);
1576 cmSystemTools::FileTimeSet(file
, ft
);
1579 cmSystemTools::FileTimeDelete(ft
);
1583 //----------------------------------------------------------------------------
1585 cmFileCommand::HandleRPathCheckCommand(std::vector
<std::string
> const& args
)
1587 // Evaluate arguments.
1588 const char* file
= 0;
1589 const char* rpath
= 0;
1590 enum Doing
{ DoingNone
, DoingFile
, DoingRPath
};
1591 Doing doing
= DoingNone
;
1592 for(unsigned int i
=1; i
< args
.size(); ++i
)
1594 if(args
[i
] == "RPATH")
1598 else if(args
[i
] == "FILE")
1602 else if(doing
== DoingFile
)
1604 file
= args
[i
].c_str();
1607 else if(doing
== DoingRPath
)
1609 rpath
= args
[i
].c_str();
1615 e
<< "RPATH_CHECK given unknown argument " << args
[i
];
1616 this->SetError(e
.str().c_str());
1622 this->SetError("RPATH_CHECK not given FILE option.");
1627 this->SetError("RPATH_CHECK not given RPATH option.");
1631 // If the file exists but does not have the desired RPath then
1632 // delete it. This is used during installation to re-install a file
1633 // if its RPath will change.
1634 if(cmSystemTools::FileExists(file
, true) &&
1635 !cmSystemTools::CheckRPath(file
, rpath
))
1637 cmSystemTools::RemoveFile(file
);
1643 //----------------------------------------------------------------------------
1644 bool cmFileCommand::HandleInstallCommand(std::vector
<std::string
> const& args
)
1646 if ( args
.size() < 6 )
1648 this->SetError("called with incorrect number of arguments");
1652 // Construct a file installer object.
1653 cmFileInstaller
installer(this, this->Makefile
);
1655 std::string rename
= "";
1656 std::string destination
= "";
1658 std::vector
<std::string
> files
;
1659 int itype
= cmTarget::INSTALL_FILES
;
1661 std::map
<cmStdString
, const char*> properties
;
1662 bool optional
= false;
1663 bool result
= this->ParseInstallArgs(args
, installer
, properties
,
1664 itype
, rename
, destination
, files
,
1668 result
= this->DoInstall(installer
,
1669 itype
, rename
, destination
, files
, optional
);
1674 //----------------------------------------------------------------------------
1675 bool cmFileCommand::ParseInstallArgs(std::vector
<std::string
> const& args
,
1676 cmFileInstaller
& installer
,
1677 std::map
<cmStdString
, const char*>& properties
,
1679 std::string
& rename
,
1680 std::string
& destination
,
1681 std::vector
<std::string
>& files
,
1684 std::string stype
= "FILES";
1685 bool doing_files
= false;
1686 bool doing_properties
= false;
1687 bool doing_permissions_file
= false;
1688 bool doing_permissions_dir
= false;
1689 bool doing_permissions_match
= false;
1690 bool use_given_permissions_file
= false;
1691 bool use_given_permissions_dir
= false;
1692 bool use_source_permissions
= false;
1693 mode_t permissions_file
= 0;
1694 mode_t permissions_dir
= 0;
1696 cmFileInstaller::MatchRule
* current_match_rule
= 0;
1697 std::vector
<std::string
>::size_type i
= 0;
1698 i
++; // Get rid of subcommand
1699 for ( ; i
!= args
.size(); ++i
)
1701 const std::string
* cstr
= &args
[i
];
1702 if ( *cstr
== "DESTINATION" && i
< args
.size()-1 )
1704 if(current_match_rule
)
1707 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1708 this->SetError(e
.str().c_str());
1713 destination
= args
[i
];
1714 doing_files
= false;
1715 doing_properties
= false;
1716 doing_permissions_file
= false;
1717 doing_permissions_dir
= false;
1719 else if ( *cstr
== "TYPE" && i
< args
.size()-1 )
1721 if(current_match_rule
)
1724 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1725 this->SetError(e
.str().c_str());
1731 if ( args
[i
+1] == "OPTIONAL" )
1736 doing_properties
= false;
1737 doing_files
= false;
1738 doing_permissions_file
= false;
1739 doing_permissions_dir
= false;
1741 else if ( *cstr
== "RENAME" && i
< args
.size()-1 )
1743 if(current_match_rule
)
1746 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1747 this->SetError(e
.str().c_str());
1753 doing_properties
= false;
1754 doing_files
= false;
1755 doing_permissions_file
= false;
1756 doing_permissions_dir
= false;
1758 else if ( *cstr
== "REGEX" && i
< args
.size()-1 )
1761 installer
.MatchRules
.push_back(cmFileInstaller::MatchRule(args
[i
]));
1762 current_match_rule
= &*(installer
.MatchRules
.end()-1);
1763 if(!current_match_rule
->Regex
.is_valid())
1766 e
<< "INSTALL could not compile REGEX \"" << args
[i
] << "\".";
1767 this->SetError(e
.str().c_str());
1770 doing_properties
= false;
1771 doing_files
= false;
1772 doing_permissions_file
= false;
1773 doing_permissions_dir
= false;
1775 else if ( *cstr
== "EXCLUDE" )
1777 // Add this property to the current match rule.
1778 if(!current_match_rule
)
1781 e
<< "INSTALL does not allow \""
1782 << *cstr
<< "\" before a REGEX is given.";
1783 this->SetError(e
.str().c_str());
1786 current_match_rule
->Properties
.Exclude
= true;
1787 doing_permissions_match
= true;
1789 else if ( *cstr
== "PROPERTIES" )
1791 if(current_match_rule
)
1794 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1795 this->SetError(e
.str().c_str());
1799 doing_properties
= true;
1800 doing_files
= false;
1801 doing_permissions_file
= false;
1802 doing_permissions_dir
= false;
1804 else if ( *cstr
== "PERMISSIONS" )
1806 if(current_match_rule
)
1808 doing_permissions_match
= true;
1809 doing_permissions_file
= false;
1813 doing_permissions_match
= false;
1814 doing_permissions_file
= true;
1815 use_given_permissions_file
= true;
1817 doing_properties
= false;
1818 doing_files
= false;
1819 doing_permissions_dir
= false;
1821 else if ( *cstr
== "DIR_PERMISSIONS" )
1823 if(current_match_rule
)
1826 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1827 this->SetError(e
.str().c_str());
1831 use_given_permissions_dir
= true;
1832 doing_properties
= false;
1833 doing_files
= false;
1834 doing_permissions_file
= false;
1835 doing_permissions_dir
= true;
1837 else if ( *cstr
== "USE_SOURCE_PERMISSIONS" )
1839 if(current_match_rule
)
1842 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1843 this->SetError(e
.str().c_str());
1847 doing_properties
= false;
1848 doing_files
= false;
1849 doing_permissions_file
= false;
1850 doing_permissions_dir
= false;
1851 use_source_permissions
= true;
1853 else if ( *cstr
== "FILES_MATCHING" )
1855 if(current_match_rule
)
1858 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1859 this->SetError(e
.str().c_str());
1863 doing_properties
= false;
1864 doing_files
= false;
1865 doing_permissions_file
= false;
1866 doing_permissions_dir
= false;
1867 installer
.MatchlessFiles
= false;
1869 else if ( *cstr
== "COMPONENTS" )
1872 e
<< "INSTALL called with old-style COMPONENTS argument. "
1873 << "This script was generated with an older version of CMake. "
1874 << "Re-run this cmake version on your build tree.";
1875 this->SetError(e
.str().c_str());
1878 else if ( *cstr
== "CONFIGURATIONS" )
1881 e
<< "INSTALL called with old-style CONFIGURATIONS argument. "
1882 << "This script was generated with an older version of CMake. "
1883 << "Re-run this cmake version on your build tree.";
1884 this->SetError(e
.str().c_str());
1887 else if ( *cstr
== "FILES" && !doing_files
)
1889 if(current_match_rule
)
1892 e
<< "INSTALL does not allow \"" << *cstr
<< "\" after REGEX.";
1893 this->SetError(e
.str().c_str());
1898 doing_properties
= false;
1899 doing_permissions_file
= false;
1900 doing_permissions_dir
= false;
1902 else if ( doing_properties
&& i
< args
.size()-1 )
1904 properties
[args
[i
]] = args
[i
+1].c_str();
1907 else if ( doing_files
)
1909 files
.push_back(*cstr
);
1911 else if(doing_permissions_file
)
1913 if(!installer
.CheckPermissions(args
[i
], permissions_file
))
1918 else if(doing_permissions_dir
)
1920 if(!installer
.CheckPermissions(args
[i
], permissions_dir
))
1925 else if(doing_permissions_match
)
1927 if(!installer
.CheckPermissions(
1928 args
[i
], current_match_rule
->Properties
.Permissions
))
1935 this->SetError("called with inappropriate arguments");
1940 // now check and postprocess what has been parsed
1941 if ( files
.size() == 0 )
1943 // nothing to do, no files were listed.
1944 // if this is handled as error, INSTALL_FILES() creates an invalid
1945 // cmake_install.cmake script with no FILES() arguments if no files were
1946 // given to INSTALL_FILES(). This was accepted with CMake 2.4.x.
1950 // Check rename form.
1953 if(itype
!= cmTarget::INSTALL_FILES
&&
1954 itype
!= cmTarget::INSTALL_PROGRAMS
)
1956 this->SetError("INSTALL option RENAME may be used only with "
1957 "FILES or PROGRAMS.");
1960 if(files
.size() > 1)
1962 this->SetError("INSTALL option RENAME may be used only with "
1968 if (this->HandleInstallDestination(installer
, destination
) == false)
1973 if(properties
.find("VERSION") != properties
.end())
1976 e
<< "INSTALL called with old-style VERSION property. "
1977 << "This script was generated with an older version of CMake. "
1978 << "Re-run this cmake version on your build tree.";
1979 this->SetError(e
.str().c_str());
1982 if(properties
.find("SOVERSION") != properties
.end())
1985 e
<< "INSTALL called with old-style SOVERSION property. "
1986 << "This script was generated with an older version of CMake. "
1987 << "Re-run this cmake version on your build tree.";
1988 this->SetError(e
.str().c_str());
1992 this->GetTargetTypeFromString(stype
, itype
);
1994 this->HandleInstallPermissions(installer
,
1998 use_given_permissions_file
,
1999 use_given_permissions_dir
,
2000 use_source_permissions
);
2005 //----------------------------------------------------------------------------
2006 bool cmFileCommand::DoInstall( cmFileInstaller
& installer
,
2008 const std::string
& rename
,
2009 const std::string
& destination
,
2010 const std::vector
<std::string
>& files
,
2011 const bool optional
)
2013 typedef std::set
<cmStdString
>::const_iterator iter_type
;
2015 // Check whether files should be copied always or only if they have
2018 cmSystemTools::IsOn(cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS"));
2020 // Handle each file listed.
2021 for (std::vector
<std::string
>::size_type i
= 0; i
< files
.size(); i
++ )
2023 // Split the input file into its directory and name components.
2024 std::vector
<std::string
> fromPathComponents
;
2025 cmSystemTools::SplitPath(files
[i
].c_str(), fromPathComponents
);
2026 std::string fromName
= *(fromPathComponents
.end()-1);
2027 std::string fromDir
= cmSystemTools::JoinPath(fromPathComponents
.begin(),
2028 fromPathComponents
.end()-1);
2030 // Compute the full path to the destination file.
2031 std::string toFile
= destination
;
2032 std::string
const& toName
= rename
.empty()? fromName
: rename
;
2039 // Construct the full path to the source file. The file name may
2040 // have been changed above.
2041 std::string fromFile
= fromDir
;
2042 if(!fromName
.empty())
2045 fromFile
+= fromName
;
2048 std::string message
;
2049 if(!cmSystemTools::SameFile(fromFile
.c_str(), toFile
.c_str()))
2051 if(itype
== cmTarget::INSTALL_DIRECTORY
&&
2052 (fromFile
.empty() ||
2053 cmSystemTools::FileIsDirectory(fromFile
.c_str())))
2055 // Try installing this directory.
2056 if(!installer
.InstallDirectory(fromFile
.c_str(), toFile
.c_str(),
2062 else if(cmSystemTools::FileExists(fromFile
.c_str()))
2064 // Install this file.
2065 if(!installer
.InstallFile(fromFile
.c_str(), toFile
.c_str(),
2073 // The input file does not exist and installation is not optional.
2075 e
<< "INSTALL cannot find file \"" << fromFile
<< "\" to install.";
2076 this->SetError(e
.str().c_str());
2085 //----------------------------------------------------------------------------
2086 bool cmFileCommand::HandleRelativePathCommand(
2087 std::vector
<std::string
> const& args
)
2089 if(args
.size() != 4 )
2091 this->SetError("called with incorrect number of arguments");
2095 const std::string
& outVar
= args
[1];
2096 const std::string
& directoryName
= args
[2];
2097 const std::string
& fileName
= args
[3];
2099 if(!cmSystemTools::FileIsFullPath(directoryName
.c_str()))
2101 std::string errstring
=
2102 "RelativePath must be passed a full path to the directory: "
2104 this->SetError(errstring
.c_str());
2107 if(!cmSystemTools::FileIsFullPath(fileName
.c_str()))
2109 std::string errstring
=
2110 "RelativePath must be passed a full path to the file: "
2112 this->SetError(errstring
.c_str());
2116 std::string res
= cmSystemTools::RelativePath(directoryName
.c_str(),
2118 this->Makefile
->AddDefinition(outVar
.c_str(),
2124 //----------------------------------------------------------------------------
2125 bool cmFileCommand::HandleRemove(std::vector
<std::string
> const& args
,
2129 std::string message
;
2130 std::vector
<std::string
>::const_iterator i
= args
.begin();
2132 i
++; // Get rid of subcommand
2133 for(;i
!= args
.end(); ++i
)
2135 if(cmSystemTools::FileIsDirectory(i
->c_str()) && recurse
)
2137 cmSystemTools::RemoveADirectory(i
->c_str());
2141 cmSystemTools::RemoveFile(i
->c_str());
2147 //----------------------------------------------------------------------------
2148 bool cmFileCommand::HandleCMakePathCommand(std::vector
<std::string
>
2152 std::vector
<std::string
>::const_iterator i
= args
.begin();
2153 if(args
.size() != 3)
2155 this->SetError("FILE(SYSTEM_PATH ENV result) must be called with "
2156 "only three arguments.");
2159 i
++; // Get rid of subcommand
2160 #if defined(_WIN32) && !defined(__CYGWIN__)
2165 std::vector
<cmsys::String
> path
= cmSystemTools::SplitString(i
->c_str(),
2168 const char* var
= i
->c_str();
2170 for(std::vector
<cmsys::String
>::iterator j
= path
.begin();
2171 j
!= path
.end(); ++j
)
2173 if(j
!= path
.begin())
2179 cmSystemTools::ConvertToUnixSlashes(*j
);
2183 *j
= cmSystemTools::ConvertToOutputPath(j
->c_str());
2184 // remove double quotes in the path
2185 cmsys::String
& s
= *j
;
2187 if(s
.size() > 1 && s
[0] == '\"' && s
[s
.size()-1] == '\"')
2189 s
= s
.substr(1,s
.size()-2);
2194 this->Makefile
->AddDefinition(var
, value
.c_str());
2197 #if defined(CMAKE_BUILD_WITH_CMAKE)
2199 // Stuff for curl download
2200 typedef std::vector
<char> cmFileCommandVectorOfChar
;
2203 cmFileCommandWriteMemoryCallback(void *ptr
, size_t size
, size_t nmemb
,
2206 register int realsize
= (int)(size
* nmemb
);
2207 std::ofstream
* fout
= static_cast<std::ofstream
*>(data
);
2208 const char* chPtr
= static_cast<char*>(ptr
);
2209 fout
->write(chPtr
, realsize
);
2214 cmFileCommandCurlDebugCallback(CURL
*, curl_infotype
, char *chPtr
,
2215 size_t size
, void *data
)
2217 cmFileCommandVectorOfChar
*vec
2218 = static_cast<cmFileCommandVectorOfChar
*>(data
);
2219 vec
->insert(vec
->end(), chPtr
, chPtr
+ size
);
2230 cmFileCommand::HandleDownloadCommand(std::vector
<std::string
>
2233 #if defined(CMAKE_BUILD_WITH_CMAKE)
2234 std::vector
<std::string
>::const_iterator i
= args
.begin();
2237 this->SetError("FILE(DOWNLOAD url file) must be called with "
2238 "at least three arguments.");
2241 i
++; // Get rid of subcommand
2242 std::string url
= *i
;
2244 std::string file
= *i
;
2247 std::string verboseLog
;
2248 std::string statusVar
;
2249 while(i
!= args
.end())
2256 timeout
= atof(i
->c_str());
2260 this->SetError("FILE(DOWNLOAD url file TIMEOUT time) missing "
2261 "time for TIMEOUT.");
2265 else if(*i
== "LOG")
2268 if( i
== args
.end())
2270 this->SetError("FILE(DOWNLOAD url file LOG VAR) missing "
2276 else if(*i
== "STATUS")
2279 if( i
== args
.end())
2281 this->SetError("FILE(DOWNLOAD url file STATUS VAR) missing "
2290 std::string dir
= cmSystemTools::GetFilenamePath(file
.c_str());
2291 if(!cmSystemTools::FileExists(dir
.c_str()) &&
2292 !cmSystemTools::MakeDirectory(dir
.c_str()))
2294 std::string errstring
= "FILE(DOWNLOAD ) error; cannot create directory: "
2295 + dir
+ ". Maybe need administrative privileges.";
2296 this->SetError(errstring
.c_str());
2300 std::ofstream
fout(file
.c_str(), std::ios::binary
);
2303 this->SetError("FILE(DOWNLOAD url file TIMEOUT time) can not open "
2308 curl_global_init(CURL_GLOBAL_DEFAULT
);
2309 curl
= curl_easy_init();
2312 this->SetError("FILE(DOWNLOAD ) error "
2313 "initializing curl.");
2317 curl_easy_setopt(curl
, CURLOPT_URL
, url
.c_str());
2318 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
,
2319 cmFileCommandWriteMemoryCallback
);
2320 curl_easy_setopt(curl
, CURLOPT_DEBUGFUNCTION
,
2321 cmFileCommandCurlDebugCallback
);
2322 cmFileCommandVectorOfChar chunkDebug
;
2323 ::curl_easy_setopt(curl
, CURLOPT_FILE
, (void *)&fout
);
2324 ::curl_easy_setopt(curl
, CURLOPT_DEBUGDATA
, (void *)&chunkDebug
);
2325 if(verboseLog
.size())
2327 curl_easy_setopt(curl
, CURLOPT_VERBOSE
, 1);
2331 curl_easy_setopt(curl
, CURLOPT_TIMEOUT
, timeout
);
2333 CURLcode res
= curl_easy_perform(curl
);
2334 /* always cleanup */
2335 curl_easy_cleanup(curl
);
2336 if(statusVar
.size())
2338 cmOStringStream result
;
2339 result
<< (int)res
<< ";\"" << curl_easy_strerror(res
) << "\"";
2340 this->Makefile
->AddDefinition(statusVar
.c_str(),
2341 result
.str().c_str());
2343 curl_global_cleanup();
2344 if(chunkDebug
.size())
2346 chunkDebug
.push_back(0);
2347 if(CURLE_OPERATION_TIMEOUTED
== res
)
2349 std::string output
= &*chunkDebug
.begin();
2351 if(verboseLog
.size())
2353 this->Makefile
->AddDefinition(verboseLog
.c_str(),
2354 &*chunkDebug
.begin());
2358 this->Makefile
->AddDefinition(verboseLog
.c_str(),
2359 &*chunkDebug
.begin());
2363 this->SetError("FILE(DOWNLOAD ) "
2364 "not supported in bootstrap cmake ");