Introduce "generator expressions" to add_test()
[cmake.git] / Source / cmInstallCommand.cxx
blob7d4ffcbd13cddbaac77b46d3ee5393cc1d447782
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmInstallCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2009-02-24 16:41:31 $
7 Version: $Revision: 1.51 $
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 // now parse the generic args (i.e. the ones not specialized on LIBRARY/
227 // ARCHIVE, RUNTIME etc. (see above)
228 // These generic args also contain the targets and the export stuff
229 std::vector<std::string> unknownArgs;
230 cmInstallCommandArguments genericArgs;
231 cmCAStringVector targetList(&genericArgs.Parser, "TARGETS");
232 cmCAString exports(&genericArgs.Parser,"EXPORT", &genericArgs.ArgumentGroup);
233 targetList.Follows(0);
234 genericArgs.ArgumentGroup.Follows(&targetList);
235 genericArgs.Parse(&genericArgVector.GetVector(), &unknownArgs);
236 bool success = genericArgs.Finalize();
238 cmInstallCommandArguments archiveArgs;
239 cmInstallCommandArguments libraryArgs;
240 cmInstallCommandArguments runtimeArgs;
241 cmInstallCommandArguments frameworkArgs;
242 cmInstallCommandArguments bundleArgs;
243 cmInstallCommandArguments privateHeaderArgs;
244 cmInstallCommandArguments publicHeaderArgs;
245 cmInstallCommandArguments resourceArgs;
247 // now parse the args for specific parts of the target (e.g. LIBRARY,
248 // RUNTIME, ARCHIVE etc.
249 archiveArgs.Parse (&archiveArgVector.GetVector(), &unknownArgs);
250 libraryArgs.Parse (&libraryArgVector.GetVector(), &unknownArgs);
251 runtimeArgs.Parse (&runtimeArgVector.GetVector(), &unknownArgs);
252 frameworkArgs.Parse (&frameworkArgVector.GetVector(), &unknownArgs);
253 bundleArgs.Parse (&bundleArgVector.GetVector(), &unknownArgs);
254 privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
255 publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(), &unknownArgs);
256 resourceArgs.Parse (&resourceArgVector.GetVector(), &unknownArgs);
258 if(!unknownArgs.empty())
260 // Unknown argument.
261 cmOStringStream e;
262 e << "TARGETS given unknown argument \"" << unknownArgs[0] << "\".";
263 this->SetError(e.str().c_str());
264 return false;
267 // apply generic args
268 archiveArgs.SetGenericArguments(&genericArgs);
269 libraryArgs.SetGenericArguments(&genericArgs);
270 runtimeArgs.SetGenericArguments(&genericArgs);
271 frameworkArgs.SetGenericArguments(&genericArgs);
272 bundleArgs.SetGenericArguments(&genericArgs);
273 privateHeaderArgs.SetGenericArguments(&genericArgs);
274 publicHeaderArgs.SetGenericArguments(&genericArgs);
275 resourceArgs.SetGenericArguments(&genericArgs);
277 success = success && archiveArgs.Finalize();
278 success = success && libraryArgs.Finalize();
279 success = success && runtimeArgs.Finalize();
280 success = success && frameworkArgs.Finalize();
281 success = success && bundleArgs.Finalize();
282 success = success && privateHeaderArgs.Finalize();
283 success = success && publicHeaderArgs.Finalize();
284 success = success && resourceArgs.Finalize();
286 if(!success)
288 return false;
291 // Enforce argument rules too complex to specify for the
292 // general-purpose parser.
293 if(archiveArgs.GetNamelinkOnly() ||
294 runtimeArgs.GetNamelinkOnly() ||
295 frameworkArgs.GetNamelinkOnly() ||
296 bundleArgs.GetNamelinkOnly() ||
297 privateHeaderArgs.GetNamelinkOnly() ||
298 publicHeaderArgs.GetNamelinkOnly() ||
299 resourceArgs.GetNamelinkOnly())
301 this->SetError(
302 "TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
303 "The NAMELINK_ONLY option may be specified only following LIBRARY."
305 return false;
307 if(archiveArgs.GetNamelinkSkip() ||
308 runtimeArgs.GetNamelinkSkip() ||
309 frameworkArgs.GetNamelinkSkip() ||
310 bundleArgs.GetNamelinkSkip() ||
311 privateHeaderArgs.GetNamelinkSkip() ||
312 publicHeaderArgs.GetNamelinkSkip() ||
313 resourceArgs.GetNamelinkSkip())
315 this->SetError(
316 "TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
317 "The NAMELINK_SKIP option may be specified only following LIBRARY."
319 return false;
321 if(libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip())
323 this->SetError(
324 "TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. "
325 "At most one of these two options may be specified."
327 return false;
330 // Select the mode for installing symlinks to versioned shared libraries.
331 cmInstallTargetGenerator::NamelinkModeType
332 namelinkMode = cmInstallTargetGenerator::NamelinkModeNone;
333 if(libraryArgs.GetNamelinkOnly())
335 namelinkMode = cmInstallTargetGenerator::NamelinkModeOnly;
337 else if(libraryArgs.GetNamelinkSkip())
339 namelinkMode = cmInstallTargetGenerator::NamelinkModeSkip;
342 // Check if there is something to do.
343 if(targetList.GetVector().empty())
345 return true;
348 // Check whether this is a DLL platform.
349 bool dll_platform = (this->Makefile->IsOn("WIN32") ||
350 this->Makefile->IsOn("CYGWIN") ||
351 this->Makefile->IsOn("MINGW"));
353 for(std::vector<std::string>::const_iterator
354 targetIt=targetList.GetVector().begin();
355 targetIt!=targetList.GetVector().end();
356 ++targetIt)
358 // Lookup this target in the current directory.
359 if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str()))
361 // Found the target. Check its type.
362 if(target->GetType() != cmTarget::EXECUTABLE &&
363 target->GetType() != cmTarget::STATIC_LIBRARY &&
364 target->GetType() != cmTarget::SHARED_LIBRARY &&
365 target->GetType() != cmTarget::MODULE_LIBRARY)
367 cmOStringStream e;
368 e << "TARGETS given target \"" << (*targetIt)
369 << "\" which is not an executable, library, or module.";
370 this->SetError(e.str().c_str());
371 return false;
373 // Store the target in the list to be installed.
374 targets.push_back(target);
376 else
378 // Did not find the target.
379 cmOStringStream e;
380 e << "TARGETS given target \"" << (*targetIt)
381 << "\" which does not exist in this directory.";
382 this->SetError(e.str().c_str());
383 return false;
387 // Keep track of whether we will be performing an installation of
388 // any files of the given type.
389 bool installsArchive = false;
390 bool installsLibrary = false;
391 bool installsRuntime = false;
392 bool installsFramework = false;
393 bool installsBundle = false;
394 bool installsPrivateHeader = false;
395 bool installsPublicHeader = false;
396 bool installsResource = false;
398 // Generate install script code to install the given targets.
399 for(std::vector<cmTarget*>::iterator ti = targets.begin();
400 ti != targets.end(); ++ti)
402 // Handle each target type.
403 cmTarget& target = *(*ti);
404 cmInstallTargetGenerator* archiveGenerator = 0;
405 cmInstallTargetGenerator* libraryGenerator = 0;
406 cmInstallTargetGenerator* runtimeGenerator = 0;
407 cmInstallTargetGenerator* frameworkGenerator = 0;
408 cmInstallTargetGenerator* bundleGenerator = 0;
409 cmInstallFilesGenerator* privateHeaderGenerator = 0;
410 cmInstallFilesGenerator* publicHeaderGenerator = 0;
411 cmInstallFilesGenerator* resourceGenerator = 0;
413 // Track whether this is a namelink-only rule.
414 bool namelinkOnly = false;
416 switch(target.GetType())
418 case cmTarget::SHARED_LIBRARY:
420 // Shared libraries are handled differently on DLL and non-DLL
421 // platforms. All windows platforms are DLL platforms including
422 // cygwin. Currently no other platform is a DLL platform.
423 if(dll_platform)
425 // When in namelink only mode skip all libraries on Windows.
426 if(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly)
428 continue;
431 // This is a DLL platform.
432 if(!archiveArgs.GetDestination().empty())
434 // The import library uses the ARCHIVE properties.
435 archiveGenerator = CreateInstallTargetGenerator(target,
436 archiveArgs, true);
438 if(!runtimeArgs.GetDestination().empty())
440 // The DLL uses the RUNTIME properties.
441 runtimeGenerator = CreateInstallTargetGenerator(target,
442 runtimeArgs, false);
444 if ((archiveGenerator==0) && (runtimeGenerator==0))
446 this->SetError("Library TARGETS given no DESTINATION!");
447 return false;
450 else
452 // This is a non-DLL platform.
453 // If it is marked with FRAMEWORK property use the FRAMEWORK set of
454 // INSTALL properties. Otherwise, use the LIBRARY properties.
455 if(target.IsFrameworkOnApple())
457 // When in namelink only mode skip frameworks.
458 if(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly)
460 continue;
463 // Use the FRAMEWORK properties.
464 if (!frameworkArgs.GetDestination().empty())
466 frameworkGenerator = CreateInstallTargetGenerator(target,
467 frameworkArgs, false);
469 else
471 cmOStringStream e;
472 e << "TARGETS given no FRAMEWORK DESTINATION for shared library "
473 "FRAMEWORK target \"" << target.GetName() << "\".";
474 this->SetError(e.str().c_str());
475 return false;
478 else
480 // The shared library uses the LIBRARY properties.
481 if (!libraryArgs.GetDestination().empty())
483 libraryGenerator = CreateInstallTargetGenerator(target,
484 libraryArgs, false);
485 libraryGenerator->SetNamelinkMode(namelinkMode);
486 namelinkOnly =
487 (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
489 else
491 cmOStringStream e;
492 e << "TARGETS given no LIBRARY DESTINATION for shared library "
493 "target \"" << target.GetName() << "\".";
494 this->SetError(e.str().c_str());
495 return false;
500 break;
501 case cmTarget::STATIC_LIBRARY:
503 // Static libraries use ARCHIVE properties.
504 if (!archiveArgs.GetDestination().empty())
506 archiveGenerator = CreateInstallTargetGenerator(target, archiveArgs,
507 false);
509 else
511 cmOStringStream e;
512 e << "TARGETS given no ARCHIVE DESTINATION for static library "
513 "target \"" << target.GetName() << "\".";
514 this->SetError(e.str().c_str());
515 return false;
518 break;
519 case cmTarget::MODULE_LIBRARY:
521 // Modules use LIBRARY properties.
522 if (!libraryArgs.GetDestination().empty())
524 libraryGenerator = CreateInstallTargetGenerator(target, libraryArgs,
525 false);
526 libraryGenerator->SetNamelinkMode(namelinkMode);
527 namelinkOnly =
528 (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
530 else
532 cmOStringStream e;
533 e << "TARGETS given no LIBRARY DESTINATION for module target \""
534 << target.GetName() << "\".";
535 this->SetError(e.str().c_str());
536 return false;
539 break;
540 case cmTarget::EXECUTABLE:
542 if(target.IsAppBundleOnApple())
544 // Application bundles use the BUNDLE properties.
545 if (!bundleArgs.GetDestination().empty())
547 bundleGenerator = CreateInstallTargetGenerator(target, bundleArgs,
548 false);
550 else if(!runtimeArgs.GetDestination().empty())
552 bool failure = false;
553 if(this->CheckCMP0006(failure))
555 // For CMake 2.4 compatibility fallback to the RUNTIME
556 // properties.
557 bundleGenerator =
558 CreateInstallTargetGenerator(target, runtimeArgs, false);
560 else if(failure)
562 return false;
565 if(!bundleGenerator)
567 cmOStringStream e;
568 e << "TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE "
569 "executable target \"" << target.GetName() << "\".";
570 this->SetError(e.str().c_str());
571 return false;
574 else
576 // Executables use the RUNTIME properties.
577 if (!runtimeArgs.GetDestination().empty())
579 runtimeGenerator = CreateInstallTargetGenerator(target,
580 runtimeArgs, false);
582 else
584 cmOStringStream e;
585 e << "TARGETS given no RUNTIME DESTINATION for executable "
586 "target \"" << target.GetName() << "\".";
587 this->SetError(e.str().c_str());
588 return false;
592 // On DLL platforms an executable may also have an import
593 // library. Install it to the archive destination if it
594 // exists.
595 if(dll_platform && !archiveArgs.GetDestination().empty() &&
596 target.IsExecutableWithExports())
598 // The import library uses the ARCHIVE properties.
599 archiveGenerator = CreateInstallTargetGenerator(target,
600 archiveArgs, true, true);
603 break;
604 default:
605 // This should never happen due to the above type check.
606 // Ignore the case.
607 break;
610 // These well-known sets of files are installed *automatically* for FRAMEWORK
611 // SHARED library targets on the Mac as part of installing the FRAMEWORK.
612 // For other target types or on other platforms, they are not installed
613 // automatically and so we need to create install files generators for them.
615 bool createInstallGeneratorsForTargetFileSets = true;
617 if(target.IsFrameworkOnApple())
619 createInstallGeneratorsForTargetFileSets = false;
622 if(createInstallGeneratorsForTargetFileSets && !namelinkOnly)
624 const char* files = target.GetProperty("PRIVATE_HEADER");
625 if ((files) && (*files))
627 std::vector<std::string> relFiles;
628 cmSystemTools::ExpandListArgument(files, relFiles);
629 std::vector<std::string> absFiles;
630 if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles))
632 return false;
635 // Create the files install generator.
636 if (!privateHeaderArgs.GetDestination().empty())
638 privateHeaderGenerator = CreateInstallFilesGenerator(absFiles,
639 privateHeaderArgs, false);
641 else
643 cmOStringStream e;
644 e << "INSTALL TARGETS - target " << target.GetName() << " has "
645 << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
646 cmSystemTools::Message(e.str().c_str(), "Warning");
650 files = target.GetProperty("PUBLIC_HEADER");
651 if ((files) && (*files))
653 std::vector<std::string> relFiles;
654 cmSystemTools::ExpandListArgument(files, relFiles);
655 std::vector<std::string> absFiles;
656 if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles))
658 return false;
661 // Create the files install generator.
662 if (!publicHeaderArgs.GetDestination().empty())
664 publicHeaderGenerator = CreateInstallFilesGenerator(absFiles,
665 publicHeaderArgs, false);
667 else
669 cmOStringStream e;
670 e << "INSTALL TARGETS - target " << target.GetName() << " has "
671 << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
672 cmSystemTools::Message(e.str().c_str(), "Warning");
676 files = target.GetProperty("RESOURCE");
677 if ((files) && (*files))
679 std::vector<std::string> relFiles;
680 cmSystemTools::ExpandListArgument(files, relFiles);
681 std::vector<std::string> absFiles;
682 if (!this->MakeFilesFullPath("RESOURCE", relFiles, absFiles))
684 return false;
687 // Create the files install generator.
688 if (!resourceArgs.GetDestination().empty())
690 resourceGenerator = CreateInstallFilesGenerator(absFiles,
691 resourceArgs, false);
693 else
695 cmOStringStream e;
696 e << "INSTALL TARGETS - target " << target.GetName() << " has "
697 << "RESOURCE files but no RESOURCE DESTINATION.";
698 cmSystemTools::Message(e.str().c_str(), "Warning");
703 // Keep track of whether we're installing anything in each category
704 installsArchive = installsArchive || archiveGenerator != 0;
705 installsLibrary = installsLibrary || libraryGenerator != 0;
706 installsRuntime = installsRuntime || runtimeGenerator != 0;
707 installsFramework = installsFramework || frameworkGenerator != 0;
708 installsBundle = installsBundle || bundleGenerator != 0;
709 installsPrivateHeader = installsPrivateHeader
710 || privateHeaderGenerator != 0;
711 installsPublicHeader = installsPublicHeader || publicHeaderGenerator != 0;
712 installsResource = installsResource || resourceGenerator;
714 this->Makefile->AddInstallGenerator(archiveGenerator);
715 this->Makefile->AddInstallGenerator(libraryGenerator);
716 this->Makefile->AddInstallGenerator(runtimeGenerator);
717 this->Makefile->AddInstallGenerator(frameworkGenerator);
718 this->Makefile->AddInstallGenerator(bundleGenerator);
719 this->Makefile->AddInstallGenerator(privateHeaderGenerator);
720 this->Makefile->AddInstallGenerator(publicHeaderGenerator);
721 this->Makefile->AddInstallGenerator(resourceGenerator);
723 // Add this install rule to an export if one was specified and
724 // this is not a namelink-only rule.
725 if(!exports.GetString().empty() && !namelinkOnly)
727 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
728 ->AddTargetToExports(exports.GetCString(), &target,
729 archiveGenerator, runtimeGenerator,
730 libraryGenerator, frameworkGenerator,
731 bundleGenerator, publicHeaderGenerator);
735 // Tell the global generator about any installation component names
736 // specified
737 if (installsArchive)
739 this->Makefile->GetLocalGenerator()->
740 GetGlobalGenerator()
741 ->AddInstallComponent(archiveArgs.GetComponent().c_str());
743 if (installsLibrary)
745 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
746 ->AddInstallComponent(libraryArgs.GetComponent().c_str());
748 if (installsRuntime)
750 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
751 ->AddInstallComponent(runtimeArgs.GetComponent().c_str());
753 if (installsFramework)
755 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
756 ->AddInstallComponent(frameworkArgs.GetComponent().c_str());
758 if (installsBundle)
760 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
761 ->AddInstallComponent(bundleArgs.GetComponent().c_str());
763 if (installsPrivateHeader)
765 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
766 ->AddInstallComponent(privateHeaderArgs.GetComponent().c_str());
768 if (installsPublicHeader)
770 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
771 ->AddInstallComponent(publicHeaderArgs.GetComponent().c_str());
773 if (installsResource)
775 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
776 ->AddInstallComponent(resourceArgs.GetComponent().c_str());
779 return true;
782 //----------------------------------------------------------------------------
783 bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
785 // This is the FILES mode.
786 bool programs = (args[0] == "PROGRAMS");
787 cmInstallCommandArguments ica;
788 cmCAStringVector files(&ica.Parser, programs ? "PROGRAMS" : "FILES");
789 files.Follows(0);
790 ica.ArgumentGroup.Follows(&files);
791 std::vector<std::string> unknownArgs;
792 ica.Parse(&args, &unknownArgs);
794 if(!unknownArgs.empty())
796 // Unknown argument.
797 cmOStringStream e;
798 e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
799 this->SetError(e.str().c_str());
800 return false;
803 // Check if there is something to do.
804 if(files.GetVector().empty())
806 return true;
809 if(!ica.GetRename().empty() && files.GetVector().size() > 1)
811 // The rename option works only with one file.
812 cmOStringStream e;
813 e << args[0] << " given RENAME option with more than one file.";
814 this->SetError(e.str().c_str());
815 return false;
818 std::vector<std::string> absFiles;
819 if (!this->MakeFilesFullPath(args[0].c_str(), files.GetVector(), absFiles))
821 return false;
824 if (!ica.Finalize())
826 return false;
829 if(ica.GetDestination().empty())
831 // A destination is required.
832 cmOStringStream e;
833 e << args[0] << " given no DESTINATION!";
834 this->SetError(e.str().c_str());
835 return false;
838 // Create the files install generator.
839 this->Makefile->AddInstallGenerator(
840 CreateInstallFilesGenerator(absFiles, ica, programs));
842 //Tell the global generator about any installation component names specified.
843 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
844 ->AddInstallComponent(ica.GetComponent().c_str());
846 return true;
849 //----------------------------------------------------------------------------
850 bool
851 cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
853 enum Doing { DoingNone, DoingDirs, DoingDestination, DoingPattern,
854 DoingRegex, DoingPermsFile, DoingPermsDir, DoingPermsMatch,
855 DoingConfigurations, DoingComponent };
856 Doing doing = DoingDirs;
857 bool in_match_mode = false;
858 bool optional = false;
859 std::vector<std::string> dirs;
860 const char* destination = 0;
861 std::string permissions_file;
862 std::string permissions_dir;
863 std::vector<std::string> configurations;
864 std::string component = "Unspecified";
865 std::string literal_args;
866 for(unsigned int i=1; i < args.size(); ++i)
868 if(args[i] == "DESTINATION")
870 if(in_match_mode)
872 cmOStringStream e;
873 e << args[0] << " does not allow \""
874 << args[i] << "\" after PATTERN or REGEX.";
875 this->SetError(e.str().c_str());
876 return false;
879 // Switch to setting the destination property.
880 doing = DoingDestination;
882 else if(args[i] == "OPTIONAL")
884 if(in_match_mode)
886 cmOStringStream e;
887 e << args[0] << " does not allow \""
888 << args[i] << "\" after PATTERN or REGEX.";
889 this->SetError(e.str().c_str());
890 return false;
893 // Mark the rule as optional.
894 optional = true;
895 doing = DoingNone;
897 else if(args[i] == "PATTERN")
899 // Switch to a new pattern match rule.
900 doing = DoingPattern;
901 in_match_mode = true;
903 else if(args[i] == "REGEX")
905 // Switch to a new regex match rule.
906 doing = DoingRegex;
907 in_match_mode = true;
909 else if(args[i] == "EXCLUDE")
911 // Add this property to the current match rule.
912 if(!in_match_mode || doing == DoingPattern || doing == DoingRegex)
914 cmOStringStream e;
915 e << args[0] << " does not allow \""
916 << args[i] << "\" before a PATTERN or REGEX is given.";
917 this->SetError(e.str().c_str());
918 return false;
920 literal_args += " EXCLUDE";
921 doing = DoingNone;
923 else if(args[i] == "PERMISSIONS")
925 if(!in_match_mode)
927 cmOStringStream e;
928 e << args[0] << " does not allow \""
929 << args[i] << "\" before a PATTERN or REGEX is given.";
930 this->SetError(e.str().c_str());
931 return false;
934 // Switch to setting the current match permissions property.
935 literal_args += " PERMISSIONS";
936 doing = DoingPermsMatch;
938 else if(args[i] == "FILE_PERMISSIONS")
940 if(in_match_mode)
942 cmOStringStream e;
943 e << args[0] << " does not allow \""
944 << args[i] << "\" after PATTERN or REGEX.";
945 this->SetError(e.str().c_str());
946 return false;
949 // Switch to setting the file permissions property.
950 doing = DoingPermsFile;
952 else if(args[i] == "DIRECTORY_PERMISSIONS")
954 if(in_match_mode)
956 cmOStringStream e;
957 e << args[0] << " does not allow \""
958 << args[i] << "\" after PATTERN or REGEX.";
959 this->SetError(e.str().c_str());
960 return false;
963 // Switch to setting the directory permissions property.
964 doing = DoingPermsDir;
966 else if(args[i] == "USE_SOURCE_PERMISSIONS")
968 if(in_match_mode)
970 cmOStringStream e;
971 e << args[0] << " does not allow \""
972 << args[i] << "\" after PATTERN or REGEX.";
973 this->SetError(e.str().c_str());
974 return false;
977 // Add this option literally.
978 literal_args += " USE_SOURCE_PERMISSIONS";
979 doing = DoingNone;
981 else if(args[i] == "FILES_MATCHING")
983 if(in_match_mode)
985 cmOStringStream e;
986 e << args[0] << " does not allow \""
987 << args[i] << "\" after PATTERN or REGEX.";
988 this->SetError(e.str().c_str());
989 return false;
992 // Add this option literally.
993 literal_args += " FILES_MATCHING";
994 doing = DoingNone;
996 else if(args[i] == "CONFIGURATIONS")
998 if(in_match_mode)
1000 cmOStringStream e;
1001 e << args[0] << " does not allow \""
1002 << args[i] << "\" after PATTERN or REGEX.";
1003 this->SetError(e.str().c_str());
1004 return false;
1007 // Switch to setting the configurations property.
1008 doing = DoingConfigurations;
1010 else if(args[i] == "COMPONENT")
1012 if(in_match_mode)
1014 cmOStringStream e;
1015 e << args[0] << " does not allow \""
1016 << args[i] << "\" after PATTERN or REGEX.";
1017 this->SetError(e.str().c_str());
1018 return false;
1021 // Switch to setting the component property.
1022 doing = DoingComponent;
1024 else if(doing == DoingDirs)
1026 // Convert this directory to a full path.
1027 std::string dir = args[i];
1028 if(!cmSystemTools::FileIsFullPath(dir.c_str()))
1030 dir = this->Makefile->GetCurrentDirectory();
1031 dir += "/";
1032 dir += args[i];
1035 // Make sure the name is a directory.
1036 if(cmSystemTools::FileExists(dir.c_str()) &&
1037 !cmSystemTools::FileIsDirectory(dir.c_str()))
1039 cmOStringStream e;
1040 e << args[0] << " given non-directory \""
1041 << args[i] << "\" to install.";
1042 this->SetError(e.str().c_str());
1043 return false;
1046 // Store the directory for installation.
1047 dirs.push_back(dir);
1049 else if(doing == DoingConfigurations)
1051 configurations.push_back(args[i]);
1053 else if(doing == DoingDestination)
1055 destination = args[i].c_str();
1056 doing = DoingNone;
1058 else if(doing == DoingPattern)
1060 // Convert the pattern to a regular expression. Require a
1061 // leading slash and trailing end-of-string in the matched
1062 // string to make sure the pattern matches only whole file
1063 // names.
1064 literal_args += " REGEX \"/";
1065 std::string regex = cmsys::Glob::PatternToRegex(args[i], false);
1066 cmSystemTools::ReplaceString(regex, "\\", "\\\\");
1067 literal_args += regex;
1068 literal_args += "$\"";
1069 doing = DoingNone;
1071 else if(doing == DoingRegex)
1073 literal_args += " REGEX \"";
1074 // Match rules are case-insensitive on some platforms.
1075 #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
1076 std::string regex = cmSystemTools::LowerCase(args[i]);
1077 #else
1078 std::string regex = args[i];
1079 #endif
1080 cmSystemTools::ReplaceString(regex, "\\", "\\\\");
1081 literal_args += regex;
1082 literal_args += "\"";
1083 doing = DoingNone;
1085 else if(doing == DoingComponent)
1087 component = args[i];
1088 doing = DoingNone;
1090 else if(doing == DoingPermsFile)
1092 // Check the requested permission.
1093 if(!cmInstallCommandArguments::CheckPermissions(args[i],permissions_file))
1095 cmOStringStream e;
1096 e << args[0] << " given invalid file permission \""
1097 << args[i] << "\".";
1098 this->SetError(e.str().c_str());
1099 return false;
1102 else if(doing == DoingPermsDir)
1104 // Check the requested permission.
1105 if(!cmInstallCommandArguments::CheckPermissions(args[i],permissions_dir))
1107 cmOStringStream e;
1108 e << args[0] << " given invalid directory permission \""
1109 << args[i] << "\".";
1110 this->SetError(e.str().c_str());
1111 return false;
1114 else if(doing == DoingPermsMatch)
1116 // Check the requested permission.
1117 if(!cmInstallCommandArguments::CheckPermissions(args[i], literal_args))
1119 cmOStringStream e;
1120 e << args[0] << " given invalid permission \""
1121 << args[i] << "\".";
1122 this->SetError(e.str().c_str());
1123 return false;
1126 else
1128 // Unknown argument.
1129 cmOStringStream e;
1130 e << args[0] << " given unknown argument \"" << args[i] << "\".";
1131 this->SetError(e.str().c_str());
1132 return false;
1136 // Support installing an empty directory.
1137 if(dirs.empty() && destination)
1139 dirs.push_back("");
1142 // Check if there is something to do.
1143 if(dirs.empty())
1145 return true;
1147 if(!destination)
1149 // A destination is required.
1150 cmOStringStream e;
1151 e << args[0] << " given no DESTINATION!";
1152 this->SetError(e.str().c_str());
1153 return false;
1156 // Create the directory install generator.
1157 this->Makefile->AddInstallGenerator(
1158 new cmInstallDirectoryGenerator(dirs, destination,
1159 permissions_file.c_str(),
1160 permissions_dir.c_str(),
1161 configurations,
1162 component.c_str(),
1163 literal_args.c_str(),
1164 optional));
1166 // Tell the global generator about any installation component names
1167 // specified.
1168 this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
1169 ->AddInstallComponent(component.c_str());
1171 return true;
1174 //----------------------------------------------------------------------------
1175 bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
1177 // This is the EXPORT mode.
1178 cmInstallCommandArguments ica;
1179 cmCAString exp(&ica.Parser, "EXPORT");
1180 cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
1181 cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
1182 exp.Follows(0);
1184 ica.ArgumentGroup.Follows(&exp);
1185 std::vector<std::string> unknownArgs;
1186 ica.Parse(&args, &unknownArgs);
1188 if (!unknownArgs.empty())
1190 // Unknown argument.
1191 cmOStringStream e;
1192 e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
1193 this->SetError(e.str().c_str());
1194 return false;
1197 if (!ica.Finalize())
1199 return false;
1202 // Make sure there is a destination.
1203 if(ica.GetDestination().empty())
1205 // A destination is required.
1206 cmOStringStream e;
1207 e << args[0] << " given no DESTINATION!";
1208 this->SetError(e.str().c_str());
1209 return false;
1212 // Check the file name.
1213 std::string fname = filename.GetString();
1214 if(fname.find_first_of(":/\\") != fname.npos)
1216 cmOStringStream e;
1217 e << args[0] << " given invalid export file name \"" << fname << "\". "
1218 << "The FILE argument may not contain a path. "
1219 << "Specify the path in the DESTINATION argument.";
1220 this->SetError(e.str().c_str());
1221 return false;
1224 // Check the file extension.
1225 if(!fname.empty() &&
1226 cmSystemTools::GetFilenameLastExtension(fname) != ".cmake")
1228 cmOStringStream e;
1229 e << args[0] << " given invalid export file name \"" << fname << "\". "
1230 << "The FILE argument must specify a name ending in \".cmake\".";
1231 this->SetError(e.str().c_str());
1232 return false;
1235 // Construct the file name.
1236 if(fname.empty())
1238 fname = exp.GetString();
1239 fname += ".cmake";
1241 if(fname.find_first_of(":/\\") != fname.npos)
1243 cmOStringStream e;
1244 e << args[0] << " given export name \"" << exp.GetString() << "\". "
1245 << "This name cannot be safely converted to a file name. "
1246 << "Specify a different export name or use the FILE option to set "
1247 << "a file name explicitly.";
1248 this->SetError(e.str().c_str());
1249 return false;
1253 // Create the export install generator.
1254 cmInstallExportGenerator* exportGenerator =
1255 new cmInstallExportGenerator(
1256 exp.GetCString(), ica.GetDestination().c_str(),
1257 ica.GetPermissions().c_str(), ica.GetConfigurations(),
1258 ica.GetComponent().c_str(), fname.c_str(),
1259 name_space.GetCString(), this->Makefile);
1260 this->Makefile->AddInstallGenerator(exportGenerator);
1262 return true;
1265 bool cmInstallCommand::MakeFilesFullPath(const char* modeName,
1266 const std::vector<std::string>& relFiles,
1267 std::vector<std::string>& absFiles)
1269 for(std::vector<std::string>::const_iterator fileIt = relFiles.begin();
1270 fileIt != relFiles.end();
1271 ++fileIt)
1273 std::string file = (*fileIt);
1274 if(!cmSystemTools::FileIsFullPath(file.c_str()))
1276 file = this->Makefile->GetCurrentDirectory();
1277 file += "/";
1278 file += *fileIt;
1281 // Make sure the file is not a directory.
1282 if(cmSystemTools::FileIsDirectory(file.c_str()))
1284 cmOStringStream e;
1285 e << modeName << " given directory \"" << (*fileIt) << "\" to install.";
1286 this->SetError(e.str().c_str());
1287 return false;
1289 // Store the file for installation.
1290 absFiles.push_back(file);
1292 return true;
1295 //----------------------------------------------------------------------------
1296 bool cmInstallCommand::CheckCMP0006(bool& failure)
1298 switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0006))
1300 case cmPolicies::WARN:
1302 this->Makefile->IssueMessage(
1303 cmake::AUTHOR_WARNING,
1304 this->Makefile->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0006)
1307 case cmPolicies::OLD:
1308 // OLD behavior is to allow compatibility
1309 return true;
1310 case cmPolicies::NEW:
1311 // NEW behavior is to disallow compatibility
1312 break;
1313 case cmPolicies::REQUIRED_IF_USED:
1314 case cmPolicies::REQUIRED_ALWAYS:
1315 failure = true;
1316 this->Makefile->IssueMessage(
1317 cmake::FATAL_ERROR,
1318 this->Makefile->GetPolicies()
1319 ->GetRequiredPolicyError(cmPolicies::CMP0006)
1321 break;
1323 return false;