Imported Upstream version 2.8.11.2
[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* additionalOptions, const char *targetName,
521                        const char* config, bool ignoreErrors, bool fast)
522 {
523   // Project name and config are not used yet.
524   (void)projectName;
525   (void)config;
526
527   std::string makeCommand =
528     cmSystemTools::ConvertToUnixOutputPath(makeProgram);
529
530   // Since we have full control over the invocation of nmake, let us
531   // make it quiet.
532   if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
533     {
534     makeCommand += " /NOLOGO ";
535     }
536   if ( ignoreErrors )
537     {
538     makeCommand += " -i";
539     }
540   if ( additionalOptions )
541     {
542     makeCommand += " ";
543     makeCommand += additionalOptions;
544     }
545   if ( targetName && strlen(targetName))
546     {
547     cmLocalUnixMakefileGenerator3 *lg;
548     if (this->LocalGenerators.size())
549       {
550       lg = static_cast<cmLocalUnixMakefileGenerator3 *>
551         (this->LocalGenerators[0]);
552       }
553     else
554       {
555       lg = static_cast<cmLocalUnixMakefileGenerator3 *>
556         (this->CreateLocalGenerator());
557       // set the Start directories
558       lg->GetMakefile()->SetStartDirectory
559         (this->CMakeInstance->GetStartDirectory());
560       lg->GetMakefile()->SetStartOutputDirectory
561         (this->CMakeInstance->GetStartOutputDirectory());
562       lg->GetMakefile()->MakeStartDirectoriesCurrent();
563       }
564
565     makeCommand += " \"";
566     std::string tname = targetName;
567     if(fast)
568       {
569       tname += "/fast";
570       }
571     tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
572                         cmLocalGenerator::MAKEFILE);
573     makeCommand += tname.c_str();
574     makeCommand += "\"";
575     if (!this->LocalGenerators.size())
576       {
577       delete lg;
578       }
579     }
580   return makeCommand;
581 }
582
583 //----------------------------------------------------------------------------
584 void
585 cmGlobalUnixMakefileGenerator3
586 ::WriteConvenienceRules(std::ostream& ruleFileStream,
587                         std::set<cmStdString> &emitted)
588 {
589   std::vector<std::string> depends;
590   std::vector<std::string> commands;
591
592   depends.push_back("cmake_check_build_system");
593
594   // write the target convenience rules
595   unsigned int i;
596   cmLocalUnixMakefileGenerator3 *lg;
597   for (i = 0; i < this->LocalGenerators.size(); ++i)
598     {
599     lg = static_cast<cmLocalUnixMakefileGenerator3 *>
600       (this->LocalGenerators[i]);
601     // for each target Generate the rule files for each target.
602     cmTargets& targets = lg->GetMakefile()->GetTargets();
603     for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
604       {
605       // Don't emit the same rule twice (e.g. two targets with the same
606       // simple name)
607       if(t->second.GetName() &&
608          strlen(t->second.GetName()) &&
609          emitted.insert(t->second.GetName()).second &&
610          // Handle user targets here.  Global targets are handled in
611          // the local generator on a per-directory basis.
612          ((t->second.GetType() == cmTarget::EXECUTABLE) ||
613           (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
614           (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
615           (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
616           (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
617           (t->second.GetType() == cmTarget::UTILITY)))
618         {
619         // Add a rule to build the target by name.
620         lg->WriteDivider(ruleFileStream);
621         ruleFileStream
622           << "# Target rules for targets named "
623           << t->second.GetName() << "\n\n";
624
625         // Write the rule.
626         commands.clear();
627         std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
628         tmp += "Makefile2";
629         commands.push_back(lg->GetRecursiveMakeCall
630                             (tmp.c_str(),t->second.GetName()));
631         depends.clear();
632         depends.push_back("cmake_check_build_system");
633         lg->WriteMakeRule(ruleFileStream,
634                           "Build rule for target.",
635                           t->second.GetName(), depends, commands,
636                           true);
637
638         // Add a fast rule to build the target
639         std::string localName = lg->GetRelativeTargetDirectory(t->second);
640         std::string makefileName;
641         makefileName = localName;
642         makefileName += "/build.make";
643         depends.clear();
644         commands.clear();
645         std::string makeTargetName = localName;
646         makeTargetName += "/build";
647         localName = t->second.GetName();
648         localName += "/fast";
649         commands.push_back(lg->GetRecursiveMakeCall
650                             (makefileName.c_str(), makeTargetName.c_str()));
651         lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
652                           localName.c_str(), depends, commands, true);
653
654         // Add a local name for the rule to relink the target before
655         // installation.
656         if(t->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str()))
657           {
658           makeTargetName = lg->GetRelativeTargetDirectory(t->second);
659           makeTargetName += "/preinstall";
660           localName = t->second.GetName();
661           localName += "/preinstall";
662           depends.clear();
663           commands.clear();
664           commands.push_back(lg->GetRecursiveMakeCall
665                              (makefileName.c_str(), makeTargetName.c_str()));
666           lg->WriteMakeRule(ruleFileStream,
667                             "Manual pre-install relink rule for target.",
668                             localName.c_str(), depends, commands, true);
669           }
670         }
671       }
672     }
673 }
674
675
676 //----------------------------------------------------------------------------
677 void
678 cmGlobalUnixMakefileGenerator3
679 ::WriteConvenienceRules2(std::ostream& ruleFileStream,
680                          cmLocalUnixMakefileGenerator3 *lg)
681 {
682   std::vector<std::string> depends;
683   std::vector<std::string> commands;
684   std::string localName;
685   std::string makeTargetName;
686
687
688   // write the directory level rules for this local gen
689   this->WriteDirectoryRules2(ruleFileStream,lg);
690
691   depends.push_back("cmake_check_build_system");
692
693   // for each target Generate the rule files for each target.
694   cmTargets& targets = lg->GetMakefile()->GetTargets();
695   for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
696     {
697     if (t->second.GetName()
698      && strlen(t->second.GetName())
699      && ((t->second.GetType() == cmTarget::EXECUTABLE)
700         || (t->second.GetType() == cmTarget::STATIC_LIBRARY)
701         || (t->second.GetType() == cmTarget::SHARED_LIBRARY)
702         || (t->second.GetType() == cmTarget::MODULE_LIBRARY)
703         || (t->second.GetType() == cmTarget::OBJECT_LIBRARY)
704         || (t->second.GetType() == cmTarget::UTILITY)))
705       {
706       std::string makefileName;
707       // Add a rule to build the target by name.
708       localName = lg->GetRelativeTargetDirectory(t->second);
709       makefileName = localName;
710       makefileName += "/build.make";
711
712       bool needRequiresStep = this->NeedRequiresStep(t->second);
713
714       lg->WriteDivider(ruleFileStream);
715       ruleFileStream
716         << "# Target rules for target "
717         << localName << "\n\n";
718
719       commands.clear();
720       makeTargetName = localName;
721       makeTargetName += "/depend";
722       commands.push_back(lg->GetRecursiveMakeCall
723                          (makefileName.c_str(),makeTargetName.c_str()));
724
725       // add requires if we need it for this generator
726       if (needRequiresStep)
727         {
728         makeTargetName = localName;
729         makeTargetName += "/requires";
730         commands.push_back(lg->GetRecursiveMakeCall
731                            (makefileName.c_str(),makeTargetName.c_str()));
732         }
733       makeTargetName = localName;
734       makeTargetName += "/build";
735       commands.push_back(lg->GetRecursiveMakeCall
736                           (makefileName.c_str(),makeTargetName.c_str()));
737
738       // Write the rule.
739       localName += "/all";
740       depends.clear();
741
742       std::string progressDir =
743         lg->GetMakefile()->GetHomeOutputDirectory();
744       progressDir += cmake::GetCMakeFilesDirectory();
745         {
746         cmOStringStream progCmd;
747         progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
748         // all target counts
749         progCmd << lg->Convert(progressDir.c_str(),
750                                 cmLocalGenerator::FULL,
751                                 cmLocalGenerator::SHELL);
752         progCmd << " ";
753         std::vector<unsigned long>& progFiles =
754           this->ProgressMap[&t->second].Marks;
755         for (std::vector<unsigned long>::iterator i = progFiles.begin();
756               i != progFiles.end(); ++i)
757           {
758           progCmd << " " << *i;
759           }
760         commands.push_back(progCmd.str());
761         }
762       progressDir = "Built target ";
763       progressDir += t->first;
764       lg->AppendEcho(commands,progressDir.c_str());
765
766       this->AppendGlobalTargetDepends(depends,t->second);
767       lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
768                         localName.c_str(), depends, commands, true);
769
770       // add the all/all dependency
771       if(!this->IsExcluded(this->LocalGenerators[0], t->second))
772         {
773         depends.clear();
774         depends.push_back(localName);
775         commands.clear();
776         lg->WriteMakeRule(ruleFileStream, "Include target in all.",
777                           "all", depends, commands, true);
778         }
779
780       // Write the rule.
781       commands.clear();
782       progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
783       progressDir += cmake::GetCMakeFilesDirectory();
784
785       {
786       // TODO: Convert the total progress count to a make variable.
787       cmOStringStream progCmd;
788       progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
789       // # in target
790       progCmd << lg->Convert(progressDir.c_str(),
791                               cmLocalGenerator::FULL,
792                               cmLocalGenerator::SHELL);
793       //
794       std::set<cmTarget *> emitted;
795       progCmd << " "
796               << this->CountProgressMarksInTarget(&t->second, emitted);
797       commands.push_back(progCmd.str());
798       }
799       std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
800       tmp += "Makefile2";
801       commands.push_back(lg->GetRecursiveMakeCall
802                           (tmp.c_str(),localName.c_str()));
803       {
804       cmOStringStream progCmd;
805       progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
806       progCmd << lg->Convert(progressDir.c_str(),
807                               cmLocalGenerator::FULL,
808                               cmLocalGenerator::SHELL);
809       progCmd << " 0";
810       commands.push_back(progCmd.str());
811       }
812       depends.clear();
813       depends.push_back("cmake_check_build_system");
814       localName = lg->GetRelativeTargetDirectory(t->second);
815       localName += "/rule";
816       lg->WriteMakeRule(ruleFileStream,
817                         "Build rule for subdir invocation for target.",
818                         localName.c_str(), depends, commands, true);
819
820       // Add a target with the canonical name (no prefix, suffix or path).
821       commands.clear();
822       depends.clear();
823       depends.push_back(localName);
824       lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
825                         t->second.GetName(), depends, commands, true);
826
827       // Add rules to prepare the target for installation.
828       if(t->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str()))
829         {
830         localName = lg->GetRelativeTargetDirectory(t->second);
831         localName += "/preinstall";
832         depends.clear();
833         commands.clear();
834         commands.push_back(lg->GetRecursiveMakeCall
835                             (makefileName.c_str(), localName.c_str()));
836         lg->WriteMakeRule(ruleFileStream,
837                           "Pre-install relink rule for target.",
838                           localName.c_str(), depends, commands, true);
839
840         if(!this->IsExcluded(this->LocalGenerators[0], t->second))
841           {
842           depends.clear();
843           depends.push_back(localName);
844           commands.clear();
845           lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
846                             "preinstall", depends, commands, true);
847           }
848         }
849
850       // add the clean rule
851       localName = lg->GetRelativeTargetDirectory(t->second);
852       makeTargetName = localName;
853       makeTargetName += "/clean";
854       depends.clear();
855       commands.clear();
856       commands.push_back(lg->GetRecursiveMakeCall
857                           (makefileName.c_str(), makeTargetName.c_str()));
858       lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
859                         makeTargetName.c_str(), depends, commands, true);
860       commands.clear();
861       depends.push_back(makeTargetName);
862       lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
863                         "clean", depends, commands, true);
864       }
865     }
866 }
867
868 //----------------------------------------------------------------------------
869 size_t
870 cmGlobalUnixMakefileGenerator3
871 ::CountProgressMarksInTarget(cmTarget* target,
872                              std::set<cmTarget*>& emitted)
873 {
874   size_t count = 0;
875   if(emitted.insert(target).second)
876     {
877     count = this->ProgressMap[target].Marks.size();
878     TargetDependSet const& depends = this->GetTargetDirectDepends(*target);
879     for(TargetDependSet::const_iterator di = depends.begin();
880         di != depends.end(); ++di)
881       {
882       count += this->CountProgressMarksInTarget(*di, emitted);
883       }
884     }
885   return count;
886 }
887
888 //----------------------------------------------------------------------------
889 size_t
890 cmGlobalUnixMakefileGenerator3
891 ::CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg)
892 {
893   size_t count = 0;
894   std::set<cmTarget*> emitted;
895   std::set<cmTarget*> const& targets = this->LocalGeneratorToTargetMap[lg];
896   for(std::set<cmTarget*>::const_iterator t = targets.begin();
897       t != targets.end(); ++t)
898     {
899     count += this->CountProgressMarksInTarget(*t, emitted);
900     }
901   return count;
902 }
903
904 //----------------------------------------------------------------------------
905 void
906 cmGlobalUnixMakefileGenerator3::RecordTargetProgress(
907   cmMakefileTargetGenerator* tg)
908 {
909   TargetProgress& tp = this->ProgressMap[tg->GetTarget()];
910   tp.NumberOfActions = tg->GetNumberOfProgressActions();
911   tp.VariableFile = tg->GetProgressFileNameFull();
912 }
913
914 //----------------------------------------------------------------------------
915 bool
916 cmGlobalUnixMakefileGenerator3::ProgressMapCompare
917 ::operator()(cmTarget* l, cmTarget* r) const
918 {
919   // Order by target name.
920   if(int c = strcmp(l->GetName(), r->GetName()))
921     {
922     return c < 0;
923     }
924   // Order duplicate targets by binary directory.
925   return strcmp(l->GetMakefile()->GetCurrentOutputDirectory(),
926                 r->GetMakefile()->GetCurrentOutputDirectory()) < 0;
927 }
928
929 //----------------------------------------------------------------------------
930 void
931 cmGlobalUnixMakefileGenerator3::TargetProgress
932 ::WriteProgressVariables(unsigned long total, unsigned long &current)
933 {
934   cmGeneratedFileStream fout(this->VariableFile.c_str());
935   for(unsigned long i = 1; i <= this->NumberOfActions; ++i)
936     {
937     fout << "CMAKE_PROGRESS_" << i << " = ";
938     if (total <= 100)
939       {
940       unsigned long num = i + current;
941       fout << num;
942       this->Marks.push_back(num);
943       }
944     else if (((i+current)*100)/total > ((i-1+current)*100)/total)
945       {
946       unsigned long num = ((i+current)*100)/total;
947       fout << num;
948       this->Marks.push_back(num);
949       }
950     fout << "\n";
951     }
952   fout << "\n";
953   current += this->NumberOfActions;
954 }
955
956 //----------------------------------------------------------------------------
957 void
958 cmGlobalUnixMakefileGenerator3
959 ::AppendGlobalTargetDepends(std::vector<std::string>& depends,
960                             cmTarget& target)
961 {
962   TargetDependSet const& depends_set = this->GetTargetDirectDepends(target);
963   for(TargetDependSet::const_iterator i = depends_set.begin();
964       i != depends_set.end(); ++i)
965     {
966     // Create the target-level dependency.
967     cmTarget const* dep = *i;
968     cmLocalUnixMakefileGenerator3* lg3 =
969       static_cast<cmLocalUnixMakefileGenerator3*>
970       (dep->GetMakefile()->GetLocalGenerator());
971     std::string tgtName = lg3->GetRelativeTargetDirectory(*dep);
972     tgtName += "/all";
973     depends.push_back(tgtName);
974     }
975 }
976
977 //----------------------------------------------------------------------------
978 void cmGlobalUnixMakefileGenerator3::WriteHelpRule
979 (std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
980 {
981   // add the help target
982   std::string path;
983   std::vector<std::string> no_depends;
984   std::vector<std::string> commands;
985   lg->AppendEcho(commands,"The following are some of the valid targets "
986                  "for this Makefile:");
987   lg->AppendEcho(commands,"... all (the default if no target is provided)");
988   lg->AppendEcho(commands,"... clean");
989   lg->AppendEcho(commands,"... depend");
990
991   // Keep track of targets already listed.
992   std::set<cmStdString> emittedTargets;
993
994   // for each local generator
995   unsigned int i;
996   cmLocalUnixMakefileGenerator3 *lg2;
997   for (i = 0; i < this->LocalGenerators.size(); ++i)
998     {
999     lg2 =
1000       static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
1001     // for the passed in makefile or if this is the top Makefile wripte out
1002     // the targets
1003     if (lg2 == lg || !lg->GetParent())
1004       {
1005       // for each target Generate the rule files for each target.
1006       cmTargets& targets = lg2->GetMakefile()->GetTargets();
1007       for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
1008         {
1009         if((t->second.GetType() == cmTarget::EXECUTABLE) ||
1010            (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
1011            (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
1012            (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
1013            (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
1014            (t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
1015            (t->second.GetType() == cmTarget::UTILITY))
1016           {
1017           if(emittedTargets.insert(t->second.GetName()).second)
1018             {
1019             path = "... ";
1020             path += t->second.GetName();
1021             lg->AppendEcho(commands,path.c_str());
1022             }
1023           }
1024         }
1025       }
1026     }
1027   std::vector<cmStdString> const& localHelp = lg->GetLocalHelp();
1028   for(std::vector<cmStdString>::const_iterator o = localHelp.begin();
1029       o != localHelp.end(); ++o)
1030     {
1031     path = "... ";
1032     path += *o;
1033     lg->AppendEcho(commands, path.c_str());
1034     }
1035   lg->WriteMakeRule(ruleFileStream, "Help Target",
1036                     "help",
1037                     no_depends, commands, true);
1038   ruleFileStream << "\n\n";
1039 }
1040
1041
1042 bool cmGlobalUnixMakefileGenerator3
1043 ::NeedRequiresStep(cmTarget const& target)
1044 {
1045   std::set<cmStdString> languages;
1046   target.GetLanguages(languages);
1047   for(std::set<cmStdString>::const_iterator l = languages.begin();
1048       l != languages.end(); ++l)
1049     {
1050     std::string var = "CMAKE_NEEDS_REQUIRES_STEP_";
1051     var += *l;
1052     var += "_FLAG";
1053     if(target.GetMakefile()->GetDefinition(var.c_str()))
1054       {
1055       return true;
1056       }
1057     }
1058   return false;
1059 }