Initial commit.
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmFileCommand.cxx
blobee3775d0958dec65a45ade36d7bdc3db3cdf8ef7
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmFileCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2008/01/23 15:27:59 $
7 Version: $Revision: 1.96 $
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"
18 #include "cmake.h"
19 #include "cmHexFileConverter.h"
20 #include "cmFileTimeComparison.h"
22 #include <sys/types.h>
23 #include <sys/stat.h>
25 #include <cmsys/Directory.hxx>
26 #include <cmsys/Glob.hxx>
27 #include <cmsys/RegularExpression.hxx>
29 // Table of permissions flags.
30 #if defined(_WIN32) && !defined(__CYGWIN__)
31 static mode_t mode_owner_read = S_IREAD;
32 static mode_t mode_owner_write = S_IWRITE;
33 static mode_t mode_owner_execute = S_IEXEC;
34 static mode_t mode_group_read = 0;
35 static mode_t mode_group_write = 0;
36 static mode_t mode_group_execute = 0;
37 static mode_t mode_world_read = 0;
38 static mode_t mode_world_write = 0;
39 static mode_t mode_world_execute = 0;
40 static mode_t mode_setuid = 0;
41 static mode_t mode_setgid = 0;
42 #else
43 static mode_t mode_owner_read = S_IRUSR;
44 static mode_t mode_owner_write = S_IWUSR;
45 static mode_t mode_owner_execute = S_IXUSR;
46 static mode_t mode_group_read = S_IRGRP;
47 static mode_t mode_group_write = S_IWGRP;
48 static mode_t mode_group_execute = S_IXGRP;
49 static mode_t mode_world_read = S_IROTH;
50 static mode_t mode_world_write = S_IWOTH;
51 static mode_t mode_world_execute = S_IXOTH;
52 static mode_t mode_setuid = S_ISUID;
53 static mode_t mode_setgid = S_ISGID;
54 #endif
56 // cmLibraryCommand
57 bool cmFileCommand
58 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
60 if(args.size() < 2 )
62 this->SetError("must be called with at least two arguments.");
63 return false;
65 std::string subCommand = args[0];
66 if ( subCommand == "WRITE" )
68 return this->HandleWriteCommand(args, false);
70 else if ( subCommand == "APPEND" )
72 return this->HandleWriteCommand(args, true);
74 else if ( subCommand == "READ" )
76 return this->HandleReadCommand(args);
78 else if ( subCommand == "STRINGS" )
80 return this->HandleStringsCommand(args);
82 else if ( subCommand == "GLOB" )
84 return this->HandleGlobCommand(args, false);
86 else if ( subCommand == "GLOB_RECURSE" )
88 return this->HandleGlobCommand(args, true);
90 else if ( subCommand == "MAKE_DIRECTORY" )
92 return this->HandleMakeDirectoryCommand(args);
94 else if ( subCommand == "REMOVE" )
96 return this->HandleRemove(args, false);
98 else if ( subCommand == "REMOVE_RECURSE" )
100 return this->HandleRemove(args, true);
102 else if ( subCommand == "INSTALL" )
104 return this->HandleInstallCommand(args);
106 else if ( subCommand == "RELATIVE_PATH" )
108 return this->HandleRelativePathCommand(args);
110 else if ( subCommand == "TO_CMAKE_PATH" )
112 return this->HandleCMakePathCommand(args, false);
114 else if ( subCommand == "TO_NATIVE_PATH" )
116 return this->HandleCMakePathCommand(args, true);
119 std::string e = "does not recognize sub-command "+subCommand;
120 this->SetError(e.c_str());
121 return false;
124 //----------------------------------------------------------------------------
125 bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args,
126 bool append)
128 std::string message;
129 std::vector<std::string>::const_iterator i = args.begin();
131 i++; // Get rid of subcommand
133 std::string fileName = *i;
134 if ( !cmsys::SystemTools::FileIsFullPath(i->c_str()) )
136 fileName = this->Makefile->GetCurrentDirectory();
137 fileName += "/" + *i;
140 i++;
142 for(;i != args.end(); ++i)
144 message += *i;
146 if ( !this->Makefile->CanIWriteThisFile(fileName.c_str()) )
148 std::string e
149 = "attempted to write a file: " + fileName +
150 " into a source directory.";
151 this->SetError(e.c_str());
152 cmSystemTools::SetFatalErrorOccured();
153 return false;
155 std::string dir = cmSystemTools::GetFilenamePath(fileName);
156 cmSystemTools::MakeDirectory(dir.c_str());
158 mode_t mode =
159 #if defined( _MSC_VER ) || defined( __MINGW32__ )
160 S_IREAD | S_IWRITE
161 #elif defined( __BORLANDC__ )
162 S_IRUSR | S_IWUSR
163 #else
164 S_IRUSR | S_IWUSR |
165 S_IRGRP |
166 S_IROTH
167 #endif
170 // Set permissions to writable
171 if ( cmSystemTools::GetPermissions(fileName.c_str(), mode) )
173 cmSystemTools::SetPermissions(fileName.c_str(),
174 #if defined( _MSC_VER ) || defined( __MINGW32__ )
175 S_IREAD | S_IWRITE
176 #else
177 S_IRUSR | S_IWUSR
178 #endif
181 // If GetPermissions fails, pretend like it is ok. File open will fail if
182 // the file is not writable
183 std::ofstream file(fileName.c_str(), append?std::ios::app: std::ios::out);
184 if ( !file )
186 std::string error = "Internal CMake error when trying to open file: ";
187 error += fileName.c_str();
188 error += " for writing.";
189 this->SetError(error.c_str());
190 return false;
192 file << message;
193 file.close();
194 cmSystemTools::SetPermissions(fileName.c_str(), mode);
195 this->Makefile->AddWrittenFile(fileName.c_str());
196 return true;
199 //----------------------------------------------------------------------------
200 bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args)
202 if ( args.size() < 3 )
204 this->SetError("READ must be called with at least two additional "
205 "arguments");
206 return false;
209 cmCommandArgumentsHelper argHelper;
210 cmCommandArgumentGroup group;
212 cmCAString readArg (&argHelper, "READ");
213 cmCAString fileNameArg (&argHelper, 0);
214 cmCAString resultArg (&argHelper, 0);
216 cmCAString offsetArg (&argHelper, "OFFSET", &group);
217 cmCAString limitArg (&argHelper, "LIMIT", &group);
218 cmCAEnabler hexOutputArg (&argHelper, "HEX", &group);
219 readArg.Follows(0);
220 fileNameArg.Follows(&readArg);
221 resultArg.Follows(&fileNameArg);
222 group.Follows(&resultArg);
223 argHelper.Parse(&args, 0);
225 std::string fileName = fileNameArg.GetString();
226 if ( !cmsys::SystemTools::FileIsFullPath(fileName.c_str()) )
228 fileName = this->Makefile->GetCurrentDirectory();
229 fileName += "/" + fileNameArg.GetString();
232 std::string variable = resultArg.GetString();
234 // Open the specified file.
235 #if defined(_WIN32) || defined(__CYGWIN__)
236 std::ifstream file(fileName.c_str(), std::ios::in |
237 (hexOutputArg.IsEnabled() ? std::ios::binary : std::ios::in));
238 #else
239 std::ifstream file(fileName.c_str(), std::ios::in);
240 #endif
242 if ( !file )
244 std::string error = "Internal CMake error when trying to open file: ";
245 error += fileName.c_str();
246 error += " for reading.";
247 this->SetError(error.c_str());
248 return false;
251 // is there a limit?
252 long sizeLimit = -1;
253 if (limitArg.GetString().size() > 0)
255 sizeLimit = atoi(limitArg.GetCString());
258 // is there an offset?
259 long offset = 0;
260 if (offsetArg.GetString().size() > 0)
262 offset = atoi(offsetArg.GetCString());
265 file.seekg(offset);
267 std::string output;
269 if (hexOutputArg.IsEnabled())
271 // Convert part of the file into hex code
272 int c;
273 while((sizeLimit != 0) && (c = file.get(), file))
275 char hex[4];
276 sprintf(hex, "%x", c&0xff);
277 output += hex;
278 if (sizeLimit > 0)
280 sizeLimit--;
284 else
286 std::string line;
287 bool has_newline = false;
288 while (sizeLimit != 0 &&
289 cmSystemTools::GetLineFromStream(file, line, &has_newline,
290 sizeLimit) )
292 if (sizeLimit > 0)
294 sizeLimit = sizeLimit - static_cast<long>(line.size());
295 if (has_newline)
297 sizeLimit--;
299 if (sizeLimit < 0)
301 sizeLimit = 0;
304 output += line;
305 if ( has_newline )
307 output += "\n";
311 this->Makefile->AddDefinition(variable.c_str(), output.c_str());
312 return true;
315 //----------------------------------------------------------------------------
316 bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
318 if(args.size() < 3)
320 this->SetError("STRINGS requires a file name and output variable");
321 return false;
324 // Get the file to read.
325 std::string fileName = args[1];
326 if(!cmsys::SystemTools::FileIsFullPath(fileName.c_str()))
328 fileName = this->Makefile->GetCurrentDirectory();
329 fileName += "/" + args[1];
332 // Get the variable in which to store the results.
333 std::string outVar = args[2];
335 // Parse the options.
336 enum { arg_none,
337 arg_limit_input,
338 arg_limit_output,
339 arg_limit_count,
340 arg_length_minimum,
341 arg_length_maximum,
342 arg__maximum,
343 arg_regex };
344 unsigned int minlen = 0;
345 unsigned int maxlen = 0;
346 int limit_input = -1;
347 int limit_output = -1;
348 unsigned int limit_count = 0;
349 cmsys::RegularExpression regex;
350 bool have_regex = false;
351 bool newline_consume = false;
352 bool hex_conversion_enabled = true;
353 int arg_mode = arg_none;
354 for(unsigned int i=3; i < args.size(); ++i)
356 if(args[i] == "LIMIT_INPUT")
358 arg_mode = arg_limit_input;
360 else if(args[i] == "LIMIT_OUTPUT")
362 arg_mode = arg_limit_output;
364 else if(args[i] == "LIMIT_COUNT")
366 arg_mode = arg_limit_count;
368 else if(args[i] == "LENGTH_MINIMUM")
370 arg_mode = arg_length_minimum;
372 else if(args[i] == "LENGTH_MAXIMUM")
374 arg_mode = arg_length_maximum;
376 else if(args[i] == "REGEX")
378 arg_mode = arg_regex;
380 else if(args[i] == "NEWLINE_CONSUME")
382 newline_consume = true;
383 arg_mode = arg_none;
385 else if(args[i] == "NO_HEX_CONVERSION")
387 hex_conversion_enabled = false;
388 arg_mode = arg_none;
390 else if(arg_mode == arg_limit_input)
392 if(sscanf(args[i].c_str(), "%d", &limit_input) != 1 ||
393 limit_input < 0)
395 cmOStringStream e;
396 e << "STRINGS option LIMIT_INPUT value \""
397 << args[i] << "\" is not an unsigned integer.";
398 this->SetError(e.str().c_str());
399 return false;
401 arg_mode = arg_none;
403 else if(arg_mode == arg_limit_output)
405 if(sscanf(args[i].c_str(), "%d", &limit_output) != 1 ||
406 limit_output < 0)
408 cmOStringStream e;
409 e << "STRINGS option LIMIT_OUTPUT value \""
410 << args[i] << "\" is not an unsigned integer.";
411 this->SetError(e.str().c_str());
412 return false;
414 arg_mode = arg_none;
416 else if(arg_mode == arg_limit_count)
418 int count;
419 if(sscanf(args[i].c_str(), "%d", &count) != 1 || count < 0)
421 cmOStringStream e;
422 e << "STRINGS option LIMIT_COUNT value \""
423 << args[i] << "\" is not an unsigned integer.";
424 this->SetError(e.str().c_str());
425 return false;
427 limit_count = count;
428 arg_mode = arg_none;
430 else if(arg_mode == arg_length_minimum)
432 int len;
433 if(sscanf(args[i].c_str(), "%d", &len) != 1 || len < 0)
435 cmOStringStream e;
436 e << "STRINGS option LENGTH_MINIMUM value \""
437 << args[i] << "\" is not an unsigned integer.";
438 this->SetError(e.str().c_str());
439 return false;
441 minlen = len;
442 arg_mode = arg_none;
444 else if(arg_mode == arg_length_maximum)
446 int len;
447 if(sscanf(args[i].c_str(), "%d", &len) != 1 || len < 0)
449 cmOStringStream e;
450 e << "STRINGS option LENGTH_MAXIMUM value \""
451 << args[i] << "\" is not an unsigned integer.";
452 this->SetError(e.str().c_str());
453 return false;
455 maxlen = len;
456 arg_mode = arg_none;
458 else if(arg_mode == arg_regex)
460 if(!regex.compile(args[i].c_str()))
462 cmOStringStream e;
463 e << "STRINGS option REGEX value \""
464 << args[i] << "\" could not be compiled.";
465 this->SetError(e.str().c_str());
466 return false;
468 have_regex = true;
469 arg_mode = arg_none;
471 else
473 cmOStringStream e;
474 e << "STRINGS given unknown argument \""
475 << args[i] << "\"";
476 this->SetError(e.str().c_str());
477 return false;
481 if (hex_conversion_enabled)
483 // TODO: should work without temp file, but just on a memory buffer
484 std::string binaryFileName = this->Makefile->GetCurrentOutputDirectory();
485 binaryFileName += cmake::GetCMakeFilesDirectory();
486 binaryFileName += "/FileCommandStringsBinaryFile";
487 if(cmHexFileConverter::TryConvert(fileName.c_str(),binaryFileName.c_str()))
489 fileName = binaryFileName;
493 // Open the specified file.
494 #if defined(_WIN32) || defined(__CYGWIN__)
495 std::ifstream fin(fileName.c_str(), std::ios::in | std::ios::binary);
496 #else
497 std::ifstream fin(fileName.c_str(), std::ios::in);
498 #endif
499 if(!fin)
501 cmOStringStream e;
502 e << "STRINGS file \"" << fileName << "\" cannot be read.";
503 this->SetError(e.str().c_str());
504 return false;
507 // Parse strings out of the file.
508 int output_size = 0;
509 std::vector<std::string> strings;
510 std::string s;
511 int c;
512 while((!limit_count || strings.size() < limit_count) &&
513 (limit_input < 0 || static_cast<int>(fin.tellg()) < limit_input) &&
514 (c = fin.get(), fin))
516 if(c == '\0')
518 // A terminating null character has been found. Check if the
519 // current string matches the requirements. Since it was
520 // terminated by a null character, we require that the length be
521 // at least one no matter what the user specified.
522 if(s.length() >= minlen && s.length() >= 1 &&
523 (!have_regex || regex.find(s.c_str())))
525 output_size += static_cast<int>(s.size()) + 1;
526 if(limit_output >= 0 && output_size >= limit_output)
528 s = "";
529 break;
531 strings.push_back(s);
534 // Reset the string to empty.
535 s = "";
537 else if(c == '\n' && !newline_consume)
539 // The current line has been terminated. Check if the current
540 // string matches the requirements. The length may now be as
541 // low as zero since blank lines are allowed.
542 if(s.length() >= minlen &&
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)
548 s = "";
549 break;
551 strings.push_back(s);
554 // Reset the string to empty.
555 s = "";
557 else if(c == '\r')
559 // Ignore CR character to make output always have UNIX newlines.
561 else if(c >= 0x20 && c < 0x7F || c == '\t' ||
562 (c == '\n' && newline_consume))
564 // This is an ASCII character that may be part of a string.
565 s += c;
567 else
569 // This is a non-string character. Reset the string to emtpy.
570 s = "";
573 // Terminate a string if the maximum length is reached.
574 if(maxlen > 0 && s.size() == maxlen)
576 if(s.length() >= minlen &&
577 (!have_regex || regex.find(s.c_str())))
579 output_size += static_cast<int>(s.size()) + 1;
580 if(limit_output >= 0 && output_size >= limit_output)
582 s = "";
583 break;
585 strings.push_back(s);
587 s = "";
591 // If there is a non-empty current string we have hit the end of the
592 // input file or the input size limit. Check if the current string
593 // matches the requirements.
594 if((!limit_count || strings.size() < limit_count) &&
595 !s.empty() && s.length() >= minlen &&
596 (!have_regex || regex.find(s.c_str())))
598 output_size += static_cast<int>(s.size()) + 1;
599 if(limit_output < 0 || output_size < limit_output)
601 strings.push_back(s);
605 // Encode the result in a CMake list.
606 const char* sep = "";
607 std::string output;
608 for(std::vector<std::string>::const_iterator si = strings.begin();
609 si != strings.end(); ++si)
611 // Separate the strings in the output to make it a list.
612 output += sep;
613 sep = ";";
615 // Store the string in the output, but escape semicolons to
616 // make sure it is a list.
617 std::string const& sr = *si;
618 for(unsigned int i=0; i < sr.size(); ++i)
620 if(sr[i] == ';')
622 output += '\\';
624 output += sr[i];
628 // Save the output in a makefile variable.
629 this->Makefile->AddDefinition(outVar.c_str(), output.c_str());
630 return true;
633 //----------------------------------------------------------------------------
634 bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
635 bool recurse)
637 if ( args.size() < 2 )
639 this->SetError("GLOB requires at least a variable name");
640 return false;
643 std::vector<std::string>::const_iterator i = args.begin();
645 i++; // Get rid of subcommand
647 std::string variable = *i;
648 i++;
649 cmsys::Glob g;
650 g.SetRecurse(recurse);
651 std::string output = "";
652 bool first = true;
653 for ( ; i != args.end(); ++i )
655 if ( *i == "RELATIVE" )
657 ++i; // skip RELATIVE
658 if ( i == args.end() )
660 this->SetError("GLOB requires a directory after the RELATIVE tag");
661 return false;
663 g.SetRelative(i->c_str());
664 ++i;
665 if(i == args.end())
667 this->SetError("GLOB requires a glob expression after the directory");
668 return false;
671 if ( !cmsys::SystemTools::FileIsFullPath(i->c_str()) )
673 std::string expr = this->Makefile->GetCurrentDirectory();
674 // Handle script mode
675 if ( expr.size() > 0 )
677 expr += "/" + *i;
678 g.FindFiles(expr);
680 else
682 g.FindFiles(*i);
685 else
687 g.FindFiles(*i);
689 std::vector<std::string>::size_type cc;
690 std::vector<std::string>& files = g.GetFiles();
691 for ( cc = 0; cc < files.size(); cc ++ )
693 if ( !first )
695 output += ";";
697 output += files[cc];
698 first = false;
701 this->Makefile->AddDefinition(variable.c_str(), output.c_str());
702 return true;
705 //----------------------------------------------------------------------------
706 bool cmFileCommand::HandleMakeDirectoryCommand(
707 std::vector<std::string> const& args)
709 if(args.size() < 2 )
711 this->SetError("called with incorrect number of arguments");
712 return false;
715 std::vector<std::string>::const_iterator i = args.begin();
717 i++; // Get rid of subcommand
719 std::string expr;
720 for ( ; i != args.end(); ++i )
722 const std::string* cdir = &(*i);
723 if ( !cmsys::SystemTools::FileIsFullPath(i->c_str()) )
725 expr = this->Makefile->GetCurrentDirectory();
726 expr += "/" + *i;
727 cdir = &expr;
729 if ( !this->Makefile->CanIWriteThisFile(cdir->c_str()) )
731 std::string e = "attempted to create a directory: " + *cdir
732 + " into a source directory.";
733 this->SetError(e.c_str());
734 cmSystemTools::SetFatalErrorOccured();
735 return false;
737 if ( !cmSystemTools::MakeDirectory(cdir->c_str()) )
739 std::string error = "problem creating directory: " + *cdir;
740 this->SetError(error.c_str());
741 return false;
744 return true;
747 //----------------------------------------------------------------------------
748 // File installation helper class.
749 struct cmFileInstaller
751 // Methods to actually install files.
752 bool InstallFile(const char* fromFile, const char* toFile, bool always);
753 bool InstallDirectory(const char* source, const char* destination,
754 bool always);
756 // All instances need the file command and makefile using them.
757 cmFileInstaller(cmFileCommand* fc, cmMakefile* mf):
758 FileCommand(fc), Makefile(mf), DestDirLength(0), MatchlessFiles(true)
760 // Get the current manifest.
761 this->Manifest =
762 this->Makefile->GetSafeDefinition("CMAKE_INSTALL_MANIFEST_FILES");
764 ~cmFileInstaller()
766 // Save the updated install manifest.
767 this->Makefile->AddDefinition("CMAKE_INSTALL_MANIFEST_FILES",
768 this->Manifest.c_str());
771 private:
772 cmFileCommand* FileCommand;
773 cmMakefile* Makefile;
774 cmFileTimeComparison FileTimes;
775 public:
777 // The length of the destdir setting.
778 int DestDirLength;
780 // Whether to install a file not matching any expression.
781 bool MatchlessFiles;
783 // The current file manifest (semicolon separated list).
784 std::string Manifest;
786 // Permissions for files and directories installed by this object.
787 mode_t FilePermissions;
788 mode_t DirPermissions;
790 // Properties set by pattern and regex match rules.
791 struct MatchProperties
793 bool Exclude;
794 mode_t Permissions;
795 MatchProperties(): Exclude(false), Permissions(0) {}
797 struct MatchRule
799 cmsys::RegularExpression Regex;
800 MatchProperties Properties;
801 std::string RegexString;
802 MatchRule(std::string const& regex):
803 Regex(regex.c_str()), RegexString(regex) {}
805 std::vector<MatchRule> MatchRules;
807 // Get the properties from rules matching this input file.
808 MatchProperties CollectMatchProperties(const char* file,
809 bool isDirectory)
811 // Match rules are case-insensitive on some platforms.
812 #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
813 std::string lower = cmSystemTools::LowerCase(file);
814 file = lower.c_str();
815 #endif
817 // Collect properties from all matching rules.
818 bool matched = false;
819 MatchProperties result;
820 for(std::vector<MatchRule>::iterator mr = this->MatchRules.begin();
821 mr != this->MatchRules.end(); ++mr)
823 if(mr->Regex.find(file))
825 matched = true;
826 result.Exclude |= mr->Properties.Exclude;
827 result.Permissions |= mr->Properties.Permissions;
830 if(!matched && !this->MatchlessFiles && !isDirectory)
832 result.Exclude = true;
834 return result;
837 // Append a file to the installation manifest.
838 void ManifestAppend(std::string const& file)
840 this->Manifest += ";";
841 this->Manifest += file.substr(this->DestDirLength);
844 // Translate an argument to a permissions bit.
845 bool CheckPermissions(std::string const& arg, mode_t& permissions)
847 if(arg == "OWNER_READ") { permissions |= mode_owner_read; }
848 else if(arg == "OWNER_WRITE") { permissions |= mode_owner_write; }
849 else if(arg == "OWNER_EXECUTE") { permissions |= mode_owner_execute; }
850 else if(arg == "GROUP_READ") { permissions |= mode_group_read; }
851 else if(arg == "GROUP_WRITE") { permissions |= mode_group_write; }
852 else if(arg == "GROUP_EXECUTE") { permissions |= mode_group_execute; }
853 else if(arg == "WORLD_READ") { permissions |= mode_world_read; }
854 else if(arg == "WORLD_WRITE") { permissions |= mode_world_write; }
855 else if(arg == "WORLD_EXECUTE") { permissions |= mode_world_execute; }
856 else if(arg == "SETUID") { permissions |= mode_setuid; }
857 else if(arg == "SETGID") { permissions |= mode_setgid; }
858 else
860 cmOStringStream e;
861 e << "INSTALL given invalid permission \"" << arg << "\".";
862 this->FileCommand->SetError(e.str().c_str());
863 return false;
865 return true;
868 private:
869 bool InstallSymlink(const char* fromFile, const char* toFile, bool always);
872 //----------------------------------------------------------------------------
873 bool cmFileInstaller::InstallSymlink(const char* fromFile, const char* toFile,
874 bool always)
876 // Read the original symlink.
877 std::string symlinkTarget;
878 if(!cmSystemTools::ReadSymlink(fromFile, symlinkTarget))
880 cmOStringStream e;
881 e << "INSTALL cannot read symlink \"" << fromFile
882 << "\" to duplicate at \"" << toFile << "\".";
883 this->FileCommand->SetError(e.str().c_str());
884 return false;
887 // Compare the symlink value to that at the destination if not
888 // always installing.
889 bool copy = true;
890 if(!always)
892 std::string oldSymlinkTarget;
893 if(cmSystemTools::ReadSymlink(toFile, oldSymlinkTarget))
895 if(symlinkTarget == oldSymlinkTarget)
897 copy = false;
902 // Inform the user about this file installation.
903 std::string message = (copy? "Installing: " : "Up-to-date: ");
904 message += toFile;
905 this->Makefile->DisplayStatus(message.c_str(), -1);
907 if(copy)
909 // Remove the destination file so we can always create the symlink.
910 cmSystemTools::RemoveFile(toFile);
912 // Create the symlink.
913 if(!cmSystemTools::CreateSymlink(symlinkTarget.c_str(), toFile))
915 cmOStringStream e;
916 e << "INSTALL cannot duplicate symlink \"" << fromFile
917 << "\" at \"" << toFile << "\".";
918 this->FileCommand->SetError(e.str().c_str());
919 return false;
923 // Add the file to the manifest.
924 this->ManifestAppend(toFile);
926 return true;
929 //----------------------------------------------------------------------------
930 bool cmFileInstaller::InstallFile(const char* fromFile, const char* toFile,
931 bool always)
933 // Collect any properties matching this file name.
934 MatchProperties match_properties =
935 this->CollectMatchProperties(fromFile, false);
937 // Skip the file if it is excluded.
938 if(match_properties.Exclude)
940 return true;
943 // Short-circuit for symbolic links.
944 if(cmSystemTools::FileIsSymlink(fromFile))
946 return this->InstallSymlink(fromFile, toFile, always);
949 // Determine whether we will copy the file.
950 bool copy = true;
951 if(!always)
953 // If both files exist with the same time do not copy.
954 if(!this->FileTimes.FileTimesDiffer(fromFile, toFile))
956 copy = false;
960 // Inform the user about this file installation.
961 std::string message = (copy? "Installing: " : "Up-to-date: ");
962 message += toFile;
963 this->Makefile->DisplayStatus(message.c_str(), -1);
965 // Copy the file.
966 if(copy && !cmSystemTools::CopyAFile(fromFile, toFile, true))
968 cmOStringStream e;
969 e << "INSTALL cannot copy file \"" << fromFile
970 << "\" to \"" << toFile << "\".";
971 this->FileCommand->SetError(e.str().c_str());
972 return false;
975 // Add the file to the manifest.
976 this->ManifestAppend(toFile);
978 // Set the file modification time of the destination file.
979 if(copy && !always)
981 cmSystemTools::CopyFileTime(fromFile, toFile);
984 // Set permissions of the destination file.
985 mode_t permissions = (match_properties.Permissions?
986 match_properties.Permissions : this->FilePermissions);
987 if(!permissions)
989 // No permissions were explicitly provided but the user requested
990 // that the source file permissions be used.
991 cmSystemTools::GetPermissions(fromFile, permissions);
993 if(permissions && !cmSystemTools::SetPermissions(toFile, permissions))
995 cmOStringStream e;
996 e << "Problem setting permissions on file \"" << toFile << "\"";
997 this->FileCommand->SetError(e.str().c_str());
998 return false;
1001 return true;
1004 //----------------------------------------------------------------------------
1005 bool cmFileInstaller::InstallDirectory(const char* source,
1006 const char* destination,
1007 bool always)
1009 // Collect any properties matching this directory name.
1010 MatchProperties match_properties =
1011 this->CollectMatchProperties(source, true);
1013 // Skip the directory if it is excluded.
1014 if(match_properties.Exclude)
1016 return true;
1019 // Short-circuit for symbolic links.
1020 if(cmSystemTools::FileIsSymlink(source))
1022 return this->InstallSymlink(source, destination, always);
1025 // Inform the user about this directory installation.
1026 std::string message = "Installing: ";
1027 message += destination;
1028 this->Makefile->DisplayStatus(message.c_str(), -1);
1030 // Make sure the destination directory exists.
1031 if(!cmSystemTools::MakeDirectory(destination))
1033 return false;
1036 // Compute the requested permissions for the destination directory.
1037 mode_t permissions = (match_properties.Permissions?
1038 match_properties.Permissions : this->DirPermissions);
1039 if(!permissions)
1041 // No permissions were explicitly provided but the user requested
1042 // that the source directory permissions be used.
1043 cmSystemTools::GetPermissions(source, permissions);
1046 // Compute the set of permissions required on this directory to
1047 // recursively install files and subdirectories safely.
1048 mode_t required_permissions =
1049 mode_owner_read | mode_owner_write | mode_owner_execute;
1051 // If the required permissions are specified it is safe to set the
1052 // final permissions now. Otherwise we must add the required
1053 // permissions temporarily during file installation.
1054 mode_t permissions_before = 0;
1055 mode_t permissions_after = 0;
1056 if(permissions & required_permissions)
1058 permissions_before = permissions;
1060 else
1062 permissions_before = permissions | required_permissions;
1063 permissions_after = permissions;
1066 // Set the required permissions of the destination directory.
1067 if(permissions_before &&
1068 !cmSystemTools::SetPermissions(destination, permissions_before))
1070 cmOStringStream e;
1071 e << "Problem setting permissions on directory \""
1072 << destination << "\"";
1073 this->FileCommand->SetError(e.str().c_str());
1074 return false;
1077 // Load the directory contents to traverse it recursively.
1078 cmsys::Directory dir;
1079 if(source && *source)
1081 dir.Load(source);
1083 unsigned long numFiles = static_cast<unsigned long>(dir.GetNumberOfFiles());
1084 for(unsigned long fileNum = 0; fileNum < numFiles; ++fileNum)
1086 if(!(strcmp(dir.GetFile(fileNum), ".") == 0 ||
1087 strcmp(dir.GetFile(fileNum), "..") == 0))
1089 cmsys_stl::string fromPath = source;
1090 fromPath += "/";
1091 fromPath += dir.GetFile(fileNum);
1092 if(cmSystemTools::FileIsDirectory(fromPath.c_str()))
1094 cmsys_stl::string toDir = destination;
1095 toDir += "/";
1096 toDir += dir.GetFile(fileNum);
1097 if(!this->InstallDirectory(fromPath.c_str(), toDir.c_str(), always))
1099 return false;
1102 else
1104 // Install this file.
1105 std::string toFile = destination;
1106 toFile += "/";
1107 toFile += dir.GetFile(fileNum);
1108 if(!this->InstallFile(fromPath.c_str(), toFile.c_str(), always))
1110 return false;
1116 // Set the requested permissions of the destination directory.
1117 if(permissions_after &&
1118 !cmSystemTools::SetPermissions(destination, permissions_after))
1120 cmOStringStream e;
1121 e << "Problem setting permissions on directory \"" << destination << "\"";
1122 this->FileCommand->SetError(e.str().c_str());
1123 return false;
1126 return true;
1129 //----------------------------------------------------------------------------
1130 void cmFileCommand::HandleInstallPermissions(cmFileInstaller& installer,
1131 mode_t& permissions_file,
1132 mode_t& permissions_dir,
1133 int itype,
1134 bool use_given_permissions_file,
1135 bool use_given_permissions_dir,
1136 bool use_source_permissions) const
1138 // Choose a default for shared library permissions.
1139 bool install_so_no_exe = this->Makefile->IsOn("CMAKE_INSTALL_SO_NO_EXE");
1140 // If file permissions were not specified set default permissions
1141 // for this target type.
1142 if(!use_given_permissions_file && !use_source_permissions)
1144 switch(itype)
1146 case cmTarget::SHARED_LIBRARY:
1147 case cmTarget::MODULE_LIBRARY:
1148 if(install_so_no_exe)
1150 // Use read/write permissions.
1151 permissions_file = 0;
1152 permissions_file |= mode_owner_read;
1153 permissions_file |= mode_owner_write;
1154 permissions_file |= mode_group_read;
1155 permissions_file |= mode_world_read;
1156 break;
1158 case cmTarget::EXECUTABLE:
1159 case cmTarget::INSTALL_PROGRAMS:
1160 // Use read/write/executable permissions.
1161 permissions_file = 0;
1162 permissions_file |= mode_owner_read;
1163 permissions_file |= mode_owner_write;
1164 permissions_file |= mode_owner_execute;
1165 permissions_file |= mode_group_read;
1166 permissions_file |= mode_group_execute;
1167 permissions_file |= mode_world_read;
1168 permissions_file |= mode_world_execute;
1169 break;
1170 default:
1171 // Use read/write permissions.
1172 permissions_file = 0;
1173 permissions_file |= mode_owner_read;
1174 permissions_file |= mode_owner_write;
1175 permissions_file |= mode_group_read;
1176 permissions_file |= mode_world_read;
1177 break;
1181 // If directory permissions were not specified set default permissions.
1182 if(!use_given_permissions_dir && !use_source_permissions)
1184 // Use read/write/executable permissions.
1185 permissions_dir = 0;
1186 permissions_dir |= mode_owner_read;
1187 permissions_dir |= mode_owner_write;
1188 permissions_dir |= mode_owner_execute;
1189 permissions_dir |= mode_group_read;
1190 permissions_dir |= mode_group_execute;
1191 permissions_dir |= mode_world_read;
1192 permissions_dir |= mode_world_execute;
1194 // Set the installer permissions.
1195 installer.FilePermissions = permissions_file;
1196 installer.DirPermissions = permissions_dir;
1199 //----------------------------------------------------------------------------
1200 void cmFileCommand
1201 ::GetTargetTypeFromString(const std::string& stype, int& itype) const
1203 if ( stype == "EXECUTABLE" )
1205 itype = cmTarget::EXECUTABLE;
1207 else if ( stype == "PROGRAM" )
1209 itype = cmTarget::INSTALL_PROGRAMS;
1211 else if ( stype == "STATIC_LIBRARY" )
1213 itype = cmTarget::STATIC_LIBRARY;
1215 else if ( stype == "SHARED_LIBRARY" )
1217 itype = cmTarget::SHARED_LIBRARY;
1219 else if ( stype == "MODULE" )
1221 itype = cmTarget::MODULE_LIBRARY;
1223 else if ( stype == "DIRECTORY" )
1225 itype = cmTarget::INSTALL_DIRECTORY;
1230 //----------------------------------------------------------------------------
1231 bool cmFileCommand::HandleInstallDestination(cmFileInstaller& installer,
1232 std::string& destination)
1234 if ( destination.size() < 2 )
1236 this->SetError("called with inapropriate arguments. "
1237 "No DESTINATION provided or .");
1238 return false;
1241 const char* destdir = cmSystemTools::GetEnv("DESTDIR");
1242 if ( destdir && *destdir )
1244 std::string sdestdir = destdir;
1245 cmSystemTools::ConvertToUnixSlashes(sdestdir);
1247 char ch1 = destination[0];
1248 char ch2 = destination[1];
1249 char ch3 = 0;
1250 if ( destination.size() > 2 )
1252 ch3 = destination[2];
1254 int skip = 0;
1255 if ( ch1 != '/' )
1257 int relative = 0;
1258 if ( ( ch1 >= 'a' && ch1 <= 'z' || ch1 >= 'A' && ch1 <= 'Z' ) &&
1259 ch2 == ':' )
1261 // Assume windows
1262 // let's do some destdir magic:
1263 skip = 2;
1264 if ( ch3 != '/' )
1266 relative = 1;
1269 else
1271 relative = 1;
1273 if ( relative )
1275 // This is relative path on unix or windows. Since we are doing
1276 // destdir, this case does not make sense.
1277 this->SetError("called with relative DESTINATION. This "
1278 "does not make sense when using DESTDIR. Specify "
1279 "absolute path or remove DESTDIR environment variable.");
1280 return false;
1283 else
1285 if ( ch2 == '/' )
1287 // looks like a network path.
1288 this->SetError("called with network path DESTINATION. This "
1289 "does not make sense when using DESTDIR. Specify local "
1290 "absolute path or remove DESTDIR environment variable.");
1291 return false;
1294 destination = sdestdir + (destination.c_str() + skip);
1295 installer.DestDirLength = int(sdestdir.size());
1298 if ( !cmSystemTools::FileExists(destination.c_str()) )
1300 if ( !cmSystemTools::MakeDirectory(destination.c_str()) )
1302 std::string errstring = "cannot create directory: " + destination +
1303 ". Maybe need administrative privileges.";
1304 this->SetError(errstring.c_str());
1305 return false;
1308 if ( !cmSystemTools::FileIsDirectory(destination.c_str()) )
1310 std::string errstring = "INSTALL destination: " + destination +
1311 " is not a directory.";
1312 this->SetError(errstring.c_str());
1313 return false;
1315 return true;
1318 //----------------------------------------------------------------------------
1319 bool cmFileCommand::HandleInstallCommand(std::vector<std::string> const& args)
1321 if ( args.size() < 6 )
1323 this->SetError("called with incorrect number of arguments");
1324 return false;
1327 // Construct a file installer object.
1328 cmFileInstaller installer(this, this->Makefile);
1330 std::string rename = "";
1331 std::string destination = "";
1333 std::vector<std::string> files;
1334 int itype = cmTarget::INSTALL_FILES;
1336 std::map<cmStdString, const char*> properties;
1337 bool optional = false;
1338 bool result = this->ParseInstallArgs(args, installer, properties,
1339 itype, rename, destination, files,
1340 optional);
1341 if (result == true)
1343 result = this->DoInstall(installer,
1344 itype, rename, destination, files, optional);
1346 return result;
1349 //----------------------------------------------------------------------------
1350 bool cmFileCommand::ParseInstallArgs(std::vector<std::string> const& args,
1351 cmFileInstaller& installer,
1352 std::map<cmStdString, const char*>& properties,
1353 int& itype,
1354 std::string& rename,
1355 std::string& destination,
1356 std::vector<std::string>& files,
1357 bool& optional)
1359 std::string stype = "FILES";
1360 bool doing_files = false;
1361 bool doing_properties = false;
1362 bool doing_permissions_file = false;
1363 bool doing_permissions_dir = false;
1364 bool doing_permissions_match = false;
1365 bool use_given_permissions_file = false;
1366 bool use_given_permissions_dir = false;
1367 bool use_source_permissions = false;
1368 mode_t permissions_file = 0;
1369 mode_t permissions_dir = 0;
1371 cmFileInstaller::MatchRule* current_match_rule = 0;
1372 std::vector<std::string>::size_type i = 0;
1373 i++; // Get rid of subcommand
1374 for ( ; i != args.size(); ++i )
1376 const std::string* cstr = &args[i];
1377 if ( *cstr == "DESTINATION" && i < args.size()-1 )
1379 if(current_match_rule)
1381 cmOStringStream e;
1382 e << "INSTALL does not allow \"" << *cstr << "\" after REGEX.";
1383 this->SetError(e.str().c_str());
1384 return false;
1387 i++;
1388 destination = args[i];
1389 doing_files = false;
1390 doing_properties = false;
1391 doing_permissions_file = false;
1392 doing_permissions_dir = false;
1394 else if ( *cstr == "TYPE" && i < args.size()-1 )
1396 if(current_match_rule)
1398 cmOStringStream e;
1399 e << "INSTALL does not allow \"" << *cstr << "\" after REGEX.";
1400 this->SetError(e.str().c_str());
1401 return false;
1404 i++;
1405 stype = args[i];
1406 if ( args[i+1] == "OPTIONAL" )
1408 i++;
1409 optional = true;
1411 doing_properties = false;
1412 doing_files = false;
1413 doing_permissions_file = false;
1414 doing_permissions_dir = false;
1416 else if ( *cstr == "RENAME" && i < args.size()-1 )
1418 if(current_match_rule)
1420 cmOStringStream e;
1421 e << "INSTALL does not allow \"" << *cstr << "\" after REGEX.";
1422 this->SetError(e.str().c_str());
1423 return false;
1426 i++;
1427 rename = args[i];
1428 doing_properties = false;
1429 doing_files = false;
1430 doing_permissions_file = false;
1431 doing_permissions_dir = false;
1433 else if ( *cstr == "REGEX" && i < args.size()-1 )
1435 i++;
1436 installer.MatchRules.push_back(cmFileInstaller::MatchRule(args[i]));
1437 current_match_rule = &*(installer.MatchRules.end()-1);
1438 if(!current_match_rule->Regex.is_valid())
1440 cmOStringStream e;
1441 e << "INSTALL could not compile REGEX \"" << args[i] << "\".";
1442 this->SetError(e.str().c_str());
1443 return false;
1445 doing_properties = false;
1446 doing_files = false;
1447 doing_permissions_file = false;
1448 doing_permissions_dir = false;
1450 else if ( *cstr == "EXCLUDE" )
1452 // Add this property to the current match rule.
1453 if(!current_match_rule)
1455 cmOStringStream e;
1456 e << "INSTALL does not allow \""
1457 << *cstr << "\" before a REGEX is given.";
1458 this->SetError(e.str().c_str());
1459 return false;
1461 current_match_rule->Properties.Exclude = true;
1462 doing_permissions_match = true;
1464 else if ( *cstr == "PROPERTIES" )
1466 if(current_match_rule)
1468 cmOStringStream e;
1469 e << "INSTALL does not allow \"" << *cstr << "\" after REGEX.";
1470 this->SetError(e.str().c_str());
1471 return false;
1474 doing_properties = true;
1475 doing_files = false;
1476 doing_permissions_file = false;
1477 doing_permissions_dir = false;
1479 else if ( *cstr == "PERMISSIONS" )
1481 if(current_match_rule)
1483 doing_permissions_match = true;
1484 doing_permissions_file = false;
1486 else
1488 doing_permissions_match = false;
1489 doing_permissions_file = true;
1490 use_given_permissions_file = true;
1492 doing_properties = false;
1493 doing_files = false;
1494 doing_permissions_dir = false;
1496 else if ( *cstr == "DIR_PERMISSIONS" )
1498 if(current_match_rule)
1500 cmOStringStream e;
1501 e << "INSTALL does not allow \"" << *cstr << "\" after REGEX.";
1502 this->SetError(e.str().c_str());
1503 return false;
1506 use_given_permissions_dir = true;
1507 doing_properties = false;
1508 doing_files = false;
1509 doing_permissions_file = false;
1510 doing_permissions_dir = true;
1512 else if ( *cstr == "USE_SOURCE_PERMISSIONS" )
1514 if(current_match_rule)
1516 cmOStringStream e;
1517 e << "INSTALL does not allow \"" << *cstr << "\" after REGEX.";
1518 this->SetError(e.str().c_str());
1519 return false;
1522 doing_properties = false;
1523 doing_files = false;
1524 doing_permissions_file = false;
1525 doing_permissions_dir = false;
1526 use_source_permissions = true;
1528 else if ( *cstr == "FILES_MATCHING" )
1530 if(current_match_rule)
1532 cmOStringStream e;
1533 e << "INSTALL does not allow \"" << *cstr << "\" after REGEX.";
1534 this->SetError(e.str().c_str());
1535 return false;
1538 doing_properties = false;
1539 doing_files = false;
1540 doing_permissions_file = false;
1541 doing_permissions_dir = false;
1542 installer.MatchlessFiles = false;
1544 else if ( *cstr == "COMPONENTS" )
1546 cmOStringStream e;
1547 e << "INSTALL called with old-style COMPONENTS argument. "
1548 << "This script was generated with an older version of CMake. "
1549 << "Re-run this cmake version on your build tree.";
1550 this->SetError(e.str().c_str());
1551 return false;
1553 else if ( *cstr == "CONFIGURATIONS" )
1555 cmOStringStream e;
1556 e << "INSTALL called with old-style CONFIGURATIONS argument. "
1557 << "This script was generated with an older version of CMake. "
1558 << "Re-run this cmake version on your build tree.";
1559 this->SetError(e.str().c_str());
1560 return false;
1562 else if ( *cstr == "FILES" && !doing_files)
1564 if(current_match_rule)
1566 cmOStringStream e;
1567 e << "INSTALL does not allow \"" << *cstr << "\" after REGEX.";
1568 this->SetError(e.str().c_str());
1569 return false;
1572 doing_files = true;
1573 doing_properties = false;
1574 doing_permissions_file = false;
1575 doing_permissions_dir = false;
1577 else if ( doing_properties && i < args.size()-1 )
1579 properties[args[i]] = args[i+1].c_str();
1580 i++;
1582 else if ( doing_files )
1584 files.push_back(*cstr);
1586 else if(doing_permissions_file)
1588 if(!installer.CheckPermissions(args[i], permissions_file))
1590 return false;
1593 else if(doing_permissions_dir)
1595 if(!installer.CheckPermissions(args[i], permissions_dir))
1597 return false;
1600 else if(doing_permissions_match)
1602 if(!installer.CheckPermissions(
1603 args[i], current_match_rule->Properties.Permissions))
1605 return false;
1608 else
1610 this->SetError("called with inappropriate arguments");
1611 return false;
1615 // now check and postprocess what has been parsed
1616 if ( files.size() == 0 )
1618 // nothing to do, no files were listed.
1619 // if this is handled as error, INSTALL_FILES() creates an invalid
1620 // cmake_install.cmake script with no FILES() arguments if no files were
1621 // given to INSTALL_FILES(). This was accepted with CMake 2.4.x.
1622 return true;
1625 // Check rename form.
1626 if(!rename.empty())
1628 if(itype != cmTarget::INSTALL_FILES &&
1629 itype != cmTarget::INSTALL_PROGRAMS)
1631 this->SetError("INSTALL option RENAME may be used only with "
1632 "FILES or PROGRAMS.");
1633 return false;
1635 if(files.size() > 1)
1637 this->SetError("INSTALL option RENAME may be used only with "
1638 "one file.");
1639 return false;
1643 if (this->HandleInstallDestination(installer, destination) == false)
1645 return false;
1648 if(properties.find("VERSION") != properties.end())
1650 cmOStringStream e;
1651 e << "INSTALL called with old-style VERSION property. "
1652 << "This script was generated with an older version of CMake. "
1653 << "Re-run this cmake version on your build tree.";
1654 this->SetError(e.str().c_str());
1655 return false;
1657 if(properties.find("SOVERSION") != properties.end())
1659 cmOStringStream e;
1660 e << "INSTALL called with old-style SOVERSION property. "
1661 << "This script was generated with an older version of CMake. "
1662 << "Re-run this cmake version on your build tree.";
1663 this->SetError(e.str().c_str());
1664 return false;
1667 this->GetTargetTypeFromString(stype, itype);
1669 this->HandleInstallPermissions(installer,
1670 permissions_file,
1671 permissions_dir,
1672 itype,
1673 use_given_permissions_file,
1674 use_given_permissions_dir,
1675 use_source_permissions);
1677 return true;
1680 //----------------------------------------------------------------------------
1681 bool cmFileCommand::DoInstall( cmFileInstaller& installer,
1682 const int itype,
1683 const std::string& rename,
1684 const std::string& destination,
1685 const std::vector<std::string>& files,
1686 const bool optional)
1688 typedef std::set<cmStdString>::const_iterator iter_type;
1690 // Check whether files should be copied always or only if they have
1691 // changed.
1692 bool copy_always =
1693 cmSystemTools::IsOn(cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS"));
1695 // Handle each file listed.
1696 for (std::vector<std::string>::size_type i = 0; i < files.size(); i ++ )
1698 // Split the input file into its directory and name components.
1699 std::vector<std::string> fromPathComponents;
1700 cmSystemTools::SplitPath(files[i].c_str(), fromPathComponents);
1701 std::string fromName = *(fromPathComponents.end()-1);
1702 std::string fromDir = cmSystemTools::JoinPath(fromPathComponents.begin(),
1703 fromPathComponents.end()-1);
1705 // Compute the full path to the destination file.
1706 std::string toFile = destination;
1707 std::string const& toName = rename.empty()? fromName : rename;
1708 if(!toName.empty())
1710 toFile += "/";
1711 toFile += toName;
1714 // Construct the full path to the source file. The file name may
1715 // have been changed above.
1716 std::string fromFile = fromDir;
1717 if(!fromName.empty())
1719 fromFile += "/";
1720 fromFile += fromName;
1723 std::string message;
1724 if(!cmSystemTools::SameFile(fromFile.c_str(), toFile.c_str()))
1726 if(itype == cmTarget::INSTALL_DIRECTORY &&
1727 (fromFile.empty() ||
1728 cmSystemTools::FileIsDirectory(fromFile.c_str())))
1730 // Try installing this directory.
1731 if(!installer.InstallDirectory(fromFile.c_str(), toFile.c_str(),
1732 copy_always))
1734 return false;
1737 else if(cmSystemTools::FileExists(fromFile.c_str()))
1739 // Install this file.
1740 if(!installer.InstallFile(fromFile.c_str(), toFile.c_str(),
1741 copy_always))
1743 return false;
1746 else if(!optional)
1748 // The input file does not exist and installation is not optional.
1749 cmOStringStream e;
1750 e << "INSTALL cannot find file \"" << fromFile << "\" to install.";
1751 this->SetError(e.str().c_str());
1752 return false;
1757 return true;
1760 //----------------------------------------------------------------------------
1761 bool cmFileCommand::HandleRelativePathCommand(
1762 std::vector<std::string> const& args)
1764 if(args.size() != 4 )
1766 this->SetError("called with incorrect number of arguments");
1767 return false;
1770 const std::string& outVar = args[1];
1771 const std::string& directoryName = args[2];
1772 const std::string& fileName = args[3];
1774 if(!cmSystemTools::FileIsFullPath(directoryName.c_str()))
1776 std::string errstring =
1777 "RelativePath must be passed a full path to the directory: "
1778 + directoryName;
1779 this->SetError(errstring.c_str());
1780 return false;
1782 if(!cmSystemTools::FileIsFullPath(fileName.c_str()))
1784 std::string errstring =
1785 "RelativePath must be passed a full path to the file: "
1786 + fileName;
1787 this->SetError(errstring.c_str());
1788 return false;
1791 std::string res = cmSystemTools::RelativePath(directoryName.c_str(),
1792 fileName.c_str());
1793 this->Makefile->AddDefinition(outVar.c_str(),
1794 res.c_str());
1795 return true;
1799 //----------------------------------------------------------------------------
1800 bool cmFileCommand::HandleRemove(std::vector<std::string> const& args,
1801 bool recurse)
1804 std::string message;
1805 std::vector<std::string>::const_iterator i = args.begin();
1807 i++; // Get rid of subcommand
1808 for(;i != args.end(); ++i)
1810 if(cmSystemTools::FileIsDirectory(i->c_str()) && recurse)
1812 cmSystemTools::RemoveADirectory(i->c_str());
1814 else
1816 cmSystemTools::RemoveFile(i->c_str());
1819 return true;
1822 //----------------------------------------------------------------------------
1823 bool cmFileCommand::HandleCMakePathCommand(std::vector<std::string>
1824 const& args,
1825 bool nativePath)
1827 std::vector<std::string>::const_iterator i = args.begin();
1828 if(args.size() != 3)
1830 this->SetError("FILE(SYSTEM_PATH ENV result) must be called with "
1831 "only three arguments.");
1832 return false;
1834 i++; // Get rid of subcommand
1835 #if defined(_WIN32) && !defined(__CYGWIN__)
1836 char pathSep = ';';
1837 #else
1838 char pathSep = ':';
1839 #endif
1840 std::vector<cmsys::String> path = cmSystemTools::SplitString(i->c_str(),
1841 pathSep);
1842 i++;
1843 const char* var = i->c_str();
1844 std::string value;
1845 for(std::vector<cmsys::String>::iterator j = path.begin();
1846 j != path.end(); ++j)
1848 if(j != path.begin())
1850 value += ";";
1852 if(!nativePath)
1854 cmSystemTools::ConvertToUnixSlashes(*j);
1856 else
1858 *j = cmSystemTools::ConvertToOutputPath(j->c_str());
1859 // remove double quotes in the path
1860 cmsys::String& s = *j;
1862 if(s.size() > 1 && s[0] == '\"' && s[s.size()-1] == '\"')
1864 s = s.substr(1,s.size()-2);
1867 value += *j;
1869 this->Makefile->AddDefinition(var, value.c_str());
1870 return true;