Imported Upstream version 2.8.9
[platform/upstream/cmake.git] / Source / cmInstallCommand.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "cmInstallCommand.h"
13
14 #include "cmInstallDirectoryGenerator.h"
15 #include "cmInstallFilesGenerator.h"
16 #include "cmInstallScriptGenerator.h"
17 #include "cmInstallTargetGenerator.h"
18 #include "cmInstallExportGenerator.h"
19 #include "cmInstallCommandArguments.h"
20
21 #include <cmsys/Glob.hxx>
22
23 static cmInstallTargetGenerator* CreateInstallTargetGenerator(cmTarget& target,
24      const cmInstallCommandArguments& args, bool impLib, bool forceOpt = false)
25 {
26   return new cmInstallTargetGenerator(target, args.GetDestination().c_str(),
27                         impLib, args.GetPermissions().c_str(),
28                         args.GetConfigurations(), args.GetComponent().c_str(),
29                         args.GetOptional() || forceOpt);
30 }
31
32 static cmInstallFilesGenerator* CreateInstallFilesGenerator(
33     const std::vector<std::string>& absFiles,
34     const cmInstallCommandArguments& args, bool programs)
35 {
36   return new cmInstallFilesGenerator(absFiles, args.GetDestination().c_str(),
37                         programs, args.GetPermissions().c_str(),
38                         args.GetConfigurations(), args.GetComponent().c_str(),
39                         args.GetRename().c_str(), args.GetOptional());
40 }
41
42
43 // cmInstallCommand
44 bool cmInstallCommand::InitialPass(std::vector<std::string> const& args,
45                                    cmExecutionStatus &)
46 {
47   // Allow calling with no arguments so that arguments may be built up
48   // using a variable that may be left empty.
49   if(args.empty())
50     {
51     return true;
52     }
53
54   // Enable the install target.
55   this->Makefile->GetLocalGenerator()
56     ->GetGlobalGenerator()->EnableInstallTarget();
57
58   this->DefaultComponentName = this->Makefile->GetSafeDefinition(
59                                        "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
60   if (this->DefaultComponentName.empty())
61     {
62     this->DefaultComponentName = "Unspecified";
63     }
64
65   // Switch among the command modes.
66   if(args[0] == "SCRIPT")
67     {
68     return this->HandleScriptMode(args);
69     }
70   else if(args[0] == "CODE")
71     {
72     return this->HandleScriptMode(args);
73     }
74   else if(args[0] == "TARGETS")
75     {
76     return this->HandleTargetsMode(args);
77     }
78   else if(args[0] == "FILES")
79     {
80     return this->HandleFilesMode(args);
81     }
82   else if(args[0] == "PROGRAMS")
83     {
84     return this->HandleFilesMode(args);
85     }
86   else if(args[0] == "DIRECTORY")
87     {
88     return this->HandleDirectoryMode(args);
89     }
90   else if(args[0] == "EXPORT")
91     {
92     return this->HandleExportMode(args);
93     }
94
95   // Unknown mode.
96   cmStdString e = "called with unknown mode ";
97   e += args[0];
98   this->SetError(e.c_str());
99   return false;
100 }
101
102 //----------------------------------------------------------------------------
103 bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
104 {
105   std::string component = this->DefaultComponentName;
106   int componentCount = 0;
107   bool doing_script = false;
108   bool doing_code = false;
109
110   // Scan the args once for COMPONENT. Only allow one.
111   //
112   for(size_t i=0; i < args.size(); ++i)
113     {
114     if(args[i] == "COMPONENT" && i+1 < args.size())
115         {
116         ++componentCount;
117         ++i;
118         component = args[i];
119         }
120     }
121
122   if(componentCount>1)
123     {
124     this->SetError("given more than one COMPONENT for the SCRIPT or CODE "
125       "signature of the INSTALL command. "
126       "Use multiple INSTALL commands with one COMPONENT each.");
127     return false;
128     }
129
130   // Scan the args again, this time adding install generators each time we
131   // encounter a SCRIPT or CODE arg:
132   //
133   for(size_t i=0; i < args.size(); ++i)
134     {
135     if(args[i] == "SCRIPT")
136       {
137       doing_script = true;
138       doing_code = false;
139       }
140     else if(args[i] == "CODE")
141       {
142       doing_script = false;
143       doing_code = true;
144       }
145     else if(args[i] == "COMPONENT")
146       {
147       doing_script = false;
148       doing_code = false;
149       }
150     else if(doing_script)
151       {
152       doing_script = false;
153       std::string script = args[i];
154       if(!cmSystemTools::FileIsFullPath(script.c_str()))
155         {
156         script = this->Makefile->GetCurrentDirectory();
157         script += "/";
158         script += args[i];
159         }
160       if(cmSystemTools::FileIsDirectory(script.c_str()))
161         {
162         this->SetError("given a directory as value of SCRIPT argument.");
163         return false;
164         }
165       this->Makefile->AddInstallGenerator(
166         new cmInstallScriptGenerator(script.c_str(), false,
167                                      component.c_str()));
168       }
169     else if(doing_code)
170       {
171       doing_code = false;
172       std::string code = args[i];
173       this->Makefile->AddInstallGenerator(
174         new cmInstallScriptGenerator(code.c_str(), true,
175                                      component.c_str()));
176       }
177     }
178
179   if(doing_script)
180     {
181     this->SetError("given no value for SCRIPT argument.");
182     return false;
183     }
184   if(doing_code)
185     {
186     this->SetError("given no value for CODE argument.");
187     return false;
188     }
189
190   //Tell the global generator about any installation component names specified.
191   this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
192                              ->AddInstallComponent(component.c_str());
193
194   return true;
195 }
196
197
198 /*struct InstallPart
199 {
200   InstallPart(cmCommandArgumentsHelper* helper, const char* key,
201          cmCommandArgumentGroup* group);
202   cmCAStringVector argVector;
203   cmInstallCommandArguments args;
204 };*/
205
206 //----------------------------------------------------------------------------
207 bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
208 {
209   // This is the TARGETS mode.
210   std::vector<cmTarget*> targets;
211
212   cmCommandArgumentsHelper argHelper;
213   cmCommandArgumentGroup group;
214   cmCAStringVector genericArgVector      (&argHelper,0);
215   cmCAStringVector archiveArgVector      (&argHelper,"ARCHIVE",&group);
216   cmCAStringVector libraryArgVector      (&argHelper,"LIBRARY",&group);
217   cmCAStringVector runtimeArgVector      (&argHelper,"RUNTIME",&group);
218   cmCAStringVector frameworkArgVector    (&argHelper,"FRAMEWORK",&group);
219   cmCAStringVector bundleArgVector       (&argHelper,"BUNDLE",&group);
220   cmCAStringVector privateHeaderArgVector(&argHelper,"PRIVATE_HEADER",&group);
221   cmCAStringVector publicHeaderArgVector (&argHelper,"PUBLIC_HEADER",&group);
222   cmCAStringVector resourceArgVector     (&argHelper,"RESOURCE",&group);
223   genericArgVector.Follows(0);
224   group.Follows(&genericArgVector);
225
226   argHelper.Parse(&args, 0);
227
228   // now parse the generic args (i.e. the ones not specialized on LIBRARY/
229   // ARCHIVE, RUNTIME etc. (see above)
230   // These generic args also contain the targets and the export stuff
231   std::vector<std::string> unknownArgs;
232   cmInstallCommandArguments genericArgs(this->DefaultComponentName);
233   cmCAStringVector targetList(&genericArgs.Parser, "TARGETS");
234   cmCAString exports(&genericArgs.Parser,"EXPORT", &genericArgs.ArgumentGroup);
235   targetList.Follows(0);
236   genericArgs.ArgumentGroup.Follows(&targetList);
237   genericArgs.Parse(&genericArgVector.GetVector(), &unknownArgs);
238   bool success = genericArgs.Finalize();
239
240   cmInstallCommandArguments archiveArgs(this->DefaultComponentName);
241   cmInstallCommandArguments libraryArgs(this->DefaultComponentName);
242   cmInstallCommandArguments runtimeArgs(this->DefaultComponentName);
243   cmInstallCommandArguments frameworkArgs(this->DefaultComponentName);
244   cmInstallCommandArguments bundleArgs(this->DefaultComponentName);
245   cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName);
246   cmInstallCommandArguments publicHeaderArgs(this->DefaultComponentName);
247   cmInstallCommandArguments resourceArgs(this->DefaultComponentName);
248
249   // now parse the args for specific parts of the target (e.g. LIBRARY,
250   // RUNTIME, ARCHIVE etc.
251   archiveArgs.Parse      (&archiveArgVector.GetVector(),       &unknownArgs);
252   libraryArgs.Parse      (&libraryArgVector.GetVector(),       &unknownArgs);
253   runtimeArgs.Parse      (&runtimeArgVector.GetVector(),       &unknownArgs);
254   frameworkArgs.Parse    (&frameworkArgVector.GetVector(),     &unknownArgs);
255   bundleArgs.Parse       (&bundleArgVector.GetVector(),        &unknownArgs);
256   privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
257   publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(),  &unknownArgs);
258   resourceArgs.Parse     (&resourceArgVector.GetVector(),      &unknownArgs);
259
260   if(!unknownArgs.empty())
261     {
262     // Unknown argument.
263     cmOStringStream e;
264     e << "TARGETS given unknown argument \"" << unknownArgs[0] << "\".";
265     this->SetError(e.str().c_str());
266     return false;
267     }
268
269   // apply generic args
270   archiveArgs.SetGenericArguments(&genericArgs);
271   libraryArgs.SetGenericArguments(&genericArgs);
272   runtimeArgs.SetGenericArguments(&genericArgs);
273   frameworkArgs.SetGenericArguments(&genericArgs);
274   bundleArgs.SetGenericArguments(&genericArgs);
275   privateHeaderArgs.SetGenericArguments(&genericArgs);
276   publicHeaderArgs.SetGenericArguments(&genericArgs);
277   resourceArgs.SetGenericArguments(&genericArgs);
278
279   success = success && archiveArgs.Finalize();
280   success = success && libraryArgs.Finalize();
281   success = success && runtimeArgs.Finalize();
282   success = success && frameworkArgs.Finalize();
283   success = success && bundleArgs.Finalize();
284   success = success && privateHeaderArgs.Finalize();
285   success = success && publicHeaderArgs.Finalize();
286   success = success && resourceArgs.Finalize();
287
288   if(!success)
289     {
290     return false;
291     }
292
293   // Enforce argument rules too complex to specify for the
294   // general-purpose parser.
295   if(archiveArgs.GetNamelinkOnly() ||
296      runtimeArgs.GetNamelinkOnly() ||
297      frameworkArgs.GetNamelinkOnly() ||
298      bundleArgs.GetNamelinkOnly() ||
299      privateHeaderArgs.GetNamelinkOnly() ||
300      publicHeaderArgs.GetNamelinkOnly() ||
301      resourceArgs.GetNamelinkOnly())
302     {
303     this->SetError(
304       "TARGETS given NAMELINK_ONLY option not in LIBRARY group.  "
305       "The NAMELINK_ONLY option may be specified only following LIBRARY."
306       );
307     return false;
308     }
309   if(archiveArgs.GetNamelinkSkip() ||
310      runtimeArgs.GetNamelinkSkip() ||
311      frameworkArgs.GetNamelinkSkip() ||
312      bundleArgs.GetNamelinkSkip() ||
313      privateHeaderArgs.GetNamelinkSkip() ||
314      publicHeaderArgs.GetNamelinkSkip() ||
315      resourceArgs.GetNamelinkSkip())
316     {
317     this->SetError(
318       "TARGETS given NAMELINK_SKIP option not in LIBRARY group.  "
319       "The NAMELINK_SKIP option may be specified only following LIBRARY."
320       );
321     return false;
322     }
323   if(libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip())
324     {
325     this->SetError(
326       "TARGETS given NAMELINK_ONLY and NAMELINK_SKIP.  "
327       "At most one of these two options may be specified."
328       );
329     return false;
330     }
331
332   // Select the mode for installing symlinks to versioned shared libraries.
333   cmInstallTargetGenerator::NamelinkModeType
334     namelinkMode = cmInstallTargetGenerator::NamelinkModeNone;
335   if(libraryArgs.GetNamelinkOnly())
336     {
337     namelinkMode = cmInstallTargetGenerator::NamelinkModeOnly;
338     }
339   else if(libraryArgs.GetNamelinkSkip())
340     {
341     namelinkMode = cmInstallTargetGenerator::NamelinkModeSkip;
342     }
343
344   // Check if there is something to do.
345   if(targetList.GetVector().empty())
346     {
347     return true;
348     }
349
350   // Check whether this is a DLL platform.
351   bool dll_platform = (this->Makefile->IsOn("WIN32") ||
352                        this->Makefile->IsOn("CYGWIN") ||
353                        this->Makefile->IsOn("MINGW"));
354
355   for(std::vector<std::string>::const_iterator
356       targetIt=targetList.GetVector().begin();
357       targetIt!=targetList.GetVector().end();
358       ++targetIt)
359     {
360     // Lookup this target in the current directory.
361     if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str()))
362       {
363       // Found the target.  Check its type.
364       if(target->GetType() != cmTarget::EXECUTABLE &&
365          target->GetType() != cmTarget::STATIC_LIBRARY &&
366          target->GetType() != cmTarget::SHARED_LIBRARY &&
367          target->GetType() != cmTarget::MODULE_LIBRARY &&
368          target->GetType() != cmTarget::OBJECT_LIBRARY)
369         {
370         cmOStringStream e;
371         e << "TARGETS given target \"" << (*targetIt)
372           << "\" which is not an executable, library, or module.";
373         this->SetError(e.str().c_str());
374         return false;
375         }
376       else if(target->GetType() == cmTarget::OBJECT_LIBRARY)
377         {
378         cmOStringStream e;
379         e << "TARGETS given OBJECT library \"" << (*targetIt)
380           << "\" which may not be installed.";
381         this->SetError(e.str().c_str());
382         return false;
383         }
384       // Store the target in the list to be installed.
385       targets.push_back(target);
386       }
387     else
388       {
389       // Did not find the target.
390       cmOStringStream e;
391       e << "TARGETS given target \"" << (*targetIt)
392         << "\" which does not exist in this directory.";
393       this->SetError(e.str().c_str());
394       return false;
395       }
396     }
397
398   // Keep track of whether we will be performing an installation of
399   // any files of the given type.
400   bool installsArchive = false;
401   bool installsLibrary = false;
402   bool installsRuntime = false;
403   bool installsFramework = false;
404   bool installsBundle = false;
405   bool installsPrivateHeader = false;
406   bool installsPublicHeader = false;
407   bool installsResource = false;
408
409   // Generate install script code to install the given targets.
410   for(std::vector<cmTarget*>::iterator ti = targets.begin();
411       ti != targets.end(); ++ti)
412     {
413     // Handle each target type.
414     cmTarget& target = *(*ti);
415     cmInstallTargetGenerator* archiveGenerator = 0;
416     cmInstallTargetGenerator* libraryGenerator = 0;
417     cmInstallTargetGenerator* runtimeGenerator = 0;
418     cmInstallTargetGenerator* frameworkGenerator = 0;
419     cmInstallTargetGenerator* bundleGenerator = 0;
420     cmInstallFilesGenerator* privateHeaderGenerator = 0;
421     cmInstallFilesGenerator* publicHeaderGenerator = 0;
422     cmInstallFilesGenerator* resourceGenerator = 0;
423
424     // Track whether this is a namelink-only rule.
425     bool namelinkOnly = false;
426
427     switch(target.GetType())
428       {
429       case cmTarget::SHARED_LIBRARY:
430         {
431         // Shared libraries are handled differently on DLL and non-DLL
432         // platforms.  All windows platforms are DLL platforms including
433         // cygwin.  Currently no other platform is a DLL platform.
434         if(dll_platform)
435           {
436           // When in namelink only mode skip all libraries on Windows.
437           if(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly)
438             {
439             continue;
440             }
441
442           // This is a DLL platform.
443           if(!archiveArgs.GetDestination().empty())
444             {
445             // The import library uses the ARCHIVE properties.
446             archiveGenerator = CreateInstallTargetGenerator(target,
447                                                             archiveArgs, true);
448             }
449           if(!runtimeArgs.GetDestination().empty())
450             {
451             // The DLL uses the RUNTIME properties.
452             runtimeGenerator = CreateInstallTargetGenerator(target,
453                                                            runtimeArgs, false);
454             }
455           if ((archiveGenerator==0) && (runtimeGenerator==0))
456             {
457             this->SetError("Library TARGETS given no DESTINATION!");
458             return false;
459             }
460           }
461         else
462           {
463           // This is a non-DLL platform.
464           // If it is marked with FRAMEWORK property use the FRAMEWORK set of
465           // INSTALL properties. Otherwise, use the LIBRARY properties.
466           if(target.IsFrameworkOnApple())
467             {
468             // When in namelink only mode skip frameworks.
469             if(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly)
470               {
471               continue;
472               }
473
474             // Use the FRAMEWORK properties.
475             if (!frameworkArgs.GetDestination().empty())
476               {
477               frameworkGenerator = CreateInstallTargetGenerator(target,
478                                                          frameworkArgs, false);
479               }
480             else
481               {
482               cmOStringStream e;
483               e << "TARGETS given no FRAMEWORK DESTINATION for shared library "
484                 "FRAMEWORK target \"" << target.GetName() << "\".";
485               this->SetError(e.str().c_str());
486               return false;
487               }
488             }
489           else
490             {
491             // The shared library uses the LIBRARY properties.
492             if (!libraryArgs.GetDestination().empty())
493               {
494               libraryGenerator = CreateInstallTargetGenerator(target,
495                                                            libraryArgs, false);
496               libraryGenerator->SetNamelinkMode(namelinkMode);
497               namelinkOnly =
498                 (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
499               }
500             else
501               {
502               cmOStringStream e;
503               e << "TARGETS given no LIBRARY DESTINATION for shared library "
504                 "target \"" << target.GetName() << "\".";
505               this->SetError(e.str().c_str());
506               return false;
507               }
508             }
509           }
510         }
511         break;
512       case cmTarget::STATIC_LIBRARY:
513         {
514         // Static libraries use ARCHIVE properties.
515         if (!archiveArgs.GetDestination().empty())
516           {
517           archiveGenerator = CreateInstallTargetGenerator(target, archiveArgs,
518                                                           false);
519           }
520         else
521           {
522           cmOStringStream e;
523           e << "TARGETS given no ARCHIVE DESTINATION for static library "
524             "target \"" << target.GetName() << "\".";
525           this->SetError(e.str().c_str());
526           return false;
527           }
528         }
529         break;
530       case cmTarget::MODULE_LIBRARY:
531         {
532         // Modules use LIBRARY properties.
533         if (!libraryArgs.GetDestination().empty())
534           {
535           libraryGenerator = CreateInstallTargetGenerator(target, libraryArgs,
536                                                           false);
537           libraryGenerator->SetNamelinkMode(namelinkMode);
538           namelinkOnly =
539             (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
540           }
541         else
542           {
543           cmOStringStream e;
544           e << "TARGETS given no LIBRARY DESTINATION for module target \""
545             << target.GetName() << "\".";
546           this->SetError(e.str().c_str());
547           return false;
548           }
549         }
550         break;
551       case cmTarget::EXECUTABLE:
552         {
553         if(target.IsAppBundleOnApple())
554           {
555           // Application bundles use the BUNDLE properties.
556           if (!bundleArgs.GetDestination().empty())
557             {
558             bundleGenerator = CreateInstallTargetGenerator(target, bundleArgs,
559                                                            false);
560             }
561           else if(!runtimeArgs.GetDestination().empty())
562             {
563             bool failure = false;
564             if(this->CheckCMP0006(failure))
565               {
566               // For CMake 2.4 compatibility fallback to the RUNTIME
567               // properties.
568               bundleGenerator =
569                 CreateInstallTargetGenerator(target, runtimeArgs, false);
570               }
571             else if(failure)
572               {
573               return false;
574               }
575             }
576           if(!bundleGenerator)
577             {
578             cmOStringStream e;
579             e << "TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE "
580                  "executable target \"" << target.GetName() << "\".";
581             this->SetError(e.str().c_str());
582             return false;
583             }
584           }
585         else
586           {
587           // Executables use the RUNTIME properties.
588           if (!runtimeArgs.GetDestination().empty())
589             {
590             runtimeGenerator = CreateInstallTargetGenerator(target,
591                                                            runtimeArgs, false);
592             }
593           else
594             {
595             cmOStringStream e;
596             e << "TARGETS given no RUNTIME DESTINATION for executable "
597                  "target \"" << target.GetName() << "\".";
598             this->SetError(e.str().c_str());
599             return false;
600             }
601           }
602
603         // On DLL platforms an executable may also have an import
604         // library.  Install it to the archive destination if it
605         // exists.
606         if(dll_platform && !archiveArgs.GetDestination().empty() &&
607            target.IsExecutableWithExports())
608           {
609           // The import library uses the ARCHIVE properties.
610           archiveGenerator = CreateInstallTargetGenerator(target,
611                                                       archiveArgs, true, true);
612           }
613         }
614         break;
615       default:
616         // This should never happen due to the above type check.
617         // Ignore the case.
618         break;
619       }
620
621     // These well-known sets of files are installed *automatically* for
622     // FRAMEWORK SHARED library targets on the Mac as part of installing the
623     // FRAMEWORK.  For other target types or on other platforms, they are not
624     // installed automatically and so we need to create install files
625     // generators for them.
626     bool createInstallGeneratorsForTargetFileSets = true;
627
628     if(target.IsFrameworkOnApple())
629       {
630       createInstallGeneratorsForTargetFileSets = false;
631       }
632
633     if(createInstallGeneratorsForTargetFileSets && !namelinkOnly)
634       {
635       const char* files = target.GetProperty("PRIVATE_HEADER");
636       if ((files) && (*files))
637         {
638         std::vector<std::string> relFiles;
639         cmSystemTools::ExpandListArgument(files, relFiles);
640         std::vector<std::string> absFiles;
641         if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles))
642           {
643           return false;
644           }
645
646         // Create the files install generator.
647         if (!privateHeaderArgs.GetDestination().empty())
648           {
649           privateHeaderGenerator =
650             CreateInstallFilesGenerator(absFiles, privateHeaderArgs, false);
651           }
652         else
653           {
654           cmOStringStream e;
655           e << "INSTALL TARGETS - target " << target.GetName() << " has "
656             << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
657           cmSystemTools::Message(e.str().c_str(), "Warning");
658           }
659         }
660
661       files = target.GetProperty("PUBLIC_HEADER");
662       if ((files) && (*files))
663         {
664         std::vector<std::string> relFiles;
665         cmSystemTools::ExpandListArgument(files, relFiles);
666         std::vector<std::string> absFiles;
667         if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles))
668           {
669           return false;
670           }
671
672         // Create the files install generator.
673         if (!publicHeaderArgs.GetDestination().empty())
674           {
675           publicHeaderGenerator =
676             CreateInstallFilesGenerator(absFiles, publicHeaderArgs, false);
677           }
678         else
679           {
680           cmOStringStream e;
681           e << "INSTALL TARGETS - target " << target.GetName() << " has "
682             << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
683           cmSystemTools::Message(e.str().c_str(), "Warning");
684           }
685         }
686
687       files = target.GetProperty("RESOURCE");
688       if ((files) && (*files))
689         {
690         std::vector<std::string> relFiles;
691         cmSystemTools::ExpandListArgument(files, relFiles);
692         std::vector<std::string> absFiles;
693         if (!this->MakeFilesFullPath("RESOURCE", relFiles, absFiles))
694           {
695           return false;
696           }
697
698         // Create the files install generator.
699         if (!resourceArgs.GetDestination().empty())
700           {
701           resourceGenerator = CreateInstallFilesGenerator(absFiles,
702                                                           resourceArgs, false);
703           }
704         else
705           {
706           cmOStringStream e;
707           e << "INSTALL TARGETS - target " << target.GetName() << " has "
708             << "RESOURCE files but no RESOURCE DESTINATION.";
709           cmSystemTools::Message(e.str().c_str(), "Warning");
710           }
711         }
712       }
713
714     // Keep track of whether we're installing anything in each category
715     installsArchive = installsArchive || archiveGenerator != 0;
716     installsLibrary = installsLibrary || libraryGenerator != 0;
717     installsRuntime = installsRuntime || runtimeGenerator != 0;
718     installsFramework = installsFramework || frameworkGenerator != 0;
719     installsBundle = installsBundle || bundleGenerator != 0;
720     installsPrivateHeader = installsPrivateHeader
721       || privateHeaderGenerator != 0;
722     installsPublicHeader = installsPublicHeader || publicHeaderGenerator != 0;
723     installsResource = installsResource || resourceGenerator;
724
725     this->Makefile->AddInstallGenerator(archiveGenerator);
726     this->Makefile->AddInstallGenerator(libraryGenerator);
727     this->Makefile->AddInstallGenerator(runtimeGenerator);
728     this->Makefile->AddInstallGenerator(frameworkGenerator);
729     this->Makefile->AddInstallGenerator(bundleGenerator);
730     this->Makefile->AddInstallGenerator(privateHeaderGenerator);
731     this->Makefile->AddInstallGenerator(publicHeaderGenerator);
732     this->Makefile->AddInstallGenerator(resourceGenerator);
733
734     // Add this install rule to an export if one was specified and
735     // this is not a namelink-only rule.
736     if(!exports.GetString().empty() && !namelinkOnly)
737       {
738       this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
739         ->AddTargetToExports(exports.GetCString(), &target,
740                              archiveGenerator, runtimeGenerator,
741                              libraryGenerator, frameworkGenerator,
742                              bundleGenerator, publicHeaderGenerator);
743       }
744     }
745
746   // Tell the global generator about any installation component names
747   // specified
748   if (installsArchive)
749     {
750     this->Makefile->GetLocalGenerator()->
751       GetGlobalGenerator()
752       ->AddInstallComponent(archiveArgs.GetComponent().c_str());
753     }
754   if (installsLibrary)
755     {
756     this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
757       ->AddInstallComponent(libraryArgs.GetComponent().c_str());
758     }
759   if (installsRuntime)
760     {
761     this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
762       ->AddInstallComponent(runtimeArgs.GetComponent().c_str());
763     }
764   if (installsFramework)
765     {
766     this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
767       ->AddInstallComponent(frameworkArgs.GetComponent().c_str());
768     }
769   if (installsBundle)
770     {
771     this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
772       ->AddInstallComponent(bundleArgs.GetComponent().c_str());
773     }
774   if (installsPrivateHeader)
775     {
776     this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
777       ->AddInstallComponent(privateHeaderArgs.GetComponent().c_str());
778     }
779   if (installsPublicHeader)
780     {
781     this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
782       ->AddInstallComponent(publicHeaderArgs.GetComponent().c_str());
783     }
784   if (installsResource)
785     {
786     this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
787       ->AddInstallComponent(resourceArgs.GetComponent().c_str());
788     }
789
790   return true;
791 }
792
793 //----------------------------------------------------------------------------
794 bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
795 {
796   // This is the FILES mode.
797   bool programs = (args[0] == "PROGRAMS");
798   cmInstallCommandArguments ica(this->DefaultComponentName);
799   cmCAStringVector files(&ica.Parser, programs ? "PROGRAMS" : "FILES");
800   files.Follows(0);
801   ica.ArgumentGroup.Follows(&files);
802   std::vector<std::string> unknownArgs;
803   ica.Parse(&args, &unknownArgs);
804
805   if(!unknownArgs.empty())
806     {
807     // Unknown argument.
808     cmOStringStream e;
809     e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
810     this->SetError(e.str().c_str());
811     return false;
812     }
813
814   // Check if there is something to do.
815   if(files.GetVector().empty())
816     {
817     return true;
818     }
819
820   if(!ica.GetRename().empty() && files.GetVector().size() > 1)
821     {
822     // The rename option works only with one file.
823     cmOStringStream e;
824     e << args[0] << " given RENAME option with more than one file.";
825     this->SetError(e.str().c_str());
826     return false;
827     }
828
829   std::vector<std::string> absFiles;
830   if (!this->MakeFilesFullPath(args[0].c_str(), files.GetVector(), absFiles))
831     {
832     return false;
833     }
834
835   if (!ica.Finalize())
836     {
837     return false;
838     }
839
840   if(ica.GetDestination().empty())
841     {
842     // A destination is required.
843     cmOStringStream e;
844     e << args[0] << " given no DESTINATION!";
845     this->SetError(e.str().c_str());
846     return false;
847     }
848
849   // Create the files install generator.
850   this->Makefile->AddInstallGenerator(
851                          CreateInstallFilesGenerator(absFiles, ica, programs));
852
853   //Tell the global generator about any installation component names specified.
854   this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
855                              ->AddInstallComponent(ica.GetComponent().c_str());
856
857   return true;
858 }
859
860 //----------------------------------------------------------------------------
861 bool
862 cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
863 {
864   enum Doing { DoingNone, DoingDirs, DoingDestination, DoingPattern,
865                DoingRegex, DoingPermsFile, DoingPermsDir, DoingPermsMatch,
866                DoingConfigurations, DoingComponent };
867   Doing doing = DoingDirs;
868   bool in_match_mode = false;
869   bool optional = false;
870   std::vector<std::string> dirs;
871   const char* destination = 0;
872   std::string permissions_file;
873   std::string permissions_dir;
874   std::vector<std::string> configurations;
875   std::string component = this->DefaultComponentName;
876   std::string literal_args;
877   for(unsigned int i=1; i < args.size(); ++i)
878     {
879     if(args[i] == "DESTINATION")
880       {
881       if(in_match_mode)
882         {
883         cmOStringStream e;
884         e << args[0] << " does not allow \""
885           << args[i] << "\" after PATTERN or REGEX.";
886         this->SetError(e.str().c_str());
887         return false;
888         }
889
890       // Switch to setting the destination property.
891       doing = DoingDestination;
892       }
893     else if(args[i] == "OPTIONAL")
894       {
895       if(in_match_mode)
896         {
897         cmOStringStream e;
898         e << args[0] << " does not allow \""
899           << args[i] << "\" after PATTERN or REGEX.";
900         this->SetError(e.str().c_str());
901         return false;
902         }
903
904       // Mark the rule as optional.
905       optional = true;
906       doing = DoingNone;
907       }
908     else if(args[i] == "PATTERN")
909       {
910       // Switch to a new pattern match rule.
911       doing = DoingPattern;
912       in_match_mode = true;
913       }
914     else if(args[i] == "REGEX")
915       {
916       // Switch to a new regex match rule.
917       doing = DoingRegex;
918       in_match_mode = true;
919       }
920     else if(args[i] == "EXCLUDE")
921       {
922       // Add this property to the current match rule.
923       if(!in_match_mode || doing == DoingPattern || doing == DoingRegex)
924         {
925         cmOStringStream e;
926         e << args[0] << " does not allow \""
927           << args[i] << "\" before a PATTERN or REGEX is given.";
928         this->SetError(e.str().c_str());
929         return false;
930         }
931       literal_args += " EXCLUDE";
932       doing = DoingNone;
933       }
934     else if(args[i] == "PERMISSIONS")
935       {
936       if(!in_match_mode)
937         {
938         cmOStringStream e;
939         e << args[0] << " does not allow \""
940           << args[i] << "\" before a PATTERN or REGEX is given.";
941         this->SetError(e.str().c_str());
942         return false;
943         }
944
945       // Switch to setting the current match permissions property.
946       literal_args += " PERMISSIONS";
947       doing = DoingPermsMatch;
948       }
949     else if(args[i] == "FILE_PERMISSIONS")
950       {
951       if(in_match_mode)
952         {
953         cmOStringStream e;
954         e << args[0] << " does not allow \""
955           << args[i] << "\" after PATTERN or REGEX.";
956         this->SetError(e.str().c_str());
957         return false;
958         }
959
960       // Switch to setting the file permissions property.
961       doing = DoingPermsFile;
962       }
963     else if(args[i] == "DIRECTORY_PERMISSIONS")
964       {
965       if(in_match_mode)
966         {
967         cmOStringStream e;
968         e << args[0] << " does not allow \""
969           << args[i] << "\" after PATTERN or REGEX.";
970         this->SetError(e.str().c_str());
971         return false;
972         }
973
974       // Switch to setting the directory permissions property.
975       doing = DoingPermsDir;
976       }
977     else if(args[i] == "USE_SOURCE_PERMISSIONS")
978       {
979       if(in_match_mode)
980         {
981         cmOStringStream e;
982         e << args[0] << " does not allow \""
983           << args[i] << "\" after PATTERN or REGEX.";
984         this->SetError(e.str().c_str());
985         return false;
986         }
987
988       // Add this option literally.
989       literal_args += " USE_SOURCE_PERMISSIONS";
990       doing = DoingNone;
991       }
992     else if(args[i] == "FILES_MATCHING")
993       {
994       if(in_match_mode)
995         {
996         cmOStringStream e;
997         e << args[0] << " does not allow \""
998           << args[i] << "\" after PATTERN or REGEX.";
999         this->SetError(e.str().c_str());
1000         return false;
1001         }
1002
1003       // Add this option literally.
1004       literal_args += " FILES_MATCHING";
1005       doing = DoingNone;
1006       }
1007     else if(args[i] == "CONFIGURATIONS")
1008       {
1009       if(in_match_mode)
1010         {
1011         cmOStringStream e;
1012         e << args[0] << " does not allow \""
1013           << args[i] << "\" after PATTERN or REGEX.";
1014         this->SetError(e.str().c_str());
1015         return false;
1016         }
1017
1018       // Switch to setting the configurations property.
1019       doing = DoingConfigurations;
1020       }
1021     else if(args[i] == "COMPONENT")
1022       {
1023       if(in_match_mode)
1024         {
1025         cmOStringStream e;
1026         e << args[0] << " does not allow \""
1027           << args[i] << "\" after PATTERN or REGEX.";
1028         this->SetError(e.str().c_str());
1029         return false;
1030         }
1031
1032       // Switch to setting the component property.
1033       doing = DoingComponent;
1034       }
1035     else if(doing == DoingDirs)
1036       {
1037       // Convert this directory to a full path.
1038       std::string dir = args[i];
1039       if(!cmSystemTools::FileIsFullPath(dir.c_str()))
1040         {
1041         dir = this->Makefile->GetCurrentDirectory();
1042         dir += "/";
1043         dir += args[i];
1044         }
1045
1046       // Make sure the name is a directory.
1047       if(cmSystemTools::FileExists(dir.c_str()) &&
1048          !cmSystemTools::FileIsDirectory(dir.c_str()))
1049         {
1050         cmOStringStream e;
1051         e << args[0] << " given non-directory \""
1052           << args[i] << "\" to install.";
1053         this->SetError(e.str().c_str());
1054         return false;
1055         }
1056
1057       // Store the directory for installation.
1058       dirs.push_back(dir);
1059       }
1060     else if(doing == DoingConfigurations)
1061       {
1062       configurations.push_back(args[i]);
1063       }
1064     else if(doing == DoingDestination)
1065       {
1066       destination = args[i].c_str();
1067       doing = DoingNone;
1068       }
1069     else if(doing == DoingPattern)
1070       {
1071       // Convert the pattern to a regular expression.  Require a
1072       // leading slash and trailing end-of-string in the matched
1073       // string to make sure the pattern matches only whole file
1074       // names.
1075       literal_args += " REGEX \"/";
1076       std::string regex = cmsys::Glob::PatternToRegex(args[i], false);
1077       cmSystemTools::ReplaceString(regex, "\\", "\\\\");
1078       literal_args += regex;
1079       literal_args += "$\"";
1080       doing = DoingNone;
1081       }
1082     else if(doing == DoingRegex)
1083       {
1084       literal_args += " REGEX \"";
1085     // Match rules are case-insensitive on some platforms.
1086 #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
1087       std::string regex = cmSystemTools::LowerCase(args[i]);
1088 #else
1089       std::string regex = args[i];
1090 #endif
1091       cmSystemTools::ReplaceString(regex, "\\", "\\\\");
1092       literal_args += regex;
1093       literal_args += "\"";
1094       doing = DoingNone;
1095       }
1096     else if(doing == DoingComponent)
1097       {
1098       component = args[i];
1099       doing = DoingNone;
1100       }
1101     else if(doing == DoingPermsFile)
1102      {
1103      // Check the requested permission.
1104      if(!cmInstallCommandArguments::CheckPermissions(args[i],permissions_file))
1105         {
1106         cmOStringStream e;
1107         e << args[0] << " given invalid file permission \""
1108           << args[i] << "\".";
1109         this->SetError(e.str().c_str());
1110         return false;
1111         }
1112       }
1113     else if(doing == DoingPermsDir)
1114       {
1115       // Check the requested permission.
1116       if(!cmInstallCommandArguments::CheckPermissions(args[i],permissions_dir))
1117         {
1118         cmOStringStream e;
1119         e << args[0] << " given invalid directory permission \""
1120           << args[i] << "\".";
1121         this->SetError(e.str().c_str());
1122         return false;
1123         }
1124       }
1125     else if(doing == DoingPermsMatch)
1126       {
1127       // Check the requested permission.
1128       if(!cmInstallCommandArguments::CheckPermissions(args[i], literal_args))
1129         {
1130         cmOStringStream e;
1131         e << args[0] << " given invalid permission \""
1132           << args[i] << "\".";
1133         this->SetError(e.str().c_str());
1134         return false;
1135         }
1136       }
1137     else
1138       {
1139       // Unknown argument.
1140       cmOStringStream e;
1141       e << args[0] << " given unknown argument \"" << args[i] << "\".";
1142       this->SetError(e.str().c_str());
1143       return false;
1144       }
1145     }
1146
1147   // Support installing an empty directory.
1148   if(dirs.empty() && destination)
1149     {
1150     dirs.push_back("");
1151     }
1152
1153   // Check if there is something to do.
1154   if(dirs.empty())
1155     {
1156     return true;
1157     }
1158   if(!destination)
1159     {
1160     // A destination is required.
1161     cmOStringStream e;
1162     e << args[0] << " given no DESTINATION!";
1163     this->SetError(e.str().c_str());
1164     return false;
1165     }
1166
1167   // Create the directory install generator.
1168   this->Makefile->AddInstallGenerator(
1169     new cmInstallDirectoryGenerator(dirs, destination,
1170                                     permissions_file.c_str(),
1171                                     permissions_dir.c_str(),
1172                                     configurations,
1173                                     component.c_str(),
1174                                     literal_args.c_str(),
1175                                     optional));
1176
1177   // Tell the global generator about any installation component names
1178   // specified.
1179   this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
1180     ->AddInstallComponent(component.c_str());
1181
1182   return true;
1183 }
1184
1185 //----------------------------------------------------------------------------
1186 bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
1187 {
1188   // This is the EXPORT mode.
1189   cmInstallCommandArguments ica(this->DefaultComponentName);
1190   cmCAString exp(&ica.Parser, "EXPORT");
1191   cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
1192   cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
1193   exp.Follows(0);
1194
1195   ica.ArgumentGroup.Follows(&exp);
1196   std::vector<std::string> unknownArgs;
1197   ica.Parse(&args, &unknownArgs);
1198
1199   if (!unknownArgs.empty())
1200     {
1201     // Unknown argument.
1202     cmOStringStream e;
1203     e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
1204     this->SetError(e.str().c_str());
1205     return false;
1206     }
1207
1208   if (!ica.Finalize())
1209     {
1210     return false;
1211     }
1212
1213   // Make sure there is a destination.
1214   if(ica.GetDestination().empty())
1215     {
1216     // A destination is required.
1217     cmOStringStream e;
1218     e << args[0] << " given no DESTINATION!";
1219     this->SetError(e.str().c_str());
1220     return false;
1221     }
1222
1223   // Check the file name.
1224   std::string fname = filename.GetString();
1225   if(fname.find_first_of(":/\\") != fname.npos)
1226     {
1227     cmOStringStream e;
1228     e << args[0] << " given invalid export file name \"" << fname << "\".  "
1229       << "The FILE argument may not contain a path.  "
1230       << "Specify the path in the DESTINATION argument.";
1231     this->SetError(e.str().c_str());
1232     return false;
1233     }
1234
1235   // Check the file extension.
1236   if(!fname.empty() &&
1237      cmSystemTools::GetFilenameLastExtension(fname) != ".cmake")
1238     {
1239     cmOStringStream e;
1240     e << args[0] << " given invalid export file name \"" << fname << "\".  "
1241       << "The FILE argument must specify a name ending in \".cmake\".";
1242     this->SetError(e.str().c_str());
1243     return false;
1244     }
1245
1246   // Construct the file name.
1247   if(fname.empty())
1248     {
1249     fname = exp.GetString();
1250     fname += ".cmake";
1251
1252     if(fname.find_first_of(":/\\") != fname.npos)
1253       {
1254       cmOStringStream e;
1255       e << args[0] << " given export name \"" << exp.GetString() << "\".  "
1256         << "This name cannot be safely converted to a file name.  "
1257         << "Specify a different export name or use the FILE option to set "
1258         << "a file name explicitly.";
1259       this->SetError(e.str().c_str());
1260       return false;
1261       }
1262     }
1263
1264   // Create the export install generator.
1265   cmInstallExportGenerator* exportGenerator =
1266     new cmInstallExportGenerator(
1267       exp.GetCString(), ica.GetDestination().c_str(),
1268       ica.GetPermissions().c_str(), ica.GetConfigurations(),
1269       ica.GetComponent().c_str(), fname.c_str(),
1270       name_space.GetCString(), this->Makefile);
1271   this->Makefile->AddInstallGenerator(exportGenerator);
1272
1273   return true;
1274 }
1275
1276 bool cmInstallCommand::MakeFilesFullPath(const char* modeName,
1277                                       const std::vector<std::string>& relFiles,
1278                                       std::vector<std::string>& absFiles)
1279 {
1280   for(std::vector<std::string>::const_iterator fileIt = relFiles.begin();
1281       fileIt != relFiles.end();
1282       ++fileIt)
1283     {
1284     std::string file = (*fileIt);
1285     if(!cmSystemTools::FileIsFullPath(file.c_str()))
1286       {
1287       file = this->Makefile->GetCurrentDirectory();
1288       file += "/";
1289       file += *fileIt;
1290       }
1291
1292     // Make sure the file is not a directory.
1293     if(cmSystemTools::FileIsDirectory(file.c_str()))
1294       {
1295       cmOStringStream e;
1296       e << modeName << " given directory \"" << (*fileIt) << "\" to install.";
1297       this->SetError(e.str().c_str());
1298       return false;
1299       }
1300     // Store the file for installation.
1301     absFiles.push_back(file);
1302     }
1303   return true;
1304 }
1305
1306 //----------------------------------------------------------------------------
1307 bool cmInstallCommand::CheckCMP0006(bool& failure)
1308 {
1309   switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0006))
1310     {
1311     case cmPolicies::WARN:
1312       {
1313       this->Makefile->IssueMessage(
1314         cmake::AUTHOR_WARNING,
1315         this->Makefile->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0006)
1316         );
1317       }
1318     case cmPolicies::OLD:
1319       // OLD behavior is to allow compatibility
1320       return true;
1321     case cmPolicies::NEW:
1322       // NEW behavior is to disallow compatibility
1323       break;
1324     case cmPolicies::REQUIRED_IF_USED:
1325     case cmPolicies::REQUIRED_ALWAYS:
1326       failure = true;
1327       this->Makefile->IssueMessage(
1328         cmake::FATAL_ERROR,
1329         this->Makefile->GetPolicies()
1330         ->GetRequiredPolicyError(cmPolicies::CMP0006)
1331         );
1332       break;
1333     }
1334   return false;
1335 }