ENH: keep cleaning up Tcl/Tk modules
[cmake.git] / Source / cmInstallCommand.cxx
blob613f066391438dba137b86e840d1a4f7f93341ba
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmInstallCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2008-01-23 15:27:59 $
7 Version: $Revision: 1.39 $
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 "cmInstallCommand.h"
19 #include "cmInstallDirectoryGenerator.h"
20 #include "cmInstallFilesGenerator.h"
21 #include "cmInstallScriptGenerator.h"
22 #include "cmInstallTargetGenerator.h"
23 #include "cmInstallExportGenerator.h"
24 #include "cmInstallCommandArguments.h"
26 #include <cmsys/Glob.hxx>
28 static cmInstallTargetGenerator* CreateInstallTargetGenerator(cmTarget& target,
29 const cmInstallCommandArguments& args, bool impLib, bool forceOpt = false)
31 return new cmInstallTargetGenerator(target, args.GetDestination().c_str(),
32 impLib, args.GetPermissions().c_str(),
33 args.GetConfigurations(), args.GetComponent().c_str(),
34 args.GetOptional() || forceOpt);
37 static cmInstallFilesGenerator* CreateInstallFilesGenerator(
38 const std::vector<std::string>& absFiles,
39 const cmInstallCommandArguments& args, bool programs)
41 return new cmInstallFilesGenerator(absFiles, args.GetDestination().c_str(),
42 programs, args.GetPermissions().c_str(),
43 args.GetConfigurations(), args.GetComponent().c_str(),
44 args.GetRename().c_str(), args.GetOptional());
48 // cmInstallCommand
49 bool cmInstallCommand::InitialPass(std::vector<std::string> const& args,
50 cmExecutionStatus &)
52 // Allow calling with no arguments so that arguments may be built up
53 // using a variable that may be left empty.
54 if(args.empty())
56 return true;
59 // Enable the install target.
60 this->Makefile->GetLocalGenerator()
61 ->GetGlobalGenerator()->EnableInstallTarget();
63 // Switch among the command modes.
64 if(args[0] == "SCRIPT")
66 return this->HandleScriptMode(args);
68 else if(args[0] == "CODE")
70 return this->HandleScriptMode(args);
72 else if(args[0] == "TARGETS")
74 return this->HandleTargetsMode(args);
76 else if(args[0] == "FILES")
78 return this->HandleFilesMode(args);
80 else if(args[0] == "PROGRAMS")
82 return this->HandleFilesMode(args);
84 else if(args[0] == "DIRECTORY")
86 return this->HandleDirectoryMode(args);
88 else if(args[0] == "EXPORT")
90 return this->HandleExportMode(args);
93 // Unknown mode.
94 cmStdString e = "called with unknown mode ";
95 e += args[0];
96 this->SetError(e.c_str());
97 return false;
100 //----------------------------------------------------------------------------
101 bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
103 std::string component("Unspecified");
104 int componentCount = 0;
105 bool doing_script = false;
106 bool doing_code = false;
108 // Scan the args once for COMPONENT. Only allow one.
110 for(size_t i=0; i < args.size(); ++i)
112 if(args[i] == "COMPONENT" && i+1 < args.size())
114 ++componentCount;
115 ++i;
116 component = args[i];
120 if(componentCount>1)
122 this->SetError("given more than one COMPONENT for the SCRIPT or CODE "
123 "signature of the INSTALL command. "
124 "Use multiple INSTALL commands with one COMPONENT each.");
125 return false;
128 // Scan the args again, this time adding install generators each time we
129 // encounter a SCRIPT or CODE arg:
131 for(size_t i=0; i < args.size(); ++i)
133 if(args[i] == "SCRIPT")
135 doing_script = true;
136 doing_code = false;
138 else if(args[i] == "CODE")
140 doing_script = false;
141 doing_code = true;
143 else if(args[i] == "COMPONENT")
145 doing_script = false;
146 doing_code = false;
148 else if(doing_script)
150 doing_script = false;
151 std::string script = args[i];
152 if(!cmSystemTools::FileIsFullPath(script.c_str()))
154 script = this->Makefile->GetCurrentDirectory();
155 script += "/";
156 script += args[i];
158 if(cmSystemTools::FileIsDirectory(script.c_str()))
160 this->SetError("given a directory as value of SCRIPT argument.");
161 return false;
163 this->Makefile->AddInstallGenerator(
164 new cmInstallScriptGenerator(script.c_str(), false,
165 component.c_str()));
167 else if(doing_code)
169 doing_code = false;
170 std::string code = args[i];
171 this->Makefile->AddInstallGenerator(
172 new cmInstallScriptGenerator(code.c_str(), true,
173 component.c_str()));
177 if(doing_script)
179 this->SetError("given no value for SCRIPT argument.");
180 return false;
182 if(doing_code)
184 this->SetError("given no value for CODE argument.");
185 return false;
188 //Tell the global generator about any installation component names specified.
189 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
190 ->AddInstallComponent(component.c_str());
192 return true;
196 /*struct InstallPart
198 InstallPart(cmCommandArgumentsHelper* helper, const char* key,
199 cmCommandArgumentGroup* group);
200 cmCAStringVector argVector;
201 cmInstallCommandArguments args;
202 };*/
204 //----------------------------------------------------------------------------
205 bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
207 // This is the TARGETS mode.
208 std::vector<cmTarget*> targets;
210 cmCommandArgumentsHelper argHelper;
211 cmCommandArgumentGroup group;
212 cmCAStringVector genericArgVector (&argHelper,0);
213 cmCAStringVector archiveArgVector (&argHelper,"ARCHIVE",&group);
214 cmCAStringVector libraryArgVector (&argHelper,"LIBRARY",&group);
215 cmCAStringVector runtimeArgVector (&argHelper,"RUNTIME",&group);
216 cmCAStringVector frameworkArgVector (&argHelper,"FRAMEWORK",&group);
217 cmCAStringVector bundleArgVector (&argHelper,"BUNDLE",&group);
218 cmCAStringVector privateHeaderArgVector(&argHelper,"PRIVATE_HEADER",&group);
219 cmCAStringVector publicHeaderArgVector (&argHelper,"PUBLIC_HEADER",&group);
220 cmCAStringVector resourceArgVector (&argHelper,"RESOURCE",&group);
221 genericArgVector.Follows(0);
222 group.Follows(&genericArgVector);
224 argHelper.Parse(&args, 0);
226 std::vector<std::string> unknownArgs;
227 cmInstallCommandArguments genericArgs;
228 cmCAStringVector targetList(&genericArgs.Parser, "TARGETS");
229 cmCAString exports(&genericArgs.Parser,"EXPORT", &genericArgs.ArgumentGroup);
230 targetList.Follows(0);
231 genericArgs.ArgumentGroup.Follows(&targetList);
232 genericArgs.Parse(&genericArgVector.GetVector(), &unknownArgs);
233 bool success = genericArgs.Finalize();
235 cmInstallCommandArguments archiveArgs;
236 cmInstallCommandArguments libraryArgs;
237 cmInstallCommandArguments runtimeArgs;
238 cmInstallCommandArguments frameworkArgs;
239 cmInstallCommandArguments bundleArgs;
240 cmInstallCommandArguments privateHeaderArgs;
241 cmInstallCommandArguments publicHeaderArgs;
242 cmInstallCommandArguments resourceArgs;
244 archiveArgs.Parse (&archiveArgVector.GetVector(), &unknownArgs);
245 libraryArgs.Parse (&libraryArgVector.GetVector(), &unknownArgs);
246 runtimeArgs.Parse (&runtimeArgVector.GetVector(), &unknownArgs);
247 frameworkArgs.Parse (&frameworkArgVector.GetVector(), &unknownArgs);
248 bundleArgs.Parse (&bundleArgVector.GetVector(), &unknownArgs);
249 privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
250 publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(), &unknownArgs);
251 resourceArgs.Parse (&resourceArgVector.GetVector(), &unknownArgs);
253 if(!unknownArgs.empty())
255 // Unknown argument.
256 cmOStringStream e;
257 e << "TARGETS given unknown argument \"" << unknownArgs[0] << "\".";
258 this->SetError(e.str().c_str());
259 return false;
262 // apply generic args
263 archiveArgs.SetGenericArguments(&genericArgs);
264 libraryArgs.SetGenericArguments(&genericArgs);
265 runtimeArgs.SetGenericArguments(&genericArgs);
266 frameworkArgs.SetGenericArguments(&genericArgs);
267 bundleArgs.SetGenericArguments(&genericArgs);
268 privateHeaderArgs.SetGenericArguments(&genericArgs);
269 publicHeaderArgs.SetGenericArguments(&genericArgs);
270 resourceArgs.SetGenericArguments(&genericArgs);
272 success = success && archiveArgs.Finalize();
273 success = success && libraryArgs.Finalize();
274 success = success && runtimeArgs.Finalize();
275 success = success && frameworkArgs.Finalize();
276 success = success && bundleArgs.Finalize();
277 success = success && privateHeaderArgs.Finalize();
278 success = success && publicHeaderArgs.Finalize();
279 success = success && resourceArgs.Finalize();
281 if(!success)
283 return false;
286 // Check if there is something to do.
287 if(targetList.GetVector().empty())
289 return true;
292 // Check whether this is a DLL platform.
293 bool dll_platform = (this->Makefile->IsOn("WIN32") ||
294 this->Makefile->IsOn("CYGWIN") ||
295 this->Makefile->IsOn("MINGW"));
297 for(std::vector<std::string>::const_iterator
298 targetIt=targetList.GetVector().begin();
299 targetIt!=targetList.GetVector().end();
300 ++targetIt)
302 // Lookup this target in the current directory.
303 if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str(), false))
305 // Found the target. Check its type.
306 if(target->GetType() != cmTarget::EXECUTABLE &&
307 target->GetType() != cmTarget::STATIC_LIBRARY &&
308 target->GetType() != cmTarget::SHARED_LIBRARY &&
309 target->GetType() != cmTarget::MODULE_LIBRARY)
311 cmOStringStream e;
312 e << "TARGETS given target \"" << (*targetIt)
313 << "\" which is not an executable, library, or module.";
314 this->SetError(e.str().c_str());
315 return false;
317 // Store the target in the list to be installed.
318 targets.push_back(target);
320 else
322 // Did not find the target.
323 cmOStringStream e;
324 e << "TARGETS given target \"" << (*targetIt)
325 << "\" which does not exist in this directory.";
326 this->SetError(e.str().c_str());
327 return false;
331 // Generate install script code to install the given targets.
332 for(std::vector<cmTarget*>::iterator ti = targets.begin();
333 ti != targets.end(); ++ti)
335 // Handle each target type.
336 cmTarget& target = *(*ti);
337 cmInstallTargetGenerator* archiveGenerator = 0;
338 cmInstallTargetGenerator* libraryGenerator = 0;
339 cmInstallTargetGenerator* runtimeGenerator = 0;
340 cmInstallTargetGenerator* frameworkGenerator = 0;
341 cmInstallTargetGenerator* bundleGenerator = 0;
342 cmInstallFilesGenerator* privateHeaderGenerator = 0;
343 cmInstallFilesGenerator* publicHeaderGenerator = 0;
344 cmInstallFilesGenerator* resourceGenerator = 0;
346 switch(target.GetType())
348 case cmTarget::SHARED_LIBRARY:
350 // Shared libraries are handled differently on DLL and non-DLL
351 // platforms. All windows platforms are DLL platforms including
352 // cygwin. Currently no other platform is a DLL platform.
353 if(dll_platform)
355 // This is a DLL platform.
356 if(!archiveArgs.GetDestination().empty())
358 // The import library uses the ARCHIVE properties.
359 archiveGenerator = CreateInstallTargetGenerator(target,
360 archiveArgs, true);
362 if(!runtimeArgs.GetDestination().empty())
364 // The DLL uses the RUNTIME properties.
365 runtimeGenerator = CreateInstallTargetGenerator(target,
366 runtimeArgs, false);
368 if ((archiveGenerator==0) && (runtimeGenerator==0))
370 this->SetError("Library TARGETS given no DESTINATION!");
371 return false;
374 else
376 // This is a non-DLL platform.
377 // If it is marked with FRAMEWORK property use the FRAMEWORK set of
378 // INSTALL properties. Otherwise, use the LIBRARY properties.
379 if(target.GetPropertyAsBool("FRAMEWORK"))
381 // Use the FRAMEWORK properties.
382 if (!frameworkArgs.GetDestination().empty())
384 frameworkGenerator = CreateInstallTargetGenerator(target,
385 frameworkArgs, false);
387 else
389 cmOStringStream e;
390 e << "TARGETS given no FRAMEWORK DESTINATION for shared library "
391 "FRAMEWORK target \"" << target.GetName() << "\".";
392 this->SetError(e.str().c_str());
393 return false;
396 else
398 // The shared library uses the LIBRARY properties.
399 if (!libraryArgs.GetDestination().empty())
401 libraryGenerator = CreateInstallTargetGenerator(target,
402 libraryArgs, false);
404 else
406 cmOStringStream e;
407 e << "TARGETS given no LIBRARY DESTINATION for shared library "
408 "target \"" << target.GetName() << "\".";
409 this->SetError(e.str().c_str());
410 return false;
415 break;
416 case cmTarget::STATIC_LIBRARY:
418 // Static libraries use ARCHIVE properties.
419 if (!archiveArgs.GetDestination().empty())
421 archiveGenerator = CreateInstallTargetGenerator(target, archiveArgs,
422 false);
424 else
426 cmOStringStream e;
427 e << "TARGETS given no ARCHIVE DESTINATION for static library "
428 "target \"" << target.GetName() << "\".";
429 this->SetError(e.str().c_str());
430 return false;
433 break;
434 case cmTarget::MODULE_LIBRARY:
436 // Modules use LIBRARY properties.
437 if (!libraryArgs.GetDestination().empty())
439 libraryGenerator = CreateInstallTargetGenerator(target, libraryArgs,
440 false);
442 else
444 cmOStringStream e;
445 e << "TARGETS given no LIBRARY DESTINATION for module target \""
446 << target.GetName() << "\".";
447 this->SetError(e.str().c_str());
448 return false;
451 break;
452 case cmTarget::EXECUTABLE:
454 // Executables use the RUNTIME properties.
455 if(target.GetPropertyAsBool("MACOSX_BUNDLE"))
457 if (!bundleArgs.GetDestination().empty())
459 bundleGenerator = CreateInstallTargetGenerator(target, bundleArgs,
460 false);
462 else
464 cmOStringStream e;
465 e << "TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE "
466 "executable target \"" << target.GetName() << "\".";
467 this->SetError(e.str().c_str());
468 return false;
471 else
473 if (!runtimeArgs.GetDestination().empty())
475 runtimeGenerator = CreateInstallTargetGenerator(target,
476 runtimeArgs, false);
478 else
480 cmOStringStream e;
481 e << "TARGETS given no RUNTIME DESTINATION for executable "
482 "target \"" << target.GetName() << "\".";
483 this->SetError(e.str().c_str());
484 return false;
488 // On DLL platforms an executable may also have an import
489 // library. Install it to the archive destination if it
490 // exists.
491 if(dll_platform && !archiveArgs.GetDestination().empty() &&
492 target.GetPropertyAsBool("ENABLE_EXPORTS"))
494 // The import library uses the ARCHIVE properties.
495 archiveGenerator = CreateInstallTargetGenerator(target,
496 archiveArgs, true, true);
499 break;
500 default:
501 // This should never happen due to the above type check.
502 // Ignore the case.
503 break;
506 // if(target.GetProperty("ASSOCIATED_FILES");
508 // These well-known sets of files are installed *automatically* for FRAMEWORK
509 // SHARED library targets on the Mac as part of installing the FRAMEWORK.
510 // For other target types or on other platforms, they are not installed
511 // automatically and so we need to create install files generators for them.
513 bool createInstallGeneratorsForTargetFileSets = true;
515 if(cmTarget::SHARED_LIBRARY == target.GetType() &&
516 target.GetPropertyAsBool("FRAMEWORK") &&
517 this->Makefile->IsOn("APPLE"))
519 createInstallGeneratorsForTargetFileSets = false;
522 if(createInstallGeneratorsForTargetFileSets)
524 const char* files = target.GetProperty("PRIVATE_HEADER");
525 if ((files) && (*files))
527 std::vector<std::string> relFiles;
528 cmSystemTools::ExpandListArgument(files, relFiles);
529 std::vector<std::string> absFiles;
530 if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles))
532 return false;
535 // Create the files install generator.
536 if (!privateHeaderArgs.GetDestination().empty())
538 privateHeaderGenerator = CreateInstallFilesGenerator(absFiles,
539 privateHeaderArgs, false);
541 else
543 cmOStringStream e;
544 e << "INSTALL TARGETS - target " << target.GetName() << " has "
545 << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
546 cmSystemTools::Message(e.str().c_str(), "Warning");
550 files = target.GetProperty("PUBLIC_HEADER");
551 if ((files) && (*files))
553 std::vector<std::string> relFiles;
554 cmSystemTools::ExpandListArgument(files, relFiles);
555 std::vector<std::string> absFiles;
556 if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles))
558 return false;
561 // Create the files install generator.
562 if (!publicHeaderArgs.GetDestination().empty())
564 publicHeaderGenerator = CreateInstallFilesGenerator(absFiles,
565 publicHeaderArgs, false);
567 else
569 cmOStringStream e;
570 e << "INSTALL TARGETS - target " << target.GetName() << " has "
571 << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
572 cmSystemTools::Message(e.str().c_str(), "Warning");
576 files = target.GetProperty("RESOURCE");
577 if ((files) && (*files))
579 std::vector<std::string> relFiles;
580 cmSystemTools::ExpandListArgument(files, relFiles);
581 std::vector<std::string> absFiles;
582 if (!this->MakeFilesFullPath("RESOURCE", relFiles, absFiles))
584 return false;
587 // Create the files install generator.
588 if (!resourceArgs.GetDestination().empty())
590 resourceGenerator = CreateInstallFilesGenerator(absFiles,
591 resourceArgs, false);
593 else
595 cmOStringStream e;
596 e << "INSTALL TARGETS - target " << target.GetName() << " has "
597 << "RESOURCE files but no RESOURCE DESTINATION.";
598 cmSystemTools::Message(e.str().c_str(), "Warning");
603 this->Makefile->AddInstallGenerator(archiveGenerator);
604 this->Makefile->AddInstallGenerator(libraryGenerator);
605 this->Makefile->AddInstallGenerator(runtimeGenerator);
606 this->Makefile->AddInstallGenerator(frameworkGenerator);
607 this->Makefile->AddInstallGenerator(bundleGenerator);
608 this->Makefile->AddInstallGenerator(privateHeaderGenerator);
609 this->Makefile->AddInstallGenerator(publicHeaderGenerator);
610 this->Makefile->AddInstallGenerator(resourceGenerator);
612 if (!exports.GetString().empty())
614 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
615 ->AddTargetToExports(exports.GetCString(), &target,
616 archiveGenerator, runtimeGenerator,
617 libraryGenerator, frameworkGenerator,
618 bundleGenerator, publicHeaderGenerator);
622 // Tell the global generator about any installation component names specified
623 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
624 ->AddInstallComponent(archiveArgs.GetComponent().c_str());
625 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
626 ->AddInstallComponent(libraryArgs.GetComponent().c_str());
627 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
628 ->AddInstallComponent(runtimeArgs.GetComponent().c_str());
629 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
630 ->AddInstallComponent(frameworkArgs.GetComponent().c_str());
631 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
632 ->AddInstallComponent(bundleArgs.GetComponent().c_str());
633 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
634 ->AddInstallComponent(privateHeaderArgs.GetComponent().c_str());
635 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
636 ->AddInstallComponent(publicHeaderArgs.GetComponent().c_str());
637 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
638 ->AddInstallComponent(resourceArgs.GetComponent().c_str());
640 return true;
643 //----------------------------------------------------------------------------
644 bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
646 // This is the FILES mode.
647 bool programs = (args[0] == "PROGRAMS");
648 cmInstallCommandArguments ica;
649 cmCAStringVector files(&ica.Parser, programs ? "PROGRAMS" : "FILES");
650 files.Follows(0);
651 ica.ArgumentGroup.Follows(&files);
652 std::vector<std::string> unknownArgs;
653 ica.Parse(&args, &unknownArgs);
655 if(!unknownArgs.empty())
657 // Unknown argument.
658 cmOStringStream e;
659 e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
660 this->SetError(e.str().c_str());
661 return false;
664 // Check if there is something to do.
665 if(files.GetVector().empty())
667 return true;
670 if(!ica.GetRename().empty() && files.GetVector().size() > 1)
672 // The rename option works only with one file.
673 cmOStringStream e;
674 e << args[0] << " given RENAME option with more than one file.";
675 this->SetError(e.str().c_str());
676 return false;
679 std::vector<std::string> absFiles;
680 if (!this->MakeFilesFullPath(args[0].c_str(), files.GetVector(), absFiles))
682 return false;
685 if (!ica.Finalize())
687 return false;
690 if(ica.GetDestination().empty())
692 // A destination is required.
693 cmOStringStream e;
694 e << args[0] << " given no DESTINATION!";
695 this->SetError(e.str().c_str());
696 return false;
699 // Create the files install generator.
700 this->Makefile->AddInstallGenerator(
701 CreateInstallFilesGenerator(absFiles, ica, programs));
703 //Tell the global generator about any installation component names specified.
704 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
705 ->AddInstallComponent(ica.GetComponent().c_str());
707 return true;
710 //----------------------------------------------------------------------------
711 bool
712 cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
714 bool doing_dirs = true;
715 bool doing_destination = false;
716 bool doing_pattern = false;
717 bool doing_regex = false;
718 bool doing_permissions_file = false;
719 bool doing_permissions_dir = false;
720 bool doing_permissions_match = false;
721 bool doing_configurations = false;
722 bool doing_component = false;
723 bool in_match_mode = false;
724 std::vector<std::string> dirs;
725 const char* destination = 0;
726 std::string permissions_file;
727 std::string permissions_dir;
728 std::vector<std::string> configurations;
729 std::string component = "Unspecified";
730 std::string literal_args;
731 for(unsigned int i=1; i < args.size(); ++i)
733 if(args[i] == "DESTINATION")
735 if(in_match_mode)
737 cmOStringStream e;
738 e << args[0] << " does not allow \""
739 << args[i] << "\" after PATTERN or REGEX.";
740 this->SetError(e.str().c_str());
741 return false;
744 // Switch to setting the destination property.
745 doing_dirs = false;
746 doing_destination = true;
747 doing_pattern = false;
748 doing_regex = false;
749 doing_permissions_file = false;
750 doing_permissions_dir = false;
751 doing_configurations = false;
752 doing_component = false;
754 else if(args[i] == "PATTERN")
756 // Switch to a new pattern match rule.
757 doing_dirs = false;
758 doing_destination = false;
759 doing_pattern = true;
760 doing_regex = false;
761 doing_permissions_file = false;
762 doing_permissions_dir = false;
763 doing_permissions_match = false;
764 doing_configurations = false;
765 doing_component = false;
766 in_match_mode = true;
768 else if(args[i] == "REGEX")
770 // Switch to a new regex match rule.
771 doing_dirs = false;
772 doing_destination = false;
773 doing_pattern = false;
774 doing_regex = true;
775 doing_permissions_file = false;
776 doing_permissions_dir = false;
777 doing_permissions_match = false;
778 doing_configurations = false;
779 doing_component = false;
780 in_match_mode = true;
782 else if(args[i] == "EXCLUDE")
784 // Add this property to the current match rule.
785 if(!in_match_mode || doing_pattern || doing_regex)
787 cmOStringStream e;
788 e << args[0] << " does not allow \""
789 << args[i] << "\" before a PATTERN or REGEX is given.";
790 this->SetError(e.str().c_str());
791 return false;
793 literal_args += " EXCLUDE";
794 doing_permissions_match = false;
796 else if(args[i] == "PERMISSIONS")
798 if(!in_match_mode)
800 cmOStringStream e;
801 e << args[0] << " does not allow \""
802 << args[i] << "\" before a PATTERN or REGEX is given.";
803 this->SetError(e.str().c_str());
804 return false;
807 // Switch to setting the current match permissions property.
808 literal_args += " PERMISSIONS";
809 doing_permissions_match = true;
811 else if(args[i] == "FILE_PERMISSIONS")
813 if(in_match_mode)
815 cmOStringStream e;
816 e << args[0] << " does not allow \""
817 << args[i] << "\" after PATTERN or REGEX.";
818 this->SetError(e.str().c_str());
819 return false;
822 // Switch to setting the file permissions property.
823 doing_dirs = false;
824 doing_destination = false;
825 doing_pattern = false;
826 doing_regex = false;
827 doing_permissions_file = true;
828 doing_permissions_dir = false;
829 doing_configurations = false;
830 doing_component = false;
832 else if(args[i] == "DIRECTORY_PERMISSIONS")
834 if(in_match_mode)
836 cmOStringStream e;
837 e << args[0] << " does not allow \""
838 << args[i] << "\" after PATTERN or REGEX.";
839 this->SetError(e.str().c_str());
840 return false;
843 // Switch to setting the directory permissions property.
844 doing_dirs = false;
845 doing_destination = false;
846 doing_pattern = false;
847 doing_regex = false;
848 doing_permissions_file = false;
849 doing_permissions_dir = true;
850 doing_configurations = false;
851 doing_component = false;
853 else if(args[i] == "USE_SOURCE_PERMISSIONS")
855 if(in_match_mode)
857 cmOStringStream e;
858 e << args[0] << " does not allow \""
859 << args[i] << "\" after PATTERN or REGEX.";
860 this->SetError(e.str().c_str());
861 return false;
864 // Add this option literally.
865 doing_dirs = false;
866 doing_destination = false;
867 doing_pattern = false;
868 doing_regex = false;
869 doing_permissions_file = false;
870 doing_permissions_dir = false;
871 doing_configurations = false;
872 doing_component = false;
873 literal_args += " USE_SOURCE_PERMISSIONS";
875 else if(args[i] == "FILES_MATCHING")
877 if(in_match_mode)
879 cmOStringStream e;
880 e << args[0] << " does not allow \""
881 << args[i] << "\" after PATTERN or REGEX.";
882 this->SetError(e.str().c_str());
883 return false;
886 // Add this option literally.
887 doing_dirs = false;
888 doing_destination = false;
889 doing_pattern = false;
890 doing_regex = false;
891 doing_permissions_file = false;
892 doing_permissions_dir = false;
893 doing_permissions_match = false;
894 doing_configurations = false;
895 doing_component = false;
896 literal_args += " FILES_MATCHING";
898 else if(args[i] == "CONFIGURATIONS")
900 if(in_match_mode)
902 cmOStringStream e;
903 e << args[0] << " does not allow \""
904 << args[i] << "\" after PATTERN or REGEX.";
905 this->SetError(e.str().c_str());
906 return false;
909 // Switch to setting the configurations property.
910 doing_dirs = false;
911 doing_destination = false;
912 doing_pattern = false;
913 doing_regex = false;
914 doing_permissions_file = false;
915 doing_permissions_dir = false;
916 doing_configurations = true;
917 doing_component = false;
919 else if(args[i] == "COMPONENT")
921 if(in_match_mode)
923 cmOStringStream e;
924 e << args[0] << " does not allow \""
925 << args[i] << "\" after PATTERN or REGEX.";
926 this->SetError(e.str().c_str());
927 return false;
930 // Switch to setting the component property.
931 doing_dirs = false;
932 doing_destination = false;
933 doing_pattern = false;
934 doing_regex = false;
935 doing_permissions_file = false;
936 doing_permissions_dir = false;
937 doing_configurations = false;
938 doing_component = true;
940 else if(doing_dirs)
942 // Convert this directory to a full path.
943 std::string dir = args[i];
944 if(!cmSystemTools::FileIsFullPath(dir.c_str()))
946 dir = this->Makefile->GetCurrentDirectory();
947 dir += "/";
948 dir += args[i];
951 // Make sure the name is a directory.
952 if(cmSystemTools::FileExists(dir.c_str()) &&
953 !cmSystemTools::FileIsDirectory(dir.c_str()))
955 cmOStringStream e;
956 e << args[0] << " given non-directory \""
957 << args[i] << "\" to install.";
958 this->SetError(e.str().c_str());
959 return false;
962 // Store the directory for installation.
963 dirs.push_back(dir);
965 else if(doing_configurations)
967 configurations.push_back(args[i]);
969 else if(doing_destination)
971 destination = args[i].c_str();
972 doing_destination = false;
974 else if(doing_pattern)
976 // Convert the pattern to a regular expression. Require a
977 // leading slash and trailing end-of-string in the matched
978 // string to make sure the pattern matches only whole file
979 // names.
980 literal_args += " REGEX \"/";
981 std::string regex = cmsys::Glob::PatternToRegex(args[i], false);
982 cmSystemTools::ReplaceString(regex, "\\", "\\\\");
983 literal_args += regex;
984 literal_args += "$\"";
985 doing_pattern = false;
987 else if(doing_regex)
989 literal_args += " REGEX \"";
990 // Match rules are case-insensitive on some platforms.
991 #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
992 std::string regex = cmSystemTools::LowerCase(args[i]);
993 #else
994 std::string regex = args[i];
995 #endif
996 cmSystemTools::ReplaceString(regex, "\\", "\\\\");
997 literal_args += regex;
998 literal_args += "\"";
999 doing_regex = false;
1001 else if(doing_component)
1003 component = args[i];
1004 doing_component = false;
1006 else if(doing_permissions_file)
1008 // Check the requested permission.
1009 if(!cmInstallCommandArguments::CheckPermissions(args[i],permissions_file))
1011 cmOStringStream e;
1012 e << args[0] << " given invalid file permission \""
1013 << args[i] << "\".";
1014 this->SetError(e.str().c_str());
1015 return false;
1018 else if(doing_permissions_dir)
1020 // Check the requested permission.
1021 if(!cmInstallCommandArguments::CheckPermissions(args[i],permissions_dir))
1023 cmOStringStream e;
1024 e << args[0] << " given invalid directory permission \""
1025 << args[i] << "\".";
1026 this->SetError(e.str().c_str());
1027 return false;
1030 else if(doing_permissions_match)
1032 // Check the requested permission.
1033 if(!cmInstallCommandArguments::CheckPermissions(args[i], literal_args))
1035 cmOStringStream e;
1036 e << args[0] << " given invalid permission \""
1037 << args[i] << "\".";
1038 this->SetError(e.str().c_str());
1039 return false;
1042 else
1044 // Unknown argument.
1045 cmOStringStream e;
1046 e << args[0] << " given unknown argument \"" << args[i] << "\".";
1047 this->SetError(e.str().c_str());
1048 return false;
1052 // Support installing an empty directory.
1053 if(dirs.empty() && destination)
1055 dirs.push_back("");
1058 // Check if there is something to do.
1059 if(dirs.empty())
1061 return true;
1063 if(!destination)
1065 // A destination is required.
1066 cmOStringStream e;
1067 e << args[0] << " given no DESTINATION!";
1068 this->SetError(e.str().c_str());
1069 return false;
1072 // Compute destination path.
1073 std::string dest;
1074 cmInstallCommandArguments::ComputeDestination(destination, dest);
1076 // Create the directory install generator.
1077 this->Makefile->AddInstallGenerator(
1078 new cmInstallDirectoryGenerator(dirs, dest.c_str(),
1079 permissions_file.c_str(),
1080 permissions_dir.c_str(),
1081 configurations,
1082 component.c_str(),
1083 literal_args.c_str()));
1085 // Tell the global generator about any installation component names
1086 // specified.
1087 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
1088 ->AddInstallComponent(component.c_str());
1090 return true;
1093 //----------------------------------------------------------------------------
1094 bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
1096 // This is the EXPORT mode.
1097 cmInstallCommandArguments ica;
1098 cmCAStringVector exports(&ica.Parser, "EXPORT");
1099 cmCAString prefix(&ica.Parser, "PREFIX", &ica.ArgumentGroup);
1100 cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
1101 exports.Follows(0);
1103 ica.ArgumentGroup.Follows(&exports);
1104 std::vector<std::string> unknownArgs;
1105 ica.Parse(&args, &unknownArgs);
1107 if (!unknownArgs.empty())
1109 // Unknown argument.
1110 cmOStringStream e;
1111 e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
1112 this->SetError(e.str().c_str());
1113 return false;
1116 if (!ica.Finalize())
1118 return false;
1121 std::string cmakeDir = this->Makefile->GetHomeOutputDirectory();
1122 cmakeDir += cmake::GetCMakeFilesDirectory();
1123 for(std::vector<std::string>::const_iterator
1124 exportIt = exports.GetVector().begin();
1125 exportIt != exports.GetVector().end();
1126 ++exportIt)
1128 const std::vector<cmTargetExport*>* exportSet = this->
1129 Makefile->GetLocalGenerator()->GetGlobalGenerator()->
1130 GetExportSet(exportIt->c_str());
1131 if (exportSet == 0)
1133 cmOStringStream e;
1134 e << "EXPORT given unknown export name \"" << exportIt->c_str() << "\".";
1135 this->SetError(e.str().c_str());
1136 return false;
1139 // Create the export install generator.
1140 cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
1141 ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
1142 ica.GetConfigurations(),0 , filename.GetCString(),
1143 prefix.GetCString(), cmakeDir.c_str());
1145 if (exportGenerator->SetExportSet(exportIt->c_str(),exportSet))
1147 this->Makefile->AddInstallGenerator(exportGenerator);
1149 else
1151 cmOStringStream e;
1152 e << "EXPORT failed, maybe a target is exported more than once.";
1153 this->SetError(e.str().c_str());
1154 delete exportGenerator;
1155 return false;
1159 return true;
1162 bool cmInstallCommand::MakeFilesFullPath(const char* modeName,
1163 const std::vector<std::string>& relFiles,
1164 std::vector<std::string>& absFiles)
1166 for(std::vector<std::string>::const_iterator fileIt = relFiles.begin();
1167 fileIt != relFiles.end();
1168 ++fileIt)
1170 std::string file = (*fileIt);
1171 if(!cmSystemTools::FileIsFullPath(file.c_str()))
1173 file = this->Makefile->GetCurrentDirectory();
1174 file += "/";
1175 file += *fileIt;
1178 // Make sure the file is not a directory.
1179 if(cmSystemTools::FileIsDirectory(file.c_str()))
1181 cmOStringStream e;
1182 e << modeName << " given directory \"" << (*fileIt) << "\" to install.";
1183 this->SetError(e.str().c_str());
1184 return false;
1186 // Store the file for installation.
1187 absFiles.push_back(file);
1189 return true;