packaging: Initial packaging
[platform/upstream/cmake.git] / Source / cmGlobalUnixMakefileGenerator3.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 "cmGlobalUnixMakefileGenerator3.h"
13 #include "cmLocalUnixMakefileGenerator3.h"
14 #include "cmMakefileTargetGenerator.h"
15 #include "cmMakefile.h"
16 #include "cmake.h"
17 #include "cmGeneratedFileStream.h"
18 #include "cmSourceFile.h"
19 #include "cmTarget.h"
20 #include "cmGeneratorTarget.h"
21
22 cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
23 {
24   // This type of makefile always requires unix style paths
25   this->ForceUnixPaths = true;
26   this->FindMakeProgramFile = "CMakeUnixFindMake.cmake";
27   this->ToolSupportsColor = true;
28
29 #if defined(_WIN32) || defined(__VMS)
30   this->UseLinkScript = false;
31 #else
32   this->UseLinkScript = true;
33 #endif
34   this->CommandDatabase = NULL;
35 }
36
37 void cmGlobalUnixMakefileGenerator3
38 ::EnableLanguage(std::vector<std::string>const& languages,
39                  cmMakefile *mf,
40                  bool optional)
41 {
42   this->cmGlobalGenerator::EnableLanguage(languages, mf, optional);
43   for(std::vector<std::string>::const_iterator l = languages.begin();
44       l != languages.end(); ++l)
45     {
46     if(*l == "NONE")
47       {
48       continue;
49       }
50     this->ResolveLanguageCompiler(*l, mf, optional);
51     }
52 }
53
54 ///! Create a local generator appropriate to this Global Generator
55 cmLocalGenerator *cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
56 {
57   cmLocalGenerator* lg = new cmLocalUnixMakefileGenerator3;
58   lg->SetGlobalGenerator(this);
59   return lg;
60 }
61
62 //----------------------------------------------------------------------------
63 void cmGlobalUnixMakefileGenerator3
64 ::GetDocumentation(cmDocumentationEntry& entry)
65 {
66   entry.Name = cmGlobalUnixMakefileGenerator3::GetActualName();
67   entry.Brief = "Generates standard UNIX makefiles.";
68   entry.Full =
69     "A hierarchy of UNIX makefiles is generated into the build tree.  Any "
70     "standard UNIX-style make program can build the project through the "
71     "default make target.  A \"make install\" target is also provided.";
72 }
73
74 //----------------------------------------------------------------------------
75 void
76 cmGlobalUnixMakefileGenerator3
77 ::ComputeTargetObjects(cmGeneratorTarget* gt) const
78 {
79   cmTarget* target = gt->Target;
80   cmLocalUnixMakefileGenerator3* lg =
81     static_cast<cmLocalUnixMakefileGenerator3*>(gt->LocalGenerator);
82
83   // Compute full path to object file directory for this target.
84   std::string dir_max;
85   dir_max += gt->Makefile->GetCurrentOutputDirectory();
86   dir_max += "/";
87   dir_max += gt->LocalGenerator->GetTargetDirectory(*target);
88   dir_max += "/";
89   gt->ObjectDirectory = dir_max;
90
91   // Compute the name of each object file.
92   for(std::vector<cmSourceFile*>::iterator
93         si = gt->ObjectSources.begin();
94       si != gt->ObjectSources.end(); ++si)
95     {
96     cmSourceFile* sf = *si;
97     bool hasSourceExtension = true;
98     std::string objectName = gt->LocalGenerator
99       ->GetObjectFileNameWithoutTarget(*sf, dir_max,
100                                        &hasSourceExtension);
101     gt->Objects[sf] = objectName;
102     lg->AddLocalObjectFile(target, sf, objectName, hasSourceExtension);
103     }
104 }
105
106 void cmGlobalUnixMakefileGenerator3::Generate()
107 {
108   // first do superclass method
109   this->cmGlobalGenerator::Generate();
110
111   // initialize progress
112   unsigned long total = 0;
113   for(ProgressMapType::const_iterator pmi = this->ProgressMap.begin();
114       pmi != this->ProgressMap.end(); ++pmi)
115     {
116     total += pmi->second.NumberOfActions;
117     }
118
119   // write each target's progress.make this loop is done twice. Bascially the
120   // Generate pass counts all the actions, the first loop below determines
121   // how many actions have progress updates for each target and writes to
122   // corrrect variable values for everything except the all targets. The
123   // second loop actually writes out correct values for the all targets as
124   // well. This is because the all targets require more information that is
125   // computed in the first loop.
126   unsigned long current = 0;
127   for(ProgressMapType::iterator pmi = this->ProgressMap.begin();
128       pmi != this->ProgressMap.end(); ++pmi)
129     {
130     pmi->second.WriteProgressVariables(total, current);
131     }
132   for(unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
133     {
134     cmLocalUnixMakefileGenerator3 *lg =
135       static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
136     std::string markFileName = lg->GetMakefile()->GetStartOutputDirectory();
137     markFileName += "/";
138     markFileName += cmake::GetCMakeFilesDirectory();
139     markFileName += "/progress.marks";
140     cmGeneratedFileStream markFile(markFileName.c_str());
141     markFile << this->CountProgressMarksInAll(lg) << "\n";
142     }
143
144   // write the main makefile
145   this->WriteMainMakefile2();
146   this->WriteMainCMakefile();
147
148   if (this->CommandDatabase != NULL) {
149     *this->CommandDatabase << std::endl << "]";
150     delete this->CommandDatabase;
151     this->CommandDatabase = NULL;
152   }
153 }
154
155 void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand(
156     const std::string &sourceFile, const std::string &workingDirectory,
157     const std::string &compileCommand) {
158   if (this->CommandDatabase == NULL)
159     {
160     std::string commandDatabaseName =
161       std::string(this->GetCMakeInstance()->GetHomeOutputDirectory())
162       + "/compile_commands.json";
163     this->CommandDatabase =
164       new cmGeneratedFileStream(commandDatabaseName.c_str());
165     *this->CommandDatabase << "[" << std::endl;
166     } else {
167     *this->CommandDatabase << "," << std::endl;
168     }
169   *this->CommandDatabase << "{" << std::endl
170       << "  \"directory\": \""
171       << cmGlobalGenerator::EscapeJSON(workingDirectory) << "\","
172       << std::endl
173       << "  \"command\": \"" <<
174       cmGlobalGenerator::EscapeJSON(compileCommand) << "\","
175       << std::endl
176       << "  \"file\": \"" <<
177       cmGlobalGenerator::EscapeJSON(sourceFile) << "\""
178       << std::endl << "}";
179 }
180
181 void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
182 {
183   // Open the output file.  This should not be copy-if-different
184   // because the check-build-system step compares the makefile time to
185   // see if the build system must be regenerated.
186   std::string makefileName =
187     this->GetCMakeInstance()->GetHomeOutputDirectory();
188   makefileName += cmake::GetCMakeFilesDirectory();
189   makefileName += "/Makefile2";
190   cmGeneratedFileStream makefileStream(makefileName.c_str());
191   if(!makefileStream)
192     {
193     return;
194     }
195
196   // get a local generator for some useful methods
197   cmLocalUnixMakefileGenerator3 *lg =
198     static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
199
200   // Write the do not edit header.
201   lg->WriteDisclaimer(makefileStream);
202
203   // Write the main entry point target.  This must be the VERY first
204   // target so that make with no arguments will run it.
205   // Just depend on the all target to drive the build.
206   std::vector<std::string> depends;
207   std::vector<std::string> no_commands;
208   depends.push_back("all");
209
210   // Write the rule.
211   lg->WriteMakeRule(makefileStream,
212                     "Default target executed when no arguments are "
213                     "given to make.",
214                     "default_target",
215                     depends,
216                     no_commands, true);
217
218   depends.clear();
219
220   // The all and preinstall rules might never have any dependencies
221   // added to them.
222   if(this->EmptyRuleHackDepends != "")
223     {
224     depends.push_back(this->EmptyRuleHackDepends);
225     }
226
227   // Write and empty all:
228   lg->WriteMakeRule(makefileStream,
229                     "The main recursive all target", "all",
230                     depends, no_commands, true);
231
232   // Write an empty preinstall:
233   lg->WriteMakeRule(makefileStream,
234                     "The main recursive preinstall target", "preinstall",
235                     depends, no_commands, true);
236
237   // Write out the "special" stuff
238   lg->WriteSpecialTargetsTop(makefileStream);
239
240   // write the target convenience rules
241   unsigned int i;
242   for (i = 0; i < this->LocalGenerators.size(); ++i)
243     {
244     lg =
245       static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
246     this->WriteConvenienceRules2(makefileStream,lg);
247     }
248
249   lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
250   lg->WriteSpecialTargetsBottom(makefileStream);
251 }
252
253
254 //----------------------------------------------------------------------------
255 void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
256 {
257   // Open the output file.  This should not be copy-if-different
258   // because the check-build-system step compares the makefile time to
259   // see if the build system must be regenerated.
260   std::string cmakefileName =
261     this->GetCMakeInstance()->GetHomeOutputDirectory();
262   cmakefileName += cmake::GetCMakeFilesDirectory();
263   cmakefileName += "/Makefile.cmake";
264   cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
265   if(!cmakefileStream)
266     {
267     return;
268     }
269
270   std::string makefileName =
271     this->GetCMakeInstance()->GetHomeOutputDirectory();
272   makefileName += "/Makefile";
273
274   // get a local generator for some useful methods
275   cmLocalUnixMakefileGenerator3 *lg =
276     static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
277
278   // Write the do not edit header.
279   lg->WriteDisclaimer(cmakefileStream);
280
281   // Save the generator name
282   cmakefileStream
283     << "# The generator used is:\n"
284     << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
285
286   // for each cmMakefile get its list of dependencies
287   std::vector<std::string> lfiles;
288   for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
289     {
290     lg =
291       static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
292
293     // Get the list of files contributing to this generation step.
294     lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
295                   lg->GetMakefile()->GetListFiles().end());
296     }
297   // Sort the list and remove duplicates.
298   std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
299 #if !defined(__VMS) // The Compaq STL on VMS crashes, so accept duplicates.
300   std::vector<std::string>::iterator new_end =
301     std::unique(lfiles.begin(),lfiles.end());
302   lfiles.erase(new_end, lfiles.end());
303 #endif
304
305   // reset lg to the first makefile
306   lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
307
308   // Build the path to the cache file.
309   std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
310   cache += "/CMakeCache.txt";
311
312   // Save the list to the cmake file.
313   cmakefileStream
314     << "# The top level Makefile was generated from the following files:\n"
315     << "SET(CMAKE_MAKEFILE_DEPENDS\n"
316     << "  \""
317     << lg->Convert(cache.c_str(),
318                    cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
319   for(std::vector<std::string>::const_iterator i = lfiles.begin();
320       i !=  lfiles.end(); ++i)
321     {
322     cmakefileStream
323       << "  \""
324       << lg->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT).c_str()
325       << "\"\n";
326     }
327   cmakefileStream
328     << "  )\n\n";
329
330   // Build the path to the cache check file.
331   std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
332   check += cmake::GetCMakeFilesDirectory();
333   check += "/cmake.check_cache";
334
335   // Set the corresponding makefile in the cmake file.
336   cmakefileStream
337     << "# The corresponding makefile is:\n"
338     << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
339     << "  \""
340     << lg->Convert(makefileName.c_str(),
341                    cmLocalGenerator::START_OUTPUT).c_str() << "\"\n"
342     << "  \""
343     << lg->Convert(check.c_str(),
344                    cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
345   cmakefileStream << "  )\n\n";
346
347   // CMake must rerun if a byproduct is missing.
348   {
349   cmakefileStream
350     << "# Byproducts of CMake generate step:\n"
351     << "SET(CMAKE_MAKEFILE_PRODUCTS\n";
352   const std::vector<std::string>& outfiles =
353     lg->GetMakefile()->GetOutputFiles();
354   for(std::vector<std::string>::const_iterator k = outfiles.begin();
355       k != outfiles.end(); ++k)
356     {
357     cmakefileStream << "  \"" <<
358       lg->Convert(k->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
359                     << "\"\n";
360     }
361
362   // add in all the directory information files
363   std::string tmpStr;
364   for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
365     {
366     lg =
367       static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
368     tmpStr = lg->GetMakefile()->GetStartOutputDirectory();
369     tmpStr += cmake::GetCMakeFilesDirectory();
370     tmpStr += "/CMakeDirectoryInformation.cmake";
371     cmakefileStream << "  \"" <<
372       lg->Convert(tmpStr.c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
373                     << "\"\n";
374     }
375   cmakefileStream << "  )\n\n";
376   }
377
378   this->WriteMainCMakefileLanguageRules(cmakefileStream,
379                                         this->LocalGenerators);
380 }
381
382 void cmGlobalUnixMakefileGenerator3
383 ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
384                                   std::vector<cmLocalGenerator *> &lGenerators
385                                   )
386 {
387   cmLocalUnixMakefileGenerator3 *lg;
388
389   // now list all the target info files
390   cmakefileStream
391     << "# Dependency information for all targets:\n";
392   cmakefileStream
393     << "SET(CMAKE_DEPEND_INFO_FILES\n";
394   for (unsigned int i = 0; i < lGenerators.size(); ++i)
395     {
396     lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
397     // for all of out targets
398     for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
399          l != lg->GetMakefile()->GetTargets().end(); l++)
400       {
401       if((l->second.GetType() == cmTarget::EXECUTABLE) ||
402          (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
403          (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
404          (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
405          (l->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
406          (l->second.GetType() == cmTarget::UTILITY))
407         {
408         std::string tname = lg->GetRelativeTargetDirectory(l->second);
409         tname += "/DependInfo.cmake";
410         cmSystemTools::ConvertToUnixSlashes(tname);
411         cmakefileStream << "  \"" << tname.c_str() << "\"\n";
412         }
413       }
414     }
415   cmakefileStream << "  )\n";
416 }
417
418 //----------------------------------------------------------------------------
419 void
420 cmGlobalUnixMakefileGenerator3
421 ::WriteDirectoryRule2(std::ostream& ruleFileStream,
422                       cmLocalUnixMakefileGenerator3* lg,
423                       const char* pass, bool check_all,
424                       bool check_relink)
425 {
426   // Get the relative path to the subdirectory from the top.
427   std::string makeTarget = lg->GetMakefile()->GetStartOutputDirectory();
428   makeTarget += "/";
429   makeTarget += pass;
430
431   // The directory-level rule should depend on the target-level rules
432   // for all targets in the directory.
433   std::vector<std::string> depends;
434   for(cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
435       l != lg->GetMakefile()->GetTargets().end(); ++l)
436     {
437     if((l->second.GetType() == cmTarget::EXECUTABLE) ||
438        (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
439        (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
440        (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
441        (l->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
442        (l->second.GetType() == cmTarget::UTILITY))
443       {
444       // Add this to the list of depends rules in this directory.
445       if((!check_all || !l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
446          (!check_relink ||
447           l->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str())))
448         {
449         std::string tname = lg->GetRelativeTargetDirectory(l->second);
450         tname += "/";
451         tname += pass;
452         depends.push_back(tname);
453         }
454       }
455     }
456
457   // The directory-level rule should depend on the directory-level
458   // rules of the subdirectories.
459   for(std::vector<cmLocalGenerator*>::iterator sdi =
460         lg->GetChildren().begin(); sdi != lg->GetChildren().end(); ++sdi)
461     {
462     cmLocalUnixMakefileGenerator3* slg =
463       static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
464     std::string subdir = slg->GetMakefile()->GetStartOutputDirectory();
465     subdir += "/";
466     subdir += pass;
467     depends.push_back(subdir);
468     }
469
470   // Work-around for makes that drop rules that have no dependencies
471   // or commands.
472   if(depends.empty() && this->EmptyRuleHackDepends != "")
473     {
474     depends.push_back(this->EmptyRuleHackDepends);
475     }
476
477   // Write the rule.
478   std::string doc = "Convenience name for \"";
479   doc += pass;
480   doc += "\" pass in the directory.";
481   std::vector<std::string> no_commands;
482   lg->WriteMakeRule(ruleFileStream, doc.c_str(),
483                     makeTarget.c_str(), depends, no_commands, true);
484 }
485
486 //----------------------------------------------------------------------------
487 void
488 cmGlobalUnixMakefileGenerator3
489 ::WriteDirectoryRules2(std::ostream& ruleFileStream,
490                        cmLocalUnixMakefileGenerator3* lg)
491 {
492   // Only subdirectories need these rules.
493   if(!lg->GetParent())
494     {
495     return;
496     }
497
498   // Begin the directory-level rules section.
499   std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
500   dir = lg->Convert(dir.c_str(), cmLocalGenerator::HOME_OUTPUT,
501                     cmLocalGenerator::MAKEFILE);
502   lg->WriteDivider(ruleFileStream);
503   ruleFileStream
504     << "# Directory level rules for directory "
505     << dir << "\n\n";
506
507   // Write directory-level rules for "all".
508   this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
509
510   // Write directory-level rules for "clean".
511   this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false);
512
513   // Write directory-level rules for "preinstall".
514   this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
515 }
516
517
518 std::string cmGlobalUnixMakefileGenerator3
519 ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
520                        const char *projectDir, const char* additionalOptions,
521                        const char *targetName, const char* config,
522                        bool ignoreErrors, bool fast)
523 {
524   // Project name & dir and config are not used yet.
525   (void)projectName;
526   (void)projectDir;
527   (void)config;
528
529   std::string makeCommand =
530     cmSystemTools::ConvertToUnixOutputPath(makeProgram);
531
532   // Since we have full control over the invocation of nmake, let us
533   // make it quiet.
534   if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
535     {
536     makeCommand += " /NOLOGO ";
537     }
538   if ( ignoreErrors )
539     {
540     makeCommand += " -i";
541     }
542   if ( additionalOptions )
543     {
544     makeCommand += " ";
545     makeCommand += additionalOptions;
546     }
547   if ( targetName && strlen(targetName))
548     {
549     cmLocalUnixMakefileGenerator3 *lg;
550     if (this->LocalGenerators.size())
551       {
552       lg = static_cast<cmLocalUnixMakefileGenerator3 *>
553         (this->LocalGenerators[0]);
554       }
555     else
556       {
557       lg = static_cast<cmLocalUnixMakefileGenerator3 *>
558         (this->CreateLocalGenerator());
559       // set the Start directories
560       lg->GetMakefile()->SetStartDirectory
561         (this->CMakeInstance->GetStartDirectory());
562       lg->GetMakefile()->SetStartOutputDirectory
563         (this->CMakeInstance->GetStartOutputDirectory());
564       lg->GetMakefile()->MakeStartDirectoriesCurrent();
565       }
566
567     makeCommand += " \"";
568     std::string tname = targetName;
569     if(fast)
570       {
571       tname += "/fast";
572       }
573     tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
574                         cmLocalGenerator::MAKEFILE);
575     makeCommand += tname.c_str();
576     makeCommand += "\"";
577     if (!this->LocalGenerators.size())
578       {
579       delete lg;
580       }
581     }
582   return makeCommand;
583 }
584
585 //----------------------------------------------------------------------------
586 void
587 cmGlobalUnixMakefileGenerator3
588 ::WriteConvenienceRules(std::ostream& ruleFileStream,
589                         std::set<cmStdString> &emitted)
590 {
591   std::vector<std::string> depends;
592   std::vector<std::string> commands;
593
594   depends.push_back("cmake_check_build_system");
595
596   // write the target convenience rules
597   unsigned int i;
598   cmLocalUnixMakefileGenerator3 *lg;
599   for (i = 0; i < this->LocalGenerators.size(); ++i)
600     {
601     lg = static_cast<cmLocalUnixMakefileGenerator3 *>
602       (this->LocalGenerators[i]);
603     // for each target Generate the rule files for each target.
604     cmTargets& targets = lg->GetMakefile()->GetTargets();
605     for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
606       {
607       // Don't emit the same rule twice (e.g. two targets with the same
608       // simple name)
609       if(t->second.GetName() &&
610          strlen(t->second.GetName()) &&
611          emitted.insert(t->second.GetName()).second &&
612          // Handle user targets here.  Global targets are handled in
613          // the local generator on a per-directory basis.
614          ((t->second.GetType() == cmTarget::EXECUTABLE) ||
615           (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
616           (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
617           (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
618           (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
619           (t->second.GetType() == cmTarget::UTILITY)))
620         {
621         // Add a rule to build the target by name.
622         lg->WriteDivider(ruleFileStream);
623         ruleFileStream
624           << "# Target rules for targets named "
625           << t->second.GetName() << "\n\n";
626
627         // Write the rule.
628         commands.clear();
629         std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
630         tmp += "Makefile2";
631         commands.push_back(lg->GetRecursiveMakeCall
632                             (tmp.c_str(),t->second.GetName()));
633         depends.clear();
634         depends.push_back("cmake_check_build_system");
635         lg->WriteMakeRule(ruleFileStream,
636                           "Build rule for target.",
637                           t->second.GetName(), depends, commands,
638                           true);
639
640         // Add a fast rule to build the target
641         std::string localName = lg->GetRelativeTargetDirectory(t->second);
642         std::string makefileName;
643         makefileName = localName;
644         makefileName += "/build.make";
645         depends.clear();
646         commands.clear();
647         std::string makeTargetName = localName;
648         makeTargetName += "/build";
649         localName = t->second.GetName();
650         localName += "/fast";
651         commands.push_back(lg->GetRecursiveMakeCall
652                             (makefileName.c_str(), makeTargetName.c_str()));
653         lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
654                           localName.c_str(), depends, commands, true);
655
656         // Add a local name for the rule to relink the target before
657         // installation.
658         if(t->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str()))
659           {
660           makeTargetName = lg->GetRelativeTargetDirectory(t->second);
661           makeTargetName += "/preinstall";
662           localName = t->second.GetName();
663           localName += "/preinstall";
664           depends.clear();
665           commands.clear();
666           commands.push_back(lg->GetRecursiveMakeCall
667                              (makefileName.c_str(), makeTargetName.c_str()));
668           lg->WriteMakeRule(ruleFileStream,
669                             "Manual pre-install relink rule for target.",
670                             localName.c_str(), depends, commands, true);
671           }
672         }
673       }
674     }
675 }
676
677
678 //----------------------------------------------------------------------------
679 void
680 cmGlobalUnixMakefileGenerator3
681 ::WriteConvenienceRules2(std::ostream& ruleFileStream,
682                          cmLocalUnixMakefileGenerator3 *lg)
683 {
684   std::vector<std::string> depends;
685   std::vector<std::string> commands;
686   std::string localName;
687   std::string makeTargetName;
688
689
690   // write the directory level rules for this local gen
691   this->WriteDirectoryRules2(ruleFileStream,lg);
692
693   depends.push_back("cmake_check_build_system");
694
695   // for each target Generate the rule files for each target.
696   cmTargets& targets = lg->GetMakefile()->GetTargets();
697   for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
698     {
699     if (t->second.GetName()
700      && strlen(t->second.GetName())
701      && ((t->second.GetType() == cmTarget::EXECUTABLE)
702         || (t->second.GetType() == cmTarget::STATIC_LIBRARY)
703         || (t->second.GetType() == cmTarget::SHARED_LIBRARY)
704         || (t->second.GetType() == cmTarget::MODULE_LIBRARY)
705         || (t->second.GetType() == cmTarget::OBJECT_LIBRARY)
706         || (t->second.GetType() == cmTarget::UTILITY)))
707       {
708       std::string makefileName;
709       // Add a rule to build the target by name.
710       localName = lg->GetRelativeTargetDirectory(t->second);
711       makefileName = localName;
712       makefileName += "/build.make";
713
714       bool needRequiresStep = this->NeedRequiresStep(t->second);
715
716       lg->WriteDivider(ruleFileStream);
717       ruleFileStream
718         << "# Target rules for target "
719         << localName << "\n\n";
720
721       commands.clear();
722       makeTargetName = localName;
723       makeTargetName += "/depend";
724       commands.push_back(lg->GetRecursiveMakeCall
725                          (makefileName.c_str(),makeTargetName.c_str()));
726
727       // add requires if we need it for this generator
728       if (needRequiresStep)
729         {
730         makeTargetName = localName;
731         makeTargetName += "/requires";
732         commands.push_back(lg->GetRecursiveMakeCall
733                            (makefileName.c_str(),makeTargetName.c_str()));
734         }
735       makeTargetName = localName;
736       makeTargetName += "/build";
737       commands.push_back(lg->GetRecursiveMakeCall
738                           (makefileName.c_str(),makeTargetName.c_str()));
739
740       // Write the rule.
741       localName += "/all";
742       depends.clear();
743
744       std::string progressDir =
745         lg->GetMakefile()->GetHomeOutputDirectory();
746       progressDir += cmake::GetCMakeFilesDirectory();
747         {
748         cmOStringStream progCmd;
749         progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
750         // all target counts
751         progCmd << lg->Convert(progressDir.c_str(),
752                                 cmLocalGenerator::FULL,
753                                 cmLocalGenerator::SHELL);
754         progCmd << " ";
755         std::vector<unsigned long>& progFiles =
756           this->ProgressMap[&t->second].Marks;
757         for (std::vector<unsigned long>::iterator i = progFiles.begin();
758               i != progFiles.end(); ++i)
759           {
760           progCmd << " " << *i;
761           }
762         commands.push_back(progCmd.str());
763         }
764       progressDir = "Built target ";
765       progressDir += t->first;
766       lg->AppendEcho(commands,progressDir.c_str());
767
768       this->AppendGlobalTargetDepends(depends,t->second);
769       lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
770                         localName.c_str(), depends, commands, true);
771
772       // add the all/all dependency
773       if(!this->IsExcluded(this->LocalGenerators[0], t->second))
774         {
775         depends.clear();
776         depends.push_back(localName);
777         commands.clear();
778         lg->WriteMakeRule(ruleFileStream, "Include target in all.",
779                           "all", depends, commands, true);
780         }
781
782       // Write the rule.
783       commands.clear();
784       progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
785       progressDir += cmake::GetCMakeFilesDirectory();
786
787       {
788       // TODO: Convert the total progress count to a make variable.
789       cmOStringStream progCmd;
790       progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
791       // # in target
792       progCmd << lg->Convert(progressDir.c_str(),
793                               cmLocalGenerator::FULL,
794                               cmLocalGenerator::SHELL);
795       //
796       std::set<cmTarget *> emitted;
797       progCmd << " "
798               << this->CountProgressMarksInTarget(&t->second, emitted);
799       commands.push_back(progCmd.str());
800       }
801       std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
802       tmp += "Makefile2";
803       commands.push_back(lg->GetRecursiveMakeCall
804                           (tmp.c_str(),localName.c_str()));
805       {
806       cmOStringStream progCmd;
807       progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
808       progCmd << lg->Convert(progressDir.c_str(),
809                               cmLocalGenerator::FULL,
810                               cmLocalGenerator::SHELL);
811       progCmd << " 0";
812       commands.push_back(progCmd.str());
813       }
814       depends.clear();
815       depends.push_back("cmake_check_build_system");
816       localName = lg->GetRelativeTargetDirectory(t->second);
817       localName += "/rule";
818       lg->WriteMakeRule(ruleFileStream,
819                         "Build rule for subdir invocation for target.",
820                         localName.c_str(), depends, commands, true);
821
822       // Add a target with the canonical name (no prefix, suffix or path).
823       commands.clear();
824       depends.clear();
825       depends.push_back(localName);
826       lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
827                         t->second.GetName(), depends, commands, true);
828
829       // Add rules to prepare the target for installation.
830       if(t->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str()))
831         {
832         localName = lg->GetRelativeTargetDirectory(t->second);
833         localName += "/preinstall";
834         depends.clear();
835         commands.clear();
836         commands.push_back(lg->GetRecursiveMakeCall
837                             (makefileName.c_str(), localName.c_str()));
838         lg->WriteMakeRule(ruleFileStream,
839                           "Pre-install relink rule for target.",
840                           localName.c_str(), depends, commands, true);
841
842         if(!this->IsExcluded(this->LocalGenerators[0], t->second))
843           {
844           depends.clear();
845           depends.push_back(localName);
846           commands.clear();
847           lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
848                             "preinstall", depends, commands, true);
849           }
850         }
851
852       // add the clean rule
853       localName = lg->GetRelativeTargetDirectory(t->second);
854       makeTargetName = localName;
855       makeTargetName += "/clean";
856       depends.clear();
857       commands.clear();
858       commands.push_back(lg->GetRecursiveMakeCall
859                           (makefileName.c_str(), makeTargetName.c_str()));
860       lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
861                         makeTargetName.c_str(), depends, commands, true);
862       commands.clear();
863       depends.push_back(makeTargetName);
864       lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
865                         "clean", depends, commands, true);
866       }
867     }
868 }
869
870 //----------------------------------------------------------------------------
871 size_t
872 cmGlobalUnixMakefileGenerator3
873 ::CountProgressMarksInTarget(cmTarget* target,
874                              std::set<cmTarget*>& emitted)
875 {
876   size_t count = 0;
877   if(emitted.insert(target).second)
878     {
879     count = this->ProgressMap[target].Marks.size();
880     TargetDependSet const& depends = this->GetTargetDirectDepends(*target);
881     for(TargetDependSet::const_iterator di = depends.begin();
882         di != depends.end(); ++di)
883       {
884       count += this->CountProgressMarksInTarget(*di, emitted);
885       }
886     }
887   return count;
888 }
889
890 //----------------------------------------------------------------------------
891 size_t
892 cmGlobalUnixMakefileGenerator3
893 ::CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg)
894 {
895   size_t count = 0;
896   std::set<cmTarget*> emitted;
897   std::set<cmTarget*> const& targets = this->LocalGeneratorToTargetMap[lg];
898   for(std::set<cmTarget*>::const_iterator t = targets.begin();
899       t != targets.end(); ++t)
900     {
901     count += this->CountProgressMarksInTarget(*t, emitted);
902     }
903   return count;
904 }
905
906 //----------------------------------------------------------------------------
907 void
908 cmGlobalUnixMakefileGenerator3::RecordTargetProgress(
909   cmMakefileTargetGenerator* tg)
910 {
911   TargetProgress& tp = this->ProgressMap[tg->GetTarget()];
912   tp.NumberOfActions = tg->GetNumberOfProgressActions();
913   tp.VariableFile = tg->GetProgressFileNameFull();
914 }
915
916 //----------------------------------------------------------------------------
917 bool
918 cmGlobalUnixMakefileGenerator3::ProgressMapCompare
919 ::operator()(cmTarget* l, cmTarget* r) const
920 {
921   // Order by target name.
922   if(int c = strcmp(l->GetName(), r->GetName()))
923     {
924     return c < 0;
925     }
926   // Order duplicate targets by binary directory.
927   return strcmp(l->GetMakefile()->GetCurrentOutputDirectory(),
928                 r->GetMakefile()->GetCurrentOutputDirectory()) < 0;
929 }
930
931 //----------------------------------------------------------------------------
932 void
933 cmGlobalUnixMakefileGenerator3::TargetProgress
934 ::WriteProgressVariables(unsigned long total, unsigned long &current)
935 {
936   cmGeneratedFileStream fout(this->VariableFile.c_str());
937   for(unsigned long i = 1; i <= this->NumberOfActions; ++i)
938     {
939     fout << "CMAKE_PROGRESS_" << i << " = ";
940     if (total <= 100)
941       {
942       unsigned long num = i + current;
943       fout << num;
944       this->Marks.push_back(num);
945       }
946     else if (((i+current)*100)/total > ((i-1+current)*100)/total)
947       {
948       unsigned long num = ((i+current)*100)/total;
949       fout << num;
950       this->Marks.push_back(num);
951       }
952     fout << "\n";
953     }
954   fout << "\n";
955   current += this->NumberOfActions;
956 }
957
958 //----------------------------------------------------------------------------
959 void
960 cmGlobalUnixMakefileGenerator3
961 ::AppendGlobalTargetDepends(std::vector<std::string>& depends,
962                             cmTarget& target)
963 {
964   TargetDependSet const& depends_set = this->GetTargetDirectDepends(target);
965   for(TargetDependSet::const_iterator i = depends_set.begin();
966       i != depends_set.end(); ++i)
967     {
968     // Create the target-level dependency.
969     cmTarget const* dep = *i;
970     cmLocalUnixMakefileGenerator3* lg3 =
971       static_cast<cmLocalUnixMakefileGenerator3*>
972       (dep->GetMakefile()->GetLocalGenerator());
973     std::string tgtName = lg3->GetRelativeTargetDirectory(*dep);
974     tgtName += "/all";
975     depends.push_back(tgtName);
976     }
977 }
978
979 //----------------------------------------------------------------------------
980 void cmGlobalUnixMakefileGenerator3::WriteHelpRule
981 (std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
982 {
983   // add the help target
984   std::string path;
985   std::vector<std::string> no_depends;
986   std::vector<std::string> commands;
987   lg->AppendEcho(commands,"The following are some of the valid targets "
988                  "for this Makefile:");
989   lg->AppendEcho(commands,"... all (the default if no target is provided)");
990   lg->AppendEcho(commands,"... clean");
991   lg->AppendEcho(commands,"... depend");
992
993   // Keep track of targets already listed.
994   std::set<cmStdString> emittedTargets;
995
996   // for each local generator
997   unsigned int i;
998   cmLocalUnixMakefileGenerator3 *lg2;
999   for (i = 0; i < this->LocalGenerators.size(); ++i)
1000     {
1001     lg2 =
1002       static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
1003     // for the passed in makefile or if this is the top Makefile wripte out
1004     // the targets
1005     if (lg2 == lg || !lg->GetParent())
1006       {
1007       // for each target Generate the rule files for each target.
1008       cmTargets& targets = lg2->GetMakefile()->GetTargets();
1009       for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
1010         {
1011         if((t->second.GetType() == cmTarget::EXECUTABLE) ||
1012            (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
1013            (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
1014            (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
1015            (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
1016            (t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
1017            (t->second.GetType() == cmTarget::UTILITY))
1018           {
1019           if(emittedTargets.insert(t->second.GetName()).second)
1020             {
1021             path = "... ";
1022             path += t->second.GetName();
1023             lg->AppendEcho(commands,path.c_str());
1024             }
1025           }
1026         }
1027       }
1028     }
1029   std::vector<cmStdString> const& localHelp = lg->GetLocalHelp();
1030   for(std::vector<cmStdString>::const_iterator o = localHelp.begin();
1031       o != localHelp.end(); ++o)
1032     {
1033     path = "... ";
1034     path += *o;
1035     lg->AppendEcho(commands, path.c_str());
1036     }
1037   lg->WriteMakeRule(ruleFileStream, "Help Target",
1038                     "help",
1039                     no_depends, commands, true);
1040   ruleFileStream << "\n\n";
1041 }
1042
1043
1044 bool cmGlobalUnixMakefileGenerator3
1045 ::NeedRequiresStep(cmTarget const& target)
1046 {
1047   std::set<cmStdString> languages;
1048   target.GetLanguages(languages);
1049   for(std::set<cmStdString>::const_iterator l = languages.begin();
1050       l != languages.end(); ++l)
1051     {
1052     std::string var = "CMAKE_NEEDS_REQUIRES_STEP_";
1053     var += *l;
1054     var += "_FLAG";
1055     if(target.GetMakefile()->GetDefinition(var.c_str()))
1056       {
1057       return true;
1058       }
1059     }
1060   return false;
1061 }