1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmInstallCommand.cxx,v $
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());
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 // 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.
425 // When in namelink only mode skip all libraries on Windows.
426 if(namelinkMode
== cmInstallTargetGenerator::NamelinkModeOnly
)
431 // This is a DLL platform.
432 if(!archiveArgs
.GetDestination().empty())
434 // The import library uses the ARCHIVE properties.
435 archiveGenerator
= CreateInstallTargetGenerator(target
,
438 if(!runtimeArgs
.GetDestination().empty())
440 // The DLL uses the RUNTIME properties.
441 runtimeGenerator
= CreateInstallTargetGenerator(target
,
444 if ((archiveGenerator
==0) && (runtimeGenerator
==0))
446 this->SetError("Library TARGETS given no DESTINATION!");
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
)
463 // Use the FRAMEWORK properties.
464 if (!frameworkArgs
.GetDestination().empty())
466 frameworkGenerator
= CreateInstallTargetGenerator(target
,
467 frameworkArgs
, false);
472 e
<< "TARGETS given no FRAMEWORK DESTINATION for shared library "
473 "FRAMEWORK target \"" << target
.GetName() << "\".";
474 this->SetError(e
.str().c_str());
480 // The shared library uses the LIBRARY properties.
481 if (!libraryArgs
.GetDestination().empty())
483 libraryGenerator
= CreateInstallTargetGenerator(target
,
485 libraryGenerator
->SetNamelinkMode(namelinkMode
);
487 (namelinkMode
== cmInstallTargetGenerator::NamelinkModeOnly
);
492 e
<< "TARGETS given no LIBRARY DESTINATION for shared library "
493 "target \"" << target
.GetName() << "\".";
494 this->SetError(e
.str().c_str());
501 case cmTarget::STATIC_LIBRARY
:
503 // Static libraries use ARCHIVE properties.
504 if (!archiveArgs
.GetDestination().empty())
506 archiveGenerator
= CreateInstallTargetGenerator(target
, archiveArgs
,
512 e
<< "TARGETS given no ARCHIVE DESTINATION for static library "
513 "target \"" << target
.GetName() << "\".";
514 this->SetError(e
.str().c_str());
519 case cmTarget::MODULE_LIBRARY
:
521 // Modules use LIBRARY properties.
522 if (!libraryArgs
.GetDestination().empty())
524 libraryGenerator
= CreateInstallTargetGenerator(target
, libraryArgs
,
526 libraryGenerator
->SetNamelinkMode(namelinkMode
);
528 (namelinkMode
== cmInstallTargetGenerator::NamelinkModeOnly
);
533 e
<< "TARGETS given no LIBRARY DESTINATION for module target \""
534 << target
.GetName() << "\".";
535 this->SetError(e
.str().c_str());
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
,
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
558 CreateInstallTargetGenerator(target
, runtimeArgs
, false);
568 e
<< "TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE "
569 "executable target \"" << target
.GetName() << "\".";
570 this->SetError(e
.str().c_str());
576 // Executables use the RUNTIME properties.
577 if (!runtimeArgs
.GetDestination().empty())
579 runtimeGenerator
= CreateInstallTargetGenerator(target
,
585 e
<< "TARGETS given no RUNTIME DESTINATION for executable "
586 "target \"" << target
.GetName() << "\".";
587 this->SetError(e
.str().c_str());
592 // On DLL platforms an executable may also have an import
593 // library. Install it to the archive destination if it
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);
605 // This should never happen due to the above type check.
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
))
635 // Create the files install generator.
636 if (!privateHeaderArgs
.GetDestination().empty())
638 privateHeaderGenerator
= CreateInstallFilesGenerator(absFiles
,
639 privateHeaderArgs
, false);
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
))
661 // Create the files install generator.
662 if (!publicHeaderArgs
.GetDestination().empty())
664 publicHeaderGenerator
= CreateInstallFilesGenerator(absFiles
,
665 publicHeaderArgs
, false);
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
))
687 // Create the files install generator.
688 if (!resourceArgs
.GetDestination().empty())
690 resourceGenerator
= CreateInstallFilesGenerator(absFiles
,
691 resourceArgs
, false);
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
739 this->Makefile
->GetLocalGenerator()->
741 ->AddInstallComponent(archiveArgs
.GetComponent().c_str());
745 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
746 ->AddInstallComponent(libraryArgs
.GetComponent().c_str());
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());
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());
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");
790 ica
.ArgumentGroup
.Follows(&files
);
791 std::vector
<std::string
> unknownArgs
;
792 ica
.Parse(&args
, &unknownArgs
);
794 if(!unknownArgs
.empty())
798 e
<< args
[0] << " given unknown argument \"" << unknownArgs
[0] << "\".";
799 this->SetError(e
.str().c_str());
803 // Check if there is something to do.
804 if(files
.GetVector().empty())
809 if(!ica
.GetRename().empty() && files
.GetVector().size() > 1)
811 // The rename option works only with one file.
813 e
<< args
[0] << " given RENAME option with more than one file.";
814 this->SetError(e
.str().c_str());
818 std::vector
<std::string
> absFiles
;
819 if (!this->MakeFilesFullPath(args
[0].c_str(), files
.GetVector(), absFiles
))
829 if(ica
.GetDestination().empty())
831 // A destination is required.
833 e
<< args
[0] << " given no DESTINATION!";
834 this->SetError(e
.str().c_str());
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());
849 //----------------------------------------------------------------------------
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")
873 e
<< args
[0] << " does not allow \""
874 << args
[i
] << "\" after PATTERN or REGEX.";
875 this->SetError(e
.str().c_str());
879 // Switch to setting the destination property.
880 doing
= DoingDestination
;
882 else if(args
[i
] == "OPTIONAL")
887 e
<< args
[0] << " does not allow \""
888 << args
[i
] << "\" after PATTERN or REGEX.";
889 this->SetError(e
.str().c_str());
893 // Mark the rule as optional.
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.
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
)
915 e
<< args
[0] << " does not allow \""
916 << args
[i
] << "\" before a PATTERN or REGEX is given.";
917 this->SetError(e
.str().c_str());
920 literal_args
+= " EXCLUDE";
923 else if(args
[i
] == "PERMISSIONS")
928 e
<< args
[0] << " does not allow \""
929 << args
[i
] << "\" before a PATTERN or REGEX is given.";
930 this->SetError(e
.str().c_str());
934 // Switch to setting the current match permissions property.
935 literal_args
+= " PERMISSIONS";
936 doing
= DoingPermsMatch
;
938 else if(args
[i
] == "FILE_PERMISSIONS")
943 e
<< args
[0] << " does not allow \""
944 << args
[i
] << "\" after PATTERN or REGEX.";
945 this->SetError(e
.str().c_str());
949 // Switch to setting the file permissions property.
950 doing
= DoingPermsFile
;
952 else if(args
[i
] == "DIRECTORY_PERMISSIONS")
957 e
<< args
[0] << " does not allow \""
958 << args
[i
] << "\" after PATTERN or REGEX.";
959 this->SetError(e
.str().c_str());
963 // Switch to setting the directory permissions property.
964 doing
= DoingPermsDir
;
966 else if(args
[i
] == "USE_SOURCE_PERMISSIONS")
971 e
<< args
[0] << " does not allow \""
972 << args
[i
] << "\" after PATTERN or REGEX.";
973 this->SetError(e
.str().c_str());
977 // Add this option literally.
978 literal_args
+= " USE_SOURCE_PERMISSIONS";
981 else if(args
[i
] == "FILES_MATCHING")
986 e
<< args
[0] << " does not allow \""
987 << args
[i
] << "\" after PATTERN or REGEX.";
988 this->SetError(e
.str().c_str());
992 // Add this option literally.
993 literal_args
+= " FILES_MATCHING";
996 else if(args
[i
] == "CONFIGURATIONS")
1001 e
<< args
[0] << " does not allow \""
1002 << args
[i
] << "\" after PATTERN or REGEX.";
1003 this->SetError(e
.str().c_str());
1007 // Switch to setting the configurations property.
1008 doing
= DoingConfigurations
;
1010 else if(args
[i
] == "COMPONENT")
1015 e
<< args
[0] << " does not allow \""
1016 << args
[i
] << "\" after PATTERN or REGEX.";
1017 this->SetError(e
.str().c_str());
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();
1035 // Make sure the name is a directory.
1036 if(cmSystemTools::FileExists(dir
.c_str()) &&
1037 !cmSystemTools::FileIsDirectory(dir
.c_str()))
1040 e
<< args
[0] << " given non-directory \""
1041 << args
[i
] << "\" to install.";
1042 this->SetError(e
.str().c_str());
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();
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
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
+= "$\"";
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
]);
1078 std::string regex
= args
[i
];
1080 cmSystemTools::ReplaceString(regex
, "\\", "\\\\");
1081 literal_args
+= regex
;
1082 literal_args
+= "\"";
1085 else if(doing
== DoingComponent
)
1087 component
= args
[i
];
1090 else if(doing
== DoingPermsFile
)
1092 // Check the requested permission.
1093 if(!cmInstallCommandArguments::CheckPermissions(args
[i
],permissions_file
))
1096 e
<< args
[0] << " given invalid file permission \""
1097 << args
[i
] << "\".";
1098 this->SetError(e
.str().c_str());
1102 else if(doing
== DoingPermsDir
)
1104 // Check the requested permission.
1105 if(!cmInstallCommandArguments::CheckPermissions(args
[i
],permissions_dir
))
1108 e
<< args
[0] << " given invalid directory permission \""
1109 << args
[i
] << "\".";
1110 this->SetError(e
.str().c_str());
1114 else if(doing
== DoingPermsMatch
)
1116 // Check the requested permission.
1117 if(!cmInstallCommandArguments::CheckPermissions(args
[i
], literal_args
))
1120 e
<< args
[0] << " given invalid permission \""
1121 << args
[i
] << "\".";
1122 this->SetError(e
.str().c_str());
1128 // Unknown argument.
1130 e
<< args
[0] << " given unknown argument \"" << args
[i
] << "\".";
1131 this->SetError(e
.str().c_str());
1136 // Support installing an empty directory.
1137 if(dirs
.empty() && destination
)
1142 // Check if there is something to do.
1149 // A destination is required.
1151 e
<< args
[0] << " given no DESTINATION!";
1152 this->SetError(e
.str().c_str());
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(),
1163 literal_args
.c_str(),
1166 // Tell the global generator about any installation component names
1168 this->Makefile
->GetLocalGenerator()->GetGlobalGenerator()
1169 ->AddInstallComponent(component
.c_str());
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
);
1184 ica
.ArgumentGroup
.Follows(&exp
);
1185 std::vector
<std::string
> unknownArgs
;
1186 ica
.Parse(&args
, &unknownArgs
);
1188 if (!unknownArgs
.empty())
1190 // Unknown argument.
1192 e
<< args
[0] << " given unknown argument \"" << unknownArgs
[0] << "\".";
1193 this->SetError(e
.str().c_str());
1197 if (!ica
.Finalize())
1202 // Make sure there is a destination.
1203 if(ica
.GetDestination().empty())
1205 // A destination is required.
1207 e
<< args
[0] << " given no DESTINATION!";
1208 this->SetError(e
.str().c_str());
1212 // Check the file name.
1213 std::string fname
= filename
.GetString();
1214 if(fname
.find_first_of(":/\\") != fname
.npos
)
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());
1224 // Check the file extension.
1225 if(!fname
.empty() &&
1226 cmSystemTools::GetFilenameLastExtension(fname
) != ".cmake")
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());
1235 // Construct the file name.
1238 fname
= exp
.GetString();
1241 if(fname
.find_first_of(":/\\") != fname
.npos
)
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());
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
);
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();
1273 std::string file
= (*fileIt
);
1274 if(!cmSystemTools::FileIsFullPath(file
.c_str()))
1276 file
= this->Makefile
->GetCurrentDirectory();
1281 // Make sure the file is not a directory.
1282 if(cmSystemTools::FileIsDirectory(file
.c_str()))
1285 e
<< modeName
<< " given directory \"" << (*fileIt
) << "\" to install.";
1286 this->SetError(e
.str().c_str());
1289 // Store the file for installation.
1290 absFiles
.push_back(file
);
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
1310 case cmPolicies::NEW
:
1311 // NEW behavior is to disallow compatibility
1313 case cmPolicies::REQUIRED_IF_USED
:
1314 case cmPolicies::REQUIRED_ALWAYS
:
1316 this->Makefile
->IssueMessage(
1318 this->Makefile
->GetPolicies()
1319 ->GetRequiredPolicyError(cmPolicies::CMP0006
)