BUG: fix some bad changes in progress calc
[cmake.git] / Source / cmGlobalUnixMakefileGenerator3.cxx
blobf684b4a0dce79fd636d60d71813e13f4a12cb1bf
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator3
4 Module: $RCSfile: cmGlobalUnixMakefileGenerator3.cxx,v $
5 Language: C++
6 Date: $Date: 2008-03-12 18:37:46 $
7 Version: $Revision: 1.126 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include "cmGlobalUnixMakefileGenerator3.h"
19 #include "cmLocalUnixMakefileGenerator3.h"
20 #include "cmMakefile.h"
21 #include "cmake.h"
22 #include "cmGeneratedFileStream.h"
23 #include "cmSourceFile.h"
24 #include "cmTarget.h"
26 cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
28 // This type of makefile always requires unix style paths
29 this->ForceUnixPaths = true;
30 this->FindMakeProgramFile = "CMakeUnixFindMake.cmake";
31 this->ToolSupportsColor = true;
32 this->ForceVerboseMakefiles = false;
34 #ifdef _WIN32
35 this->UseLinkScript = false;
36 #else
37 this->UseLinkScript = true;
38 #endif
41 void cmGlobalUnixMakefileGenerator3
42 ::EnableLanguage(std::vector<std::string>const& languages,
43 cmMakefile *mf,
44 bool optional)
46 this->cmGlobalGenerator::EnableLanguage(languages, mf, optional);
47 std::string path;
48 for(std::vector<std::string>::const_iterator l = languages.begin();
49 l != languages.end(); ++l)
51 if(*l == "NONE")
53 continue;
55 const char* lang = l->c_str();
56 std::string langComp = "CMAKE_";
57 langComp += lang;
58 langComp += "_COMPILER";
60 if(!mf->GetDefinition(langComp.c_str()))
62 cmSystemTools::Error(langComp.c_str(),
63 " not set, after EnableLanguage");
64 continue;
66 const char* name = mf->GetRequiredDefinition(langComp.c_str());
67 if(!cmSystemTools::FileIsFullPath(name))
69 path = cmSystemTools::FindProgram(name);
71 else
73 path = name;
75 if((path.size() == 0 || !cmSystemTools::FileExists(path.c_str()))
76 && (optional==false))
78 std::string message = "your ";
79 message += lang;
80 message += " compiler: \"";
81 message += name;
82 message += "\" was not found. Please set ";
83 message += langComp;
84 message += " to a valid compiler path or name.";
85 cmSystemTools::Error(message.c_str());
86 path = name;
88 std::string doc = lang;
89 doc += " compiler.";
90 const char* cname = this->GetCMakeInstance()->
91 GetCacheManager()->GetCacheValue(langComp.c_str());
92 std::string changeVars;
93 if(cname && (path != cname))
95 const char* cvars =
96 this->GetCMakeInstance()->GetProperty(
97 "__CMAKE_DELETE_CACHE_CHANGE_VARS_");
98 if(cvars)
100 changeVars += cvars;
101 changeVars += ";";
103 changeVars += langComp;
104 changeVars += ";";
105 changeVars += cname;
106 this->GetCMakeInstance()->SetProperty(
107 "__CMAKE_DELETE_CACHE_CHANGE_VARS_",
108 changeVars.c_str());
110 mf->AddCacheDefinition(langComp.c_str(), path.c_str(),
111 doc.c_str(), cmCacheManager::FILEPATH);
115 ///! Create a local generator appropriate to this Global Generator
116 cmLocalGenerator *cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
118 cmLocalGenerator* lg = new cmLocalUnixMakefileGenerator3;
119 lg->SetGlobalGenerator(this);
120 return lg;
123 //----------------------------------------------------------------------------
124 void cmGlobalUnixMakefileGenerator3
125 ::GetDocumentation(cmDocumentationEntry& entry) const
127 entry.Name = this->GetName();
128 entry.Brief = "Generates standard UNIX makefiles.";
129 entry.Full =
130 "A hierarchy of UNIX makefiles is generated into the build tree. Any "
131 "standard UNIX-style make program can build the project through the "
132 "default make target. A \"make install\" target is also provided.";
135 //----------------------------------------------------------------------------
136 void cmGlobalUnixMakefileGenerator3::Generate()
138 // first do superclass method
139 this->cmGlobalGenerator::Generate();
141 // initialize progress
142 unsigned int i;
143 unsigned long total = 0;
144 for (i = 0; i < this->LocalGenerators.size(); ++i)
146 cmLocalUnixMakefileGenerator3 *lg =
147 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
148 total += lg->GetNumberOfProgressActions();
151 // write each target's progress.make this loop is done twice. Bascially the
152 // Generate pass counts all the actions, the first loop below determines
153 // how many actions have progress updates for each target and writes to
154 // corrrect variable values for everything except the all targets. The
155 // second loop actually writes out correct values for the all targets as
156 // well. This is because the all targets require more information that is
157 // computed in the first loop.
158 unsigned long current = 0;
159 for (i = 0; i < this->LocalGenerators.size(); ++i)
161 cmLocalUnixMakefileGenerator3 *lg =
162 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
163 lg->WriteProgressVariables(total,current);
165 for (i = 0; i < this->LocalGenerators.size(); ++i)
167 cmLocalUnixMakefileGenerator3 *lg =
168 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
169 lg->WriteAllProgressVariable();
172 // write the main makefile
173 this->WriteMainMakefile2();
174 this->WriteMainCMakefile();
177 void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
179 // Open the output file. This should not be copy-if-different
180 // because the check-build-system step compares the makefile time to
181 // see if the build system must be regenerated.
182 std::string makefileName =
183 this->GetCMakeInstance()->GetHomeOutputDirectory();
184 makefileName += cmake::GetCMakeFilesDirectory();
185 makefileName += "/Makefile2";
186 cmGeneratedFileStream makefileStream(makefileName.c_str());
187 if(!makefileStream)
189 return;
192 // get a local generator for some useful methods
193 cmLocalUnixMakefileGenerator3 *lg =
194 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
196 // Write the do not edit header.
197 lg->WriteDisclaimer(makefileStream);
199 // Write the main entry point target. This must be the VERY first
200 // target so that make with no arguments will run it.
201 // Just depend on the all target to drive the build.
202 std::vector<std::string> depends;
203 std::vector<std::string> no_commands;
204 depends.push_back("all");
206 // Write the rule.
207 lg->WriteMakeRule(makefileStream,
208 "Default target executed when no arguments are "
209 "given to make.",
210 "default_target",
211 depends,
212 no_commands, true);
214 depends.clear();
216 // The all and preinstall rules might never have any dependencies
217 // added to them.
218 if(this->EmptyRuleHackDepends != "")
220 depends.push_back(this->EmptyRuleHackDepends);
223 // Write and empty all:
224 lg->WriteMakeRule(makefileStream,
225 "The main recursive all target", "all",
226 depends, no_commands, true);
228 // Write an empty preinstall:
229 lg->WriteMakeRule(makefileStream,
230 "The main recursive preinstall target", "preinstall",
231 depends, no_commands, true);
233 // Write out the "special" stuff
234 lg->WriteSpecialTargetsTop(makefileStream);
236 // write the target convenience rules
237 unsigned int i;
238 for (i = 0; i < this->LocalGenerators.size(); ++i)
240 lg =
241 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
242 this->WriteConvenienceRules2(makefileStream,lg);
245 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
246 lg->WriteSpecialTargetsBottom(makefileStream);
250 //----------------------------------------------------------------------------
251 void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
253 // Open the output file. This should not be copy-if-different
254 // because the check-build-system step compares the makefile time to
255 // see if the build system must be regenerated.
256 std::string cmakefileName =
257 this->GetCMakeInstance()->GetHomeOutputDirectory();
258 cmakefileName += cmake::GetCMakeFilesDirectory();
259 cmakefileName += "/Makefile.cmake";
260 cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
261 if(!cmakefileStream)
263 return;
266 std::string makefileName =
267 this->GetCMakeInstance()->GetHomeOutputDirectory();
268 makefileName += "/Makefile";
270 // get a local generator for some useful methods
271 cmLocalUnixMakefileGenerator3 *lg =
272 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
274 // Write the do not edit header.
275 lg->WriteDisclaimer(cmakefileStream);
277 // Save the generator name
278 cmakefileStream
279 << "# The generator used is:\n"
280 << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
282 // for each cmMakefile get its list of dependencies
283 std::vector<std::string> lfiles;
284 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
286 lg =
287 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
289 // Get the list of files contributing to this generation step.
290 lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
291 lg->GetMakefile()->GetListFiles().end());
293 // Sort the list and remove duplicates.
294 std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
295 std::vector<std::string>::iterator new_end =
296 std::unique(lfiles.begin(),lfiles.end());
297 lfiles.erase(new_end, lfiles.end());
299 // reset lg to the first makefile
300 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
302 // Build the path to the cache file.
303 std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
304 cache += "/CMakeCache.txt";
306 // Save the list to the cmake file.
307 cmakefileStream
308 << "# The top level Makefile was generated from the following files:\n"
309 << "SET(CMAKE_MAKEFILE_DEPENDS\n"
310 << " \""
311 << lg->Convert(cache.c_str(),
312 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
313 for(std::vector<std::string>::const_iterator i = lfiles.begin();
314 i != lfiles.end(); ++i)
316 cmakefileStream
317 << " \""
318 << lg->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT).c_str()
319 << "\"\n";
321 cmakefileStream
322 << " )\n\n";
324 // Build the path to the cache check file.
325 std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
326 check += cmake::GetCMakeFilesDirectory();
327 check += "/cmake.check_cache";
329 // Set the corresponding makefile in the cmake file.
330 cmakefileStream
331 << "# The corresponding makefile is:\n"
332 << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
333 << " \""
334 << lg->Convert(makefileName.c_str(),
335 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n"
336 << " \""
337 << lg->Convert(check.c_str(),
338 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
340 // add in all the directory information files
341 std::string tmpStr;
342 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
344 lg =
345 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
346 tmpStr = lg->GetMakefile()->GetStartOutputDirectory();
347 tmpStr += cmake::GetCMakeFilesDirectory();
348 tmpStr += "/CMakeDirectoryInformation.cmake";
349 cmakefileStream << " \"" <<
350 lg->Convert(tmpStr.c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
351 << "\"\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)
357 cmakefileStream << " \"" <<
358 lg->Convert(k->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
359 << "\"\n";
362 cmakefileStream << " )\n\n";
364 this->WriteMainCMakefileLanguageRules(cmakefileStream,
365 this->LocalGenerators);
368 void cmGlobalUnixMakefileGenerator3
369 ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
370 std::vector<cmLocalGenerator *> &lGenerators
373 cmLocalUnixMakefileGenerator3 *lg;
375 // now list all the target info files
376 cmakefileStream
377 << "# Dependency information for all targets:\n";
378 cmakefileStream
379 << "SET(CMAKE_DEPEND_INFO_FILES\n";
380 for (unsigned int i = 0; i < lGenerators.size(); ++i)
382 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
383 // for all of out targets
384 for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
385 l != lg->GetMakefile()->GetTargets().end(); l++)
387 if((l->second.GetType() == cmTarget::EXECUTABLE) ||
388 (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
389 (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
390 (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
391 (l->second.GetType() == cmTarget::UTILITY))
393 std::string tname = lg->GetRelativeTargetDirectory(l->second);
394 tname += "/DependInfo.cmake";
395 cmSystemTools::ConvertToUnixSlashes(tname);
396 cmakefileStream << " \"" << tname.c_str() << "\"\n";
400 cmakefileStream << " )\n";
403 //----------------------------------------------------------------------------
404 void
405 cmGlobalUnixMakefileGenerator3
406 ::WriteDirectoryRule2(std::ostream& ruleFileStream,
407 cmLocalUnixMakefileGenerator3* lg,
408 const char* pass, bool check_all,
409 bool check_relink)
411 // Get the relative path to the subdirectory from the top.
412 std::string makeTarget = lg->GetMakefile()->GetStartOutputDirectory();
413 makeTarget += "/";
414 makeTarget += pass;
416 // The directory-level rule should depend on the target-level rules
417 // for all targets in the directory.
418 std::vector<std::string> depends;
419 for(cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
420 l != lg->GetMakefile()->GetTargets().end(); ++l)
422 if((l->second.GetType() == cmTarget::EXECUTABLE) ||
423 (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
424 (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
425 (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
426 (l->second.GetType() == cmTarget::UTILITY))
428 // Add this to the list of depends rules in this directory.
429 if((!check_all || !l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
430 (!check_relink || l->second.NeedRelinkBeforeInstall()))
432 std::string tname = lg->GetRelativeTargetDirectory(l->second);
433 tname += "/";
434 tname += pass;
435 depends.push_back(tname);
440 // The directory-level rule should depend on the directory-level
441 // rules of the subdirectories.
442 for(std::vector<cmLocalGenerator*>::iterator sdi =
443 lg->GetChildren().begin(); sdi != lg->GetChildren().end(); ++sdi)
445 cmLocalUnixMakefileGenerator3* slg =
446 static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
447 std::string subdir = slg->GetMakefile()->GetStartOutputDirectory();
448 subdir += "/";
449 subdir += pass;
450 depends.push_back(subdir);
453 // Work-around for makes that drop rules that have no dependencies
454 // or commands.
455 if(depends.empty() && this->EmptyRuleHackDepends != "")
457 depends.push_back(this->EmptyRuleHackDepends);
460 // Write the rule.
461 std::string doc = "Convenience name for \"";
462 doc += pass;
463 doc += "\" pass in the directory.";
464 std::vector<std::string> no_commands;
465 lg->WriteMakeRule(ruleFileStream, doc.c_str(),
466 makeTarget.c_str(), depends, no_commands, true);
469 //----------------------------------------------------------------------------
470 void
471 cmGlobalUnixMakefileGenerator3
472 ::WriteDirectoryRules2(std::ostream& ruleFileStream,
473 cmLocalUnixMakefileGenerator3* lg)
475 // Only subdirectories need these rules.
476 if(!lg->GetParent())
478 return;
481 // Begin the directory-level rules section.
482 std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
483 dir = lg->Convert(dir.c_str(), cmLocalGenerator::HOME_OUTPUT,
484 cmLocalGenerator::MAKEFILE);
485 lg->WriteDivider(ruleFileStream);
486 ruleFileStream
487 << "# Directory level rules for directory "
488 << dir << "\n\n";
490 // Write directory-level rules for "all".
491 this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
493 // Write directory-level rules for "clean".
494 this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false);
496 // Write directory-level rules for "preinstall".
497 this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
501 std::string cmGlobalUnixMakefileGenerator3
502 ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
503 const char* additionalOptions, const char *targetName,
504 const char* config, bool ignoreErrors, bool fast)
506 // Project name and config are not used yet.
507 (void)projectName;
508 (void)config;
510 std::string makeCommand =
511 cmSystemTools::ConvertToUnixOutputPath(makeProgram);
513 // Since we have full control over the invocation of nmake, let us
514 // make it quiet.
515 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
517 makeCommand += " /NOLOGO ";
519 if ( ignoreErrors )
521 makeCommand += " -i";
523 if ( additionalOptions )
525 makeCommand += " ";
526 makeCommand += additionalOptions;
528 if ( targetName && strlen(targetName))
530 cmLocalUnixMakefileGenerator3 *lg;
531 if (this->LocalGenerators.size())
533 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
534 (this->LocalGenerators[0]);
536 else
538 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
539 (this->CreateLocalGenerator());
540 // set the Start directories
541 lg->GetMakefile()->SetStartDirectory
542 (this->CMakeInstance->GetStartDirectory());
543 lg->GetMakefile()->SetStartOutputDirectory
544 (this->CMakeInstance->GetStartOutputDirectory());
545 lg->GetMakefile()->MakeStartDirectoriesCurrent();
548 makeCommand += " \"";
549 std::string tname = targetName;
550 if(fast)
552 tname += "/fast";
554 tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
555 cmLocalGenerator::MAKEFILE);
556 makeCommand += tname.c_str();
557 makeCommand += "\"";
558 if (!this->LocalGenerators.size())
560 delete lg;
563 return makeCommand;
566 //----------------------------------------------------------------------------
567 void
568 cmGlobalUnixMakefileGenerator3
569 ::WriteConvenienceRules(std::ostream& ruleFileStream,
570 std::set<cmStdString> &emitted)
572 std::vector<std::string> depends;
573 std::vector<std::string> commands;
575 depends.push_back("cmake_check_build_system");
577 // write the target convenience rules
578 unsigned int i;
579 cmLocalUnixMakefileGenerator3 *lg;
580 for (i = 0; i < this->LocalGenerators.size(); ++i)
582 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
583 (this->LocalGenerators[i]);
584 // for each target Generate the rule files for each target.
585 cmTargets& targets = lg->GetMakefile()->GetTargets();
586 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
588 // Don't emit the same rule twice (e.g. two targets with the same
589 // simple name)
590 if(t->second.GetName() &&
591 strlen(t->second.GetName()) &&
592 emitted.insert(t->second.GetName()).second &&
593 // Handle user targets here. Global targets are handled in
594 // the local generator on a per-directory basis.
595 ((t->second.GetType() == cmTarget::EXECUTABLE) ||
596 (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
597 (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
598 (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
599 (t->second.GetType() == cmTarget::UTILITY)))
601 // Add a rule to build the target by name.
602 lg->WriteDivider(ruleFileStream);
603 ruleFileStream
604 << "# Target rules for targets named "
605 << t->second.GetName() << "\n\n";
607 // Write the rule.
608 commands.clear();
609 std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
610 tmp += "Makefile2";
611 commands.push_back(lg->GetRecursiveMakeCall
612 (tmp.c_str(),t->second.GetName()));
613 depends.clear();
614 depends.push_back("cmake_check_build_system");
615 lg->WriteMakeRule(ruleFileStream,
616 "Build rule for target.",
617 t->second.GetName(), depends, commands,
618 true);
620 // Add a fast rule to build the target
621 std::string localName = lg->GetRelativeTargetDirectory(t->second);
622 std::string makefileName;
623 makefileName = localName;
624 makefileName += "/build.make";
625 depends.clear();
626 commands.clear();
627 std::string makeTargetName = localName;
628 makeTargetName += "/build";
629 localName = t->second.GetName();
630 localName += "/fast";
631 commands.push_back(lg->GetRecursiveMakeCall
632 (makefileName.c_str(), makeTargetName.c_str()));
633 lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
634 localName.c_str(), depends, commands, true);
636 // Add a local name for the rule to relink the target before
637 // installation.
638 if(t->second.NeedRelinkBeforeInstall())
640 makeTargetName = lg->GetRelativeTargetDirectory(t->second);
641 makeTargetName += "/preinstall";
642 localName = t->second.GetName();
643 localName += "/preinstall";
644 depends.clear();
645 commands.clear();
646 commands.push_back(lg->GetRecursiveMakeCall
647 (makefileName.c_str(), makeTargetName.c_str()));
648 lg->WriteMakeRule(ruleFileStream,
649 "Manual pre-install relink rule for target.",
650 localName.c_str(), depends, commands, true);
658 //----------------------------------------------------------------------------
659 void
660 cmGlobalUnixMakefileGenerator3
661 ::WriteConvenienceRules2(std::ostream& ruleFileStream,
662 cmLocalUnixMakefileGenerator3 *lg)
664 std::vector<std::string> depends;
665 std::vector<std::string> commands;
666 std::string localName;
667 std::string makeTargetName;
670 // write the directory level rules for this local gen
671 this->WriteDirectoryRules2(ruleFileStream,lg);
673 depends.push_back("cmake_check_build_system");
675 // for each target Generate the rule files for each target.
676 cmTargets& targets = lg->GetMakefile()->GetTargets();
677 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
679 if (t->second.GetName()
680 && strlen(t->second.GetName())
681 && ((t->second.GetType() == cmTarget::EXECUTABLE)
682 || (t->second.GetType() == cmTarget::STATIC_LIBRARY)
683 || (t->second.GetType() == cmTarget::SHARED_LIBRARY)
684 || (t->second.GetType() == cmTarget::MODULE_LIBRARY)
685 || (t->second.GetType() == cmTarget::UTILITY)))
687 std::string makefileName;
688 // Add a rule to build the target by name.
689 localName = lg->GetRelativeTargetDirectory(t->second);
690 makefileName = localName;
691 makefileName += "/build.make";
693 bool needRequiresStep = this->NeedRequiresStep(t->second);
695 lg->WriteDivider(ruleFileStream);
696 ruleFileStream
697 << "# Target rules for target "
698 << localName << "\n\n";
700 commands.clear();
701 makeTargetName = localName;
702 makeTargetName += "/depend";
703 commands.push_back(lg->GetRecursiveMakeCall
704 (makefileName.c_str(),makeTargetName.c_str()));
706 // add requires if we need it for this generator
707 if (needRequiresStep)
709 makeTargetName = localName;
710 makeTargetName += "/requires";
711 commands.push_back(lg->GetRecursiveMakeCall
712 (makefileName.c_str(),makeTargetName.c_str()));
714 makeTargetName = localName;
715 makeTargetName += "/build";
716 commands.push_back(lg->GetRecursiveMakeCall
717 (makefileName.c_str(),makeTargetName.c_str()));
719 // Write the rule.
720 localName += "/all";
721 depends.clear();
723 std::string progressDir =
724 lg->GetMakefile()->GetHomeOutputDirectory();
725 progressDir += cmake::GetCMakeFilesDirectory();
727 cmOStringStream progCmd;
728 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
729 // all target counts
730 progCmd << lg->Convert(progressDir.c_str(),
731 cmLocalGenerator::FULL,
732 cmLocalGenerator::SHELL);
733 progCmd << " ";
734 std::vector<int> &progFiles = lg->ProgressFiles[t->first];
735 for (std::vector<int>::iterator i = progFiles.begin();
736 i != progFiles.end(); ++i)
738 progCmd << " " << *i;
740 commands.push_back(progCmd.str());
742 progressDir = "Built target ";
743 progressDir += t->first;
744 lg->AppendEcho(commands,progressDir.c_str());
746 this->AppendGlobalTargetDepends(depends,t->second);
747 lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
748 localName.c_str(), depends, commands, true);
750 // add the all/all dependency
751 if(!this->IsExcluded(this->LocalGenerators[0], t->second))
753 depends.clear();
754 depends.push_back(localName);
755 commands.clear();
756 lg->WriteMakeRule(ruleFileStream, "Include target in all.",
757 "all", depends, commands, true);
760 // Write the rule.
761 commands.clear();
762 progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
763 progressDir += cmake::GetCMakeFilesDirectory();
766 // TODO: Convert the total progress count to a make variable.
767 cmOStringStream progCmd;
768 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
769 // # in target
770 progCmd << lg->Convert(progressDir.c_str(),
771 cmLocalGenerator::FULL,
772 cmLocalGenerator::SHELL);
774 std::set<cmStdString> emitted;
775 progCmd << " "
776 << this->GetTargetTotalNumberOfActions(t->second,
777 emitted);
778 commands.push_back(progCmd.str());
780 std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
781 tmp += "Makefile2";
782 commands.push_back(lg->GetRecursiveMakeCall
783 (tmp.c_str(),localName.c_str()));
785 cmOStringStream progCmd;
786 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
787 progCmd << lg->Convert(progressDir.c_str(),
788 cmLocalGenerator::FULL,
789 cmLocalGenerator::SHELL);
790 progCmd << " 0";
791 commands.push_back(progCmd.str());
793 depends.clear();
794 depends.push_back("cmake_check_build_system");
795 localName = lg->GetRelativeTargetDirectory(t->second);
796 localName += "/rule";
797 lg->WriteMakeRule(ruleFileStream,
798 "Build rule for subdir invocation for target.",
799 localName.c_str(), depends, commands, true);
801 // Add a target with the canonical name (no prefix, suffix or path).
802 commands.clear();
803 depends.clear();
804 depends.push_back(localName);
805 lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
806 t->second.GetName(), depends, commands, true);
808 // Add rules to prepare the target for installation.
809 if(t->second.NeedRelinkBeforeInstall())
811 localName = lg->GetRelativeTargetDirectory(t->second);
812 localName += "/preinstall";
813 depends.clear();
814 commands.clear();
815 commands.push_back(lg->GetRecursiveMakeCall
816 (makefileName.c_str(), localName.c_str()));
817 lg->WriteMakeRule(ruleFileStream,
818 "Pre-install relink rule for target.",
819 localName.c_str(), depends, commands, true);
821 if(!this->IsExcluded(this->LocalGenerators[0], t->second))
823 depends.clear();
824 depends.push_back(localName);
825 commands.clear();
826 lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
827 "preinstall", depends, commands, true);
831 // add the clean rule
832 localName = lg->GetRelativeTargetDirectory(t->second);
833 makeTargetName = localName;
834 makeTargetName += "/clean";
835 depends.clear();
836 commands.clear();
837 commands.push_back(lg->GetRecursiveMakeCall
838 (makefileName.c_str(), makeTargetName.c_str()));
839 lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
840 makeTargetName.c_str(), depends, commands, true);
841 commands.clear();
842 depends.push_back(makeTargetName);
843 lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
844 "clean", depends, commands, true);
849 //----------------------------------------------------------------------------
850 int cmGlobalUnixMakefileGenerator3
851 ::GetTargetTotalNumberOfActions(cmTarget & target,
852 std::set<cmStdString> &emitted)
854 // do not double count
855 int result = 0;
857 if(emitted.insert(target.GetName()).second)
859 cmLocalUnixMakefileGenerator3 *lg =
860 static_cast<cmLocalUnixMakefileGenerator3 *>
861 (target.GetMakefile()->GetLocalGenerator());
862 result = static_cast<int>(lg->ProgressFiles[target.GetName()].size());
864 TargetDependSet & depends = this->GetTargetDirectDepends(target);
866 TargetDependSet::iterator i;
867 for (i = depends.begin(); i != depends.end(); ++i)
869 result += this->GetTargetTotalNumberOfActions(**i, emitted);
873 return result;
876 unsigned long cmGlobalUnixMakefileGenerator3
877 ::GetNumberOfProgressActionsInAll(cmLocalUnixMakefileGenerator3 *lg)
879 unsigned long result = 0;
880 std::set<cmStdString> emitted;
881 std::set<cmTarget *>& targets = this->LocalGeneratorToTargetMap[lg];
882 for(std::set<cmTarget *>::iterator t = targets.begin();
883 t != targets.end(); ++t)
885 result += this->GetTargetTotalNumberOfActions(**t,emitted);
887 return result;
891 //----------------------------------------------------------------------------
892 void
893 cmGlobalUnixMakefileGenerator3
894 ::AppendGlobalTargetDepends(std::vector<std::string>& depends,
895 cmTarget& target)
897 TargetDependSet const& depends_set = this->GetTargetDirectDepends(target);
898 for(TargetDependSet::const_iterator i = depends_set.begin();
899 i != depends_set.end(); ++i)
901 // Create the target-level dependency.
902 cmTarget const* dep = *i;
903 cmLocalUnixMakefileGenerator3* lg3 =
904 static_cast<cmLocalUnixMakefileGenerator3*>
905 (dep->GetMakefile()->GetLocalGenerator());
906 std::string tgtName = lg3->GetRelativeTargetDirectory(*dep);
907 tgtName += "/all";
908 depends.push_back(tgtName);
912 //----------------------------------------------------------------------------
913 void cmGlobalUnixMakefileGenerator3::WriteHelpRule
914 (std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
916 // add the help target
917 std::string path;
918 std::vector<std::string> no_depends;
919 std::vector<std::string> commands;
920 lg->AppendEcho(commands,"The following are some of the valid targets "
921 "for this Makefile:");
922 lg->AppendEcho(commands,"... all (the default if no target is provided)");
923 lg->AppendEcho(commands,"... clean");
924 lg->AppendEcho(commands,"... depend");
926 // Keep track of targets already listed.
927 std::set<cmStdString> emittedTargets;
929 // for each local generator
930 unsigned int i;
931 cmLocalUnixMakefileGenerator3 *lg2;
932 for (i = 0; i < this->LocalGenerators.size(); ++i)
934 lg2 =
935 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
936 // for the passed in makefile or if this is the top Makefile wripte out
937 // the targets
938 if (lg2 == lg || !lg->GetParent())
940 // for each target Generate the rule files for each target.
941 cmTargets& targets = lg2->GetMakefile()->GetTargets();
942 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
944 if((t->second.GetType() == cmTarget::EXECUTABLE) ||
945 (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
946 (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
947 (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
948 (t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
949 (t->second.GetType() == cmTarget::UTILITY))
951 if(emittedTargets.insert(t->second.GetName()).second)
953 path = "... ";
954 path += t->second.GetName();
955 lg->AppendEcho(commands,path.c_str());
959 std::vector<cmStdString> const& localHelp = lg->GetLocalHelp();
960 for(std::vector<cmStdString>::const_iterator o = localHelp.begin();
961 o != localHelp.end(); ++o)
963 path = "... ";
964 path += *o;
965 lg->AppendEcho(commands, path.c_str());
969 lg->WriteMakeRule(ruleFileStream, "Help Target",
970 "help:",
971 no_depends, commands, true);
972 ruleFileStream << "\n\n";
976 bool cmGlobalUnixMakefileGenerator3
977 ::NeedRequiresStep(cmTarget const& target)
979 std::set<cmStdString> languages;
980 target.GetLanguages(languages);
981 for(std::set<cmStdString>::const_iterator l = languages.begin();
982 l != languages.end(); ++l)
984 std::string var = "CMAKE_NEEDS_REQUIRES_STEP_";
985 var += *l;
986 var += "_FLAG";
987 if(target.GetMakefile()->GetDefinition(var.c_str()))
989 return true;
992 return false;