1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmInstallCommand.cxx,v $
6 Date: $Date: 2008-02-07 21:22:00 $
7 Version: $Revision: 1.45 $
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());
49 bool cmInstallCommand::InitialPass(std::vector
<std::string
> const& args
,
52 // Allow calling with no arguments so that arguments may be built up
53 // using a variable that may be left empty.
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
);
94 cmStdString e
= "called with unknown mode ";
96 this->SetError(e
.c_str());
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())
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.");
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")
138 else if(args
[i
] == "CODE")
140 doing_script
= false;
143 else if(args
[i
] == "COMPONENT")
145 doing_script
= 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();
158 if(cmSystemTools::FileIsDirectory(script
.c_str()))
160 this->SetError("given a directory as value of SCRIPT argument.");
163 this->Makefile
->AddInstallGenerator(
164 new cmInstallScriptGenerator(script
.c_str(), false,
170 std::string code
= args
[i
];
171 this->Makefile
->AddInstallGenerator(
172 new cmInstallScriptGenerator(code
.c_str(), true,
179 this->SetError("given no value for SCRIPT argument.");
184 this->SetError("given no value for CODE argument.");
188 //Tell the global generator about any installation component names specified.
189 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
190 ->AddInstallComponent(component
.c_str());
198 InstallPart(cmCommandArgumentsHelper* helper, const char* key,
199 cmCommandArgumentGroup* group);
200 cmCAStringVector argVector;
201 cmInstallCommandArguments args;
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())
262 e
<< "TARGETS given unknown argument \"" << unknownArgs
[0] << "\".";
263 this->SetError(e
.str().c_str());
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();
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())
302 "TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
303 "The NAMELINK_ONLY option may be specified only following LIBRARY."
307 if(archiveArgs
.GetNamelinkSkip() ||
308 runtimeArgs
.GetNamelinkSkip() ||
309 frameworkArgs
.GetNamelinkSkip() ||
310 bundleArgs
.GetNamelinkSkip() ||
311 privateHeaderArgs
.GetNamelinkSkip() ||
312 publicHeaderArgs
.GetNamelinkSkip() ||
313 resourceArgs
.GetNamelinkSkip())
316 "TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
317 "The NAMELINK_SKIP option may be specified only following LIBRARY."
321 if(libraryArgs
.GetNamelinkOnly() && libraryArgs
.GetNamelinkSkip())
324 "TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. "
325 "At most one of these two options may be specified."
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())
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();
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
)
368 e
<< "TARGETS given target \"" << (*targetIt
)
369 << "\" which is not an executable, library, or module.";
370 this->SetError(e
.str().c_str());
373 // Store the target in the list to be installed.
374 targets
.push_back(target
);
378 // Did not find the target.
380 e
<< "TARGETS given target \"" << (*targetIt
)
381 << "\" which does not exist in this directory.";
382 this->SetError(e
.str().c_str());
387 // Generate install script code to install the given targets.
388 for(std::vector
<cmTarget
*>::iterator ti
= targets
.begin();
389 ti
!= targets
.end(); ++ti
)
391 // Handle each target type.
392 cmTarget
& target
= *(*ti
);
393 cmInstallTargetGenerator
* archiveGenerator
= 0;
394 cmInstallTargetGenerator
* libraryGenerator
= 0;
395 cmInstallTargetGenerator
* runtimeGenerator
= 0;
396 cmInstallTargetGenerator
* frameworkGenerator
= 0;
397 cmInstallTargetGenerator
* bundleGenerator
= 0;
398 cmInstallFilesGenerator
* privateHeaderGenerator
= 0;
399 cmInstallFilesGenerator
* publicHeaderGenerator
= 0;
400 cmInstallFilesGenerator
* resourceGenerator
= 0;
402 // Track whether this is a namelink-only rule.
403 bool namelinkOnly
= false;
405 switch(target
.GetType())
407 case cmTarget::SHARED_LIBRARY
:
409 // Shared libraries are handled differently on DLL and non-DLL
410 // platforms. All windows platforms are DLL platforms including
411 // cygwin. Currently no other platform is a DLL platform.
414 // When in namelink only mode skip all libraries on Windows.
415 if(namelinkMode
== cmInstallTargetGenerator::NamelinkModeOnly
)
420 // This is a DLL platform.
421 if(!archiveArgs
.GetDestination().empty())
423 // The import library uses the ARCHIVE properties.
424 archiveGenerator
= CreateInstallTargetGenerator(target
,
427 if(!runtimeArgs
.GetDestination().empty())
429 // The DLL uses the RUNTIME properties.
430 runtimeGenerator
= CreateInstallTargetGenerator(target
,
433 if ((archiveGenerator
==0) && (runtimeGenerator
==0))
435 this->SetError("Library TARGETS given no DESTINATION!");
441 // This is a non-DLL platform.
442 // If it is marked with FRAMEWORK property use the FRAMEWORK set of
443 // INSTALL properties. Otherwise, use the LIBRARY properties.
444 if(target
.IsFrameworkOnApple())
446 // When in namelink only mode skip frameworks.
447 if(namelinkMode
== cmInstallTargetGenerator::NamelinkModeOnly
)
452 // Use the FRAMEWORK properties.
453 if (!frameworkArgs
.GetDestination().empty())
455 frameworkGenerator
= CreateInstallTargetGenerator(target
,
456 frameworkArgs
, false);
461 e
<< "TARGETS given no FRAMEWORK DESTINATION for shared library "
462 "FRAMEWORK target \"" << target
.GetName() << "\".";
463 this->SetError(e
.str().c_str());
469 // The shared library uses the LIBRARY properties.
470 if (!libraryArgs
.GetDestination().empty())
472 libraryGenerator
= CreateInstallTargetGenerator(target
,
474 libraryGenerator
->SetNamelinkMode(namelinkMode
);
476 (namelinkMode
== cmInstallTargetGenerator::NamelinkModeOnly
);
481 e
<< "TARGETS given no LIBRARY DESTINATION for shared library "
482 "target \"" << target
.GetName() << "\".";
483 this->SetError(e
.str().c_str());
490 case cmTarget::STATIC_LIBRARY
:
492 // Static libraries use ARCHIVE properties.
493 if (!archiveArgs
.GetDestination().empty())
495 archiveGenerator
= CreateInstallTargetGenerator(target
, archiveArgs
,
501 e
<< "TARGETS given no ARCHIVE DESTINATION for static library "
502 "target \"" << target
.GetName() << "\".";
503 this->SetError(e
.str().c_str());
508 case cmTarget::MODULE_LIBRARY
:
510 // Modules use LIBRARY properties.
511 if (!libraryArgs
.GetDestination().empty())
513 libraryGenerator
= CreateInstallTargetGenerator(target
, libraryArgs
,
515 libraryGenerator
->SetNamelinkMode(namelinkMode
);
517 (namelinkMode
== cmInstallTargetGenerator::NamelinkModeOnly
);
522 e
<< "TARGETS given no LIBRARY DESTINATION for module target \""
523 << target
.GetName() << "\".";
524 this->SetError(e
.str().c_str());
529 case cmTarget::EXECUTABLE
:
531 if(target
.IsAppBundleOnApple())
533 // Application bundles use the BUNDLE properties.
534 if (!bundleArgs
.GetDestination().empty())
536 bundleGenerator
= CreateInstallTargetGenerator(target
, bundleArgs
,
542 e
<< "TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE "
543 "executable target \"" << target
.GetName() << "\".";
544 this->SetError(e
.str().c_str());
550 // Executables use the RUNTIME properties.
551 if (!runtimeArgs
.GetDestination().empty())
553 runtimeGenerator
= CreateInstallTargetGenerator(target
,
559 e
<< "TARGETS given no RUNTIME DESTINATION for executable "
560 "target \"" << target
.GetName() << "\".";
561 this->SetError(e
.str().c_str());
566 // On DLL platforms an executable may also have an import
567 // library. Install it to the archive destination if it
569 if(dll_platform
&& !archiveArgs
.GetDestination().empty() &&
570 target
.IsExecutableWithExports())
572 // The import library uses the ARCHIVE properties.
573 archiveGenerator
= CreateInstallTargetGenerator(target
,
574 archiveArgs
, true, true);
579 // This should never happen due to the above type check.
584 // if(target.GetProperty("ASSOCIATED_FILES");
586 // These well-known sets of files are installed *automatically* for FRAMEWORK
587 // SHARED library targets on the Mac as part of installing the FRAMEWORK.
588 // For other target types or on other platforms, they are not installed
589 // automatically and so we need to create install files generators for them.
591 bool createInstallGeneratorsForTargetFileSets
= true;
593 if(target
.IsFrameworkOnApple())
595 createInstallGeneratorsForTargetFileSets
= false;
598 if(createInstallGeneratorsForTargetFileSets
&& !namelinkOnly
)
600 const char* files
= target
.GetProperty("PRIVATE_HEADER");
601 if ((files
) && (*files
))
603 std::vector
<std::string
> relFiles
;
604 cmSystemTools::ExpandListArgument(files
, relFiles
);
605 std::vector
<std::string
> absFiles
;
606 if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles
, absFiles
))
611 // Create the files install generator.
612 if (!privateHeaderArgs
.GetDestination().empty())
614 privateHeaderGenerator
= CreateInstallFilesGenerator(absFiles
,
615 privateHeaderArgs
, false);
620 e
<< "INSTALL TARGETS - target " << target
.GetName() << " has "
621 << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
622 cmSystemTools::Message(e
.str().c_str(), "Warning");
626 files
= target
.GetProperty("PUBLIC_HEADER");
627 if ((files
) && (*files
))
629 std::vector
<std::string
> relFiles
;
630 cmSystemTools::ExpandListArgument(files
, relFiles
);
631 std::vector
<std::string
> absFiles
;
632 if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles
, absFiles
))
637 // Create the files install generator.
638 if (!publicHeaderArgs
.GetDestination().empty())
640 publicHeaderGenerator
= CreateInstallFilesGenerator(absFiles
,
641 publicHeaderArgs
, false);
646 e
<< "INSTALL TARGETS - target " << target
.GetName() << " has "
647 << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
648 cmSystemTools::Message(e
.str().c_str(), "Warning");
652 files
= target
.GetProperty("RESOURCE");
653 if ((files
) && (*files
))
655 std::vector
<std::string
> relFiles
;
656 cmSystemTools::ExpandListArgument(files
, relFiles
);
657 std::vector
<std::string
> absFiles
;
658 if (!this->MakeFilesFullPath("RESOURCE", relFiles
, absFiles
))
663 // Create the files install generator.
664 if (!resourceArgs
.GetDestination().empty())
666 resourceGenerator
= CreateInstallFilesGenerator(absFiles
,
667 resourceArgs
, false);
672 e
<< "INSTALL TARGETS - target " << target
.GetName() << " has "
673 << "RESOURCE files but no RESOURCE DESTINATION.";
674 cmSystemTools::Message(e
.str().c_str(), "Warning");
679 this->Makefile
->AddInstallGenerator(archiveGenerator
);
680 this->Makefile
->AddInstallGenerator(libraryGenerator
);
681 this->Makefile
->AddInstallGenerator(runtimeGenerator
);
682 this->Makefile
->AddInstallGenerator(frameworkGenerator
);
683 this->Makefile
->AddInstallGenerator(bundleGenerator
);
684 this->Makefile
->AddInstallGenerator(privateHeaderGenerator
);
685 this->Makefile
->AddInstallGenerator(publicHeaderGenerator
);
686 this->Makefile
->AddInstallGenerator(resourceGenerator
);
688 // Add this install rule to an export if one was specified and
689 // this is not a namelink-only rule.
690 if(!exports
.GetString().empty() && !namelinkOnly
)
692 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
693 ->AddTargetToExports(exports
.GetCString(), &target
,
694 archiveGenerator
, runtimeGenerator
,
695 libraryGenerator
, frameworkGenerator
,
696 bundleGenerator
, publicHeaderGenerator
);
700 // Tell the global generator about any installation component names specified
701 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
702 ->AddInstallComponent(archiveArgs
.GetComponent().c_str());
703 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
704 ->AddInstallComponent(libraryArgs
.GetComponent().c_str());
705 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
706 ->AddInstallComponent(runtimeArgs
.GetComponent().c_str());
707 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
708 ->AddInstallComponent(frameworkArgs
.GetComponent().c_str());
709 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
710 ->AddInstallComponent(bundleArgs
.GetComponent().c_str());
711 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
712 ->AddInstallComponent(privateHeaderArgs
.GetComponent().c_str());
713 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
714 ->AddInstallComponent(publicHeaderArgs
.GetComponent().c_str());
715 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
716 ->AddInstallComponent(resourceArgs
.GetComponent().c_str());
721 //----------------------------------------------------------------------------
722 bool cmInstallCommand::HandleFilesMode(std::vector
<std::string
> const& args
)
724 // This is the FILES mode.
725 bool programs
= (args
[0] == "PROGRAMS");
726 cmInstallCommandArguments ica
;
727 cmCAStringVector
files(&ica
.Parser
, programs
? "PROGRAMS" : "FILES");
729 ica
.ArgumentGroup
.Follows(&files
);
730 std::vector
<std::string
> unknownArgs
;
731 ica
.Parse(&args
, &unknownArgs
);
733 if(!unknownArgs
.empty())
737 e
<< args
[0] << " given unknown argument \"" << unknownArgs
[0] << "\".";
738 this->SetError(e
.str().c_str());
742 // Check if there is something to do.
743 if(files
.GetVector().empty())
748 if(!ica
.GetRename().empty() && files
.GetVector().size() > 1)
750 // The rename option works only with one file.
752 e
<< args
[0] << " given RENAME option with more than one file.";
753 this->SetError(e
.str().c_str());
757 std::vector
<std::string
> absFiles
;
758 if (!this->MakeFilesFullPath(args
[0].c_str(), files
.GetVector(), absFiles
))
768 if(ica
.GetDestination().empty())
770 // A destination is required.
772 e
<< args
[0] << " given no DESTINATION!";
773 this->SetError(e
.str().c_str());
777 // Create the files install generator.
778 this->Makefile
->AddInstallGenerator(
779 CreateInstallFilesGenerator(absFiles
, ica
, programs
));
781 //Tell the global generator about any installation component names specified.
782 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
783 ->AddInstallComponent(ica
.GetComponent().c_str());
788 //----------------------------------------------------------------------------
790 cmInstallCommand::HandleDirectoryMode(std::vector
<std::string
> const& args
)
792 bool doing_dirs
= true;
793 bool doing_destination
= false;
794 bool doing_pattern
= false;
795 bool doing_regex
= false;
796 bool doing_permissions_file
= false;
797 bool doing_permissions_dir
= false;
798 bool doing_permissions_match
= false;
799 bool doing_configurations
= false;
800 bool doing_component
= false;
801 bool in_match_mode
= false;
802 std::vector
<std::string
> dirs
;
803 const char* destination
= 0;
804 std::string permissions_file
;
805 std::string permissions_dir
;
806 std::vector
<std::string
> configurations
;
807 std::string component
= "Unspecified";
808 std::string literal_args
;
809 for(unsigned int i
=1; i
< args
.size(); ++i
)
811 if(args
[i
] == "DESTINATION")
816 e
<< args
[0] << " does not allow \""
817 << args
[i
] << "\" after PATTERN or REGEX.";
818 this->SetError(e
.str().c_str());
822 // Switch to setting the destination property.
824 doing_destination
= true;
825 doing_pattern
= false;
827 doing_permissions_file
= false;
828 doing_permissions_dir
= false;
829 doing_configurations
= false;
830 doing_component
= false;
832 else if(args
[i
] == "PATTERN")
834 // Switch to a new pattern match rule.
836 doing_destination
= false;
837 doing_pattern
= true;
839 doing_permissions_file
= false;
840 doing_permissions_dir
= false;
841 doing_permissions_match
= false;
842 doing_configurations
= false;
843 doing_component
= false;
844 in_match_mode
= true;
846 else if(args
[i
] == "REGEX")
848 // Switch to a new regex match rule.
850 doing_destination
= false;
851 doing_pattern
= false;
853 doing_permissions_file
= false;
854 doing_permissions_dir
= false;
855 doing_permissions_match
= false;
856 doing_configurations
= false;
857 doing_component
= false;
858 in_match_mode
= true;
860 else if(args
[i
] == "EXCLUDE")
862 // Add this property to the current match rule.
863 if(!in_match_mode
|| doing_pattern
|| doing_regex
)
866 e
<< args
[0] << " does not allow \""
867 << args
[i
] << "\" before a PATTERN or REGEX is given.";
868 this->SetError(e
.str().c_str());
871 literal_args
+= " EXCLUDE";
872 doing_permissions_match
= false;
874 else if(args
[i
] == "PERMISSIONS")
879 e
<< args
[0] << " does not allow \""
880 << args
[i
] << "\" before a PATTERN or REGEX is given.";
881 this->SetError(e
.str().c_str());
885 // Switch to setting the current match permissions property.
886 literal_args
+= " PERMISSIONS";
887 doing_permissions_match
= true;
889 else if(args
[i
] == "FILE_PERMISSIONS")
894 e
<< args
[0] << " does not allow \""
895 << args
[i
] << "\" after PATTERN or REGEX.";
896 this->SetError(e
.str().c_str());
900 // Switch to setting the file permissions property.
902 doing_destination
= false;
903 doing_pattern
= false;
905 doing_permissions_file
= true;
906 doing_permissions_dir
= false;
907 doing_configurations
= false;
908 doing_component
= false;
910 else if(args
[i
] == "DIRECTORY_PERMISSIONS")
915 e
<< args
[0] << " does not allow \""
916 << args
[i
] << "\" after PATTERN or REGEX.";
917 this->SetError(e
.str().c_str());
921 // Switch to setting the directory permissions property.
923 doing_destination
= false;
924 doing_pattern
= false;
926 doing_permissions_file
= false;
927 doing_permissions_dir
= true;
928 doing_configurations
= false;
929 doing_component
= false;
931 else if(args
[i
] == "USE_SOURCE_PERMISSIONS")
936 e
<< args
[0] << " does not allow \""
937 << args
[i
] << "\" after PATTERN or REGEX.";
938 this->SetError(e
.str().c_str());
942 // Add this option literally.
944 doing_destination
= false;
945 doing_pattern
= false;
947 doing_permissions_file
= false;
948 doing_permissions_dir
= false;
949 doing_configurations
= false;
950 doing_component
= false;
951 literal_args
+= " USE_SOURCE_PERMISSIONS";
953 else if(args
[i
] == "FILES_MATCHING")
958 e
<< args
[0] << " does not allow \""
959 << args
[i
] << "\" after PATTERN or REGEX.";
960 this->SetError(e
.str().c_str());
964 // Add this option literally.
966 doing_destination
= false;
967 doing_pattern
= false;
969 doing_permissions_file
= false;
970 doing_permissions_dir
= false;
971 doing_permissions_match
= false;
972 doing_configurations
= false;
973 doing_component
= false;
974 literal_args
+= " FILES_MATCHING";
976 else if(args
[i
] == "CONFIGURATIONS")
981 e
<< args
[0] << " does not allow \""
982 << args
[i
] << "\" after PATTERN or REGEX.";
983 this->SetError(e
.str().c_str());
987 // Switch to setting the configurations property.
989 doing_destination
= false;
990 doing_pattern
= false;
992 doing_permissions_file
= false;
993 doing_permissions_dir
= false;
994 doing_configurations
= true;
995 doing_component
= false;
997 else if(args
[i
] == "COMPONENT")
1002 e
<< args
[0] << " does not allow \""
1003 << args
[i
] << "\" after PATTERN or REGEX.";
1004 this->SetError(e
.str().c_str());
1008 // Switch to setting the component property.
1010 doing_destination
= false;
1011 doing_pattern
= false;
1012 doing_regex
= false;
1013 doing_permissions_file
= false;
1014 doing_permissions_dir
= false;
1015 doing_configurations
= false;
1016 doing_component
= true;
1020 // Convert this directory to a full path.
1021 std::string dir
= args
[i
];
1022 if(!cmSystemTools::FileIsFullPath(dir
.c_str()))
1024 dir
= this->Makefile
->GetCurrentDirectory();
1029 // Make sure the name is a directory.
1030 if(cmSystemTools::FileExists(dir
.c_str()) &&
1031 !cmSystemTools::FileIsDirectory(dir
.c_str()))
1034 e
<< args
[0] << " given non-directory \""
1035 << args
[i
] << "\" to install.";
1036 this->SetError(e
.str().c_str());
1040 // Store the directory for installation.
1041 dirs
.push_back(dir
);
1043 else if(doing_configurations
)
1045 configurations
.push_back(args
[i
]);
1047 else if(doing_destination
)
1049 destination
= args
[i
].c_str();
1050 doing_destination
= false;
1052 else if(doing_pattern
)
1054 // Convert the pattern to a regular expression. Require a
1055 // leading slash and trailing end-of-string in the matched
1056 // string to make sure the pattern matches only whole file
1058 literal_args
+= " REGEX \"/";
1059 std::string regex
= cmsys::Glob::PatternToRegex(args
[i
], false);
1060 cmSystemTools::ReplaceString(regex
, "\\", "\\\\");
1061 literal_args
+= regex
;
1062 literal_args
+= "$\"";
1063 doing_pattern
= false;
1065 else if(doing_regex
)
1067 literal_args
+= " REGEX \"";
1068 // Match rules are case-insensitive on some platforms.
1069 #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
1070 std::string regex
= cmSystemTools::LowerCase(args
[i
]);
1072 std::string regex
= args
[i
];
1074 cmSystemTools::ReplaceString(regex
, "\\", "\\\\");
1075 literal_args
+= regex
;
1076 literal_args
+= "\"";
1077 doing_regex
= false;
1079 else if(doing_component
)
1081 component
= args
[i
];
1082 doing_component
= false;
1084 else if(doing_permissions_file
)
1086 // Check the requested permission.
1087 if(!cmInstallCommandArguments::CheckPermissions(args
[i
],permissions_file
))
1090 e
<< args
[0] << " given invalid file permission \""
1091 << args
[i
] << "\".";
1092 this->SetError(e
.str().c_str());
1096 else if(doing_permissions_dir
)
1098 // Check the requested permission.
1099 if(!cmInstallCommandArguments::CheckPermissions(args
[i
],permissions_dir
))
1102 e
<< args
[0] << " given invalid directory permission \""
1103 << args
[i
] << "\".";
1104 this->SetError(e
.str().c_str());
1108 else if(doing_permissions_match
)
1110 // Check the requested permission.
1111 if(!cmInstallCommandArguments::CheckPermissions(args
[i
], literal_args
))
1114 e
<< args
[0] << " given invalid permission \""
1115 << args
[i
] << "\".";
1116 this->SetError(e
.str().c_str());
1122 // Unknown argument.
1124 e
<< args
[0] << " given unknown argument \"" << args
[i
] << "\".";
1125 this->SetError(e
.str().c_str());
1130 // Support installing an empty directory.
1131 if(dirs
.empty() && destination
)
1136 // Check if there is something to do.
1143 // A destination is required.
1145 e
<< args
[0] << " given no DESTINATION!";
1146 this->SetError(e
.str().c_str());
1150 // Create the directory install generator.
1151 this->Makefile
->AddInstallGenerator(
1152 new cmInstallDirectoryGenerator(dirs
, destination
,
1153 permissions_file
.c_str(),
1154 permissions_dir
.c_str(),
1157 literal_args
.c_str()));
1159 // Tell the global generator about any installation component names
1161 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
1162 ->AddInstallComponent(component
.c_str());
1167 //----------------------------------------------------------------------------
1168 bool cmInstallCommand::HandleExportMode(std::vector
<std::string
> const& args
)
1170 // This is the EXPORT mode.
1171 cmInstallCommandArguments ica
;
1172 cmCAString
exp(&ica
.Parser
, "EXPORT");
1173 cmCAString
name_space(&ica
.Parser
, "NAMESPACE", &ica
.ArgumentGroup
);
1174 cmCAString
filename(&ica
.Parser
, "FILE", &ica
.ArgumentGroup
);
1177 ica
.ArgumentGroup
.Follows(&exp
);
1178 std::vector
<std::string
> unknownArgs
;
1179 ica
.Parse(&args
, &unknownArgs
);
1181 if (!unknownArgs
.empty())
1183 // Unknown argument.
1185 e
<< args
[0] << " given unknown argument \"" << unknownArgs
[0] << "\".";
1186 this->SetError(e
.str().c_str());
1190 if (!ica
.Finalize())
1195 // Make sure there is a destination.
1196 if(ica
.GetDestination().empty())
1198 // A destination is required.
1200 e
<< args
[0] << " given no DESTINATION!";
1201 this->SetError(e
.str().c_str());
1205 // Check the file name.
1206 std::string fname
= filename
.GetString();
1207 if(fname
.find_first_of(":/\\") != fname
.npos
)
1210 e
<< args
[0] << " given invalid export file name \"" << fname
<< "\". "
1211 << "The FILE argument may not contain a path. "
1212 << "Specify the path in the DESTINATION argument.";
1213 this->SetError(e
.str().c_str());
1217 // Check the file extension.
1218 if(!fname
.empty() &&
1219 cmSystemTools::GetFilenameLastExtension(fname
) != ".cmake")
1222 e
<< args
[0] << " given invalid export file name \"" << fname
<< "\". "
1223 << "The FILE argument must specify a name ending in \".cmake\".";
1224 this->SetError(e
.str().c_str());
1228 // Construct the file name.
1231 fname
= exp
.GetString();
1234 if(fname
.find_first_of(":/\\") != fname
.npos
)
1237 e
<< args
[0] << " given export name \"" << exp
.GetString() << "\". "
1238 << "This name cannot be safely converted to a file name. "
1239 << "Specify a different export name or use the FILE option to set "
1240 << "a file name explicitly.";
1241 this->SetError(e
.str().c_str());
1246 // Create the export install generator.
1247 cmInstallExportGenerator
* exportGenerator
=
1248 new cmInstallExportGenerator(
1249 exp
.GetCString(), ica
.GetDestination().c_str(),
1250 ica
.GetPermissions().c_str(), ica
.GetConfigurations(),
1251 ica
.GetComponent().c_str(), fname
.c_str(),
1252 name_space
.GetCString(), this->Makefile
);
1253 this->Makefile
->AddInstallGenerator(exportGenerator
);
1258 bool cmInstallCommand::MakeFilesFullPath(const char* modeName
,
1259 const std::vector
<std::string
>& relFiles
,
1260 std::vector
<std::string
>& absFiles
)
1262 for(std::vector
<std::string
>::const_iterator fileIt
= relFiles
.begin();
1263 fileIt
!= relFiles
.end();
1266 std::string file
= (*fileIt
);
1267 if(!cmSystemTools::FileIsFullPath(file
.c_str()))
1269 file
= this->Makefile
->GetCurrentDirectory();
1274 // Make sure the file is not a directory.
1275 if(cmSystemTools::FileIsDirectory(file
.c_str()))
1278 e
<< modeName
<< " given directory \"" << (*fileIt
) << "\" to install.";
1279 this->SetError(e
.str().c_str());
1282 // Store the file for installation.
1283 absFiles
.push_back(file
);