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