STYLE: Fix typo in GetFilenameLastExtension docs
[cmake.git] / Source / cmGlobalUnixMakefileGenerator3.cxx
blob1da31bba35bf78c34516447516e0c36dd89781d2
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator3
4 Module: $RCSfile: cmGlobalUnixMakefileGenerator3.cxx,v $
5 Language: C++
6 Date: $Date: 2008-07-03 13:31:29 $
7 Version: $Revision: 1.131 $
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 if(!optional)
64 cmSystemTools::Error(langComp.c_str(),
65 " not set, after EnableLanguage");
67 continue;
69 const char* name = mf->GetRequiredDefinition(langComp.c_str());
70 if(!cmSystemTools::FileIsFullPath(name))
72 path = cmSystemTools::FindProgram(name);
74 else
76 path = name;
78 if((path.size() == 0 || !cmSystemTools::FileExists(path.c_str()))
79 && (optional==false))
81 std::string message = "your ";
82 message += lang;
83 message += " compiler: \"";
84 message += name;
85 message += "\" was not found. Please set ";
86 message += langComp;
87 message += " to a valid compiler path or name.";
88 cmSystemTools::Error(message.c_str());
89 path = name;
91 std::string doc = lang;
92 doc += " compiler.";
93 const char* cname = this->GetCMakeInstance()->
94 GetCacheManager()->GetCacheValue(langComp.c_str());
95 std::string changeVars;
96 if(cname && (path != cname) && (optional==false))
98 const char* cvars =
99 this->GetCMakeInstance()->GetProperty(
100 "__CMAKE_DELETE_CACHE_CHANGE_VARS_");
101 if(cvars)
103 changeVars += cvars;
104 changeVars += ";";
106 changeVars += langComp;
107 changeVars += ";";
108 changeVars += cname;
109 this->GetCMakeInstance()->SetProperty(
110 "__CMAKE_DELETE_CACHE_CHANGE_VARS_",
111 changeVars.c_str());
113 mf->AddCacheDefinition(langComp.c_str(), path.c_str(),
114 doc.c_str(), cmCacheManager::FILEPATH);
118 ///! Create a local generator appropriate to this Global Generator
119 cmLocalGenerator *cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
121 cmLocalGenerator* lg = new cmLocalUnixMakefileGenerator3;
122 lg->SetGlobalGenerator(this);
123 return lg;
126 //----------------------------------------------------------------------------
127 void cmGlobalUnixMakefileGenerator3
128 ::GetDocumentation(cmDocumentationEntry& entry) const
130 entry.Name = this->GetName();
131 entry.Brief = "Generates standard UNIX makefiles.";
132 entry.Full =
133 "A hierarchy of UNIX makefiles is generated into the build tree. Any "
134 "standard UNIX-style make program can build the project through the "
135 "default make target. A \"make install\" target is also provided.";
138 //----------------------------------------------------------------------------
139 void cmGlobalUnixMakefileGenerator3::Generate()
141 // first do superclass method
142 this->cmGlobalGenerator::Generate();
144 // initialize progress
145 unsigned int i;
146 unsigned long total = 0;
147 for (i = 0; i < this->LocalGenerators.size(); ++i)
149 cmLocalUnixMakefileGenerator3 *lg =
150 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
151 total += lg->GetNumberOfProgressActions();
154 // write each target's progress.make this loop is done twice. Bascially the
155 // Generate pass counts all the actions, the first loop below determines
156 // how many actions have progress updates for each target and writes to
157 // corrrect variable values for everything except the all targets. The
158 // second loop actually writes out correct values for the all targets as
159 // well. This is because the all targets require more information that is
160 // computed in the first loop.
161 unsigned long current = 0;
162 for (i = 0; i < this->LocalGenerators.size(); ++i)
164 cmLocalUnixMakefileGenerator3 *lg =
165 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
166 lg->WriteProgressVariables(total,current);
168 for (i = 0; i < this->LocalGenerators.size(); ++i)
170 cmLocalUnixMakefileGenerator3 *lg =
171 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
172 lg->WriteAllProgressVariable();
175 // write the main makefile
176 this->WriteMainMakefile2();
177 this->WriteMainCMakefile();
180 void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
182 // Open the output file. This should not be copy-if-different
183 // because the check-build-system step compares the makefile time to
184 // see if the build system must be regenerated.
185 std::string makefileName =
186 this->GetCMakeInstance()->GetHomeOutputDirectory();
187 makefileName += cmake::GetCMakeFilesDirectory();
188 makefileName += "/Makefile2";
189 cmGeneratedFileStream makefileStream(makefileName.c_str());
190 if(!makefileStream)
192 return;
195 // get a local generator for some useful methods
196 cmLocalUnixMakefileGenerator3 *lg =
197 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
199 // Write the do not edit header.
200 lg->WriteDisclaimer(makefileStream);
202 // Write the main entry point target. This must be the VERY first
203 // target so that make with no arguments will run it.
204 // Just depend on the all target to drive the build.
205 std::vector<std::string> depends;
206 std::vector<std::string> no_commands;
207 depends.push_back("all");
209 // Write the rule.
210 lg->WriteMakeRule(makefileStream,
211 "Default target executed when no arguments are "
212 "given to make.",
213 "default_target",
214 depends,
215 no_commands, true);
217 depends.clear();
219 // The all and preinstall rules might never have any dependencies
220 // added to them.
221 if(this->EmptyRuleHackDepends != "")
223 depends.push_back(this->EmptyRuleHackDepends);
226 // Write and empty all:
227 lg->WriteMakeRule(makefileStream,
228 "The main recursive all target", "all",
229 depends, no_commands, true);
231 // Write an empty preinstall:
232 lg->WriteMakeRule(makefileStream,
233 "The main recursive preinstall target", "preinstall",
234 depends, no_commands, true);
236 // Write out the "special" stuff
237 lg->WriteSpecialTargetsTop(makefileStream);
239 // write the target convenience rules
240 unsigned int i;
241 for (i = 0; i < this->LocalGenerators.size(); ++i)
243 lg =
244 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
245 this->WriteConvenienceRules2(makefileStream,lg);
248 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
249 lg->WriteSpecialTargetsBottom(makefileStream);
253 //----------------------------------------------------------------------------
254 void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
256 // Open the output file. This should not be copy-if-different
257 // because the check-build-system step compares the makefile time to
258 // see if the build system must be regenerated.
259 std::string cmakefileName =
260 this->GetCMakeInstance()->GetHomeOutputDirectory();
261 cmakefileName += cmake::GetCMakeFilesDirectory();
262 cmakefileName += "/Makefile.cmake";
263 cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
264 if(!cmakefileStream)
266 return;
269 std::string makefileName =
270 this->GetCMakeInstance()->GetHomeOutputDirectory();
271 makefileName += "/Makefile";
273 // get a local generator for some useful methods
274 cmLocalUnixMakefileGenerator3 *lg =
275 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
277 // Write the do not edit header.
278 lg->WriteDisclaimer(cmakefileStream);
280 // Save the generator name
281 cmakefileStream
282 << "# The generator used is:\n"
283 << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
285 // for each cmMakefile get its list of dependencies
286 std::vector<std::string> lfiles;
287 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
289 lg =
290 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
292 // Get the list of files contributing to this generation step.
293 lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
294 lg->GetMakefile()->GetListFiles().end());
296 // Sort the list and remove duplicates.
297 std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
298 std::vector<std::string>::iterator new_end =
299 std::unique(lfiles.begin(),lfiles.end());
300 lfiles.erase(new_end, lfiles.end());
302 // reset lg to the first makefile
303 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
305 // Build the path to the cache file.
306 std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
307 cache += "/CMakeCache.txt";
309 // Save the list to the cmake file.
310 cmakefileStream
311 << "# The top level Makefile was generated from the following files:\n"
312 << "SET(CMAKE_MAKEFILE_DEPENDS\n"
313 << " \""
314 << lg->Convert(cache.c_str(),
315 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
316 for(std::vector<std::string>::const_iterator i = lfiles.begin();
317 i != lfiles.end(); ++i)
319 cmakefileStream
320 << " \""
321 << lg->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT).c_str()
322 << "\"\n";
324 cmakefileStream
325 << " )\n\n";
327 // Build the path to the cache check file.
328 std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
329 check += cmake::GetCMakeFilesDirectory();
330 check += "/cmake.check_cache";
332 // Set the corresponding makefile in the cmake file.
333 cmakefileStream
334 << "# The corresponding makefile is:\n"
335 << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
336 << " \""
337 << lg->Convert(makefileName.c_str(),
338 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n"
339 << " \""
340 << lg->Convert(check.c_str(),
341 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
343 // add in all the directory information files
344 std::string tmpStr;
345 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
347 lg =
348 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
349 tmpStr = lg->GetMakefile()->GetStartOutputDirectory();
350 tmpStr += cmake::GetCMakeFilesDirectory();
351 tmpStr += "/CMakeDirectoryInformation.cmake";
352 cmakefileStream << " \"" <<
353 lg->Convert(tmpStr.c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
354 << "\"\n";
355 const std::vector<std::string>& outfiles =
356 lg->GetMakefile()->GetOutputFiles();
357 for(std::vector<std::string>::const_iterator k= outfiles.begin();
358 k != outfiles.end(); ++k)
360 cmakefileStream << " \"" <<
361 lg->Convert(k->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
362 << "\"\n";
365 cmakefileStream << " )\n\n";
367 this->WriteMainCMakefileLanguageRules(cmakefileStream,
368 this->LocalGenerators);
371 void cmGlobalUnixMakefileGenerator3
372 ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
373 std::vector<cmLocalGenerator *> &lGenerators
376 cmLocalUnixMakefileGenerator3 *lg;
378 // now list all the target info files
379 cmakefileStream
380 << "# Dependency information for all targets:\n";
381 cmakefileStream
382 << "SET(CMAKE_DEPEND_INFO_FILES\n";
383 for (unsigned int i = 0; i < lGenerators.size(); ++i)
385 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
386 // for all of out targets
387 for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
388 l != lg->GetMakefile()->GetTargets().end(); l++)
390 if((l->second.GetType() == cmTarget::EXECUTABLE) ||
391 (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
392 (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
393 (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
394 (l->second.GetType() == cmTarget::UTILITY))
396 std::string tname = lg->GetRelativeTargetDirectory(l->second);
397 tname += "/DependInfo.cmake";
398 cmSystemTools::ConvertToUnixSlashes(tname);
399 cmakefileStream << " \"" << tname.c_str() << "\"\n";
403 cmakefileStream << " )\n";
406 //----------------------------------------------------------------------------
407 void
408 cmGlobalUnixMakefileGenerator3
409 ::WriteDirectoryRule2(std::ostream& ruleFileStream,
410 cmLocalUnixMakefileGenerator3* lg,
411 const char* pass, bool check_all,
412 bool check_relink)
414 // Get the relative path to the subdirectory from the top.
415 std::string makeTarget = lg->GetMakefile()->GetStartOutputDirectory();
416 makeTarget += "/";
417 makeTarget += pass;
419 // The directory-level rule should depend on the target-level rules
420 // for all targets in the directory.
421 std::vector<std::string> depends;
422 for(cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
423 l != lg->GetMakefile()->GetTargets().end(); ++l)
425 if((l->second.GetType() == cmTarget::EXECUTABLE) ||
426 (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
427 (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
428 (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
429 (l->second.GetType() == cmTarget::UTILITY))
431 // Add this to the list of depends rules in this directory.
432 if((!check_all || !l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
433 (!check_relink || l->second.NeedRelinkBeforeInstall()))
435 std::string tname = lg->GetRelativeTargetDirectory(l->second);
436 tname += "/";
437 tname += pass;
438 depends.push_back(tname);
443 // The directory-level rule should depend on the directory-level
444 // rules of the subdirectories.
445 for(std::vector<cmLocalGenerator*>::iterator sdi =
446 lg->GetChildren().begin(); sdi != lg->GetChildren().end(); ++sdi)
448 cmLocalUnixMakefileGenerator3* slg =
449 static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
450 std::string subdir = slg->GetMakefile()->GetStartOutputDirectory();
451 subdir += "/";
452 subdir += pass;
453 depends.push_back(subdir);
456 // Work-around for makes that drop rules that have no dependencies
457 // or commands.
458 if(depends.empty() && this->EmptyRuleHackDepends != "")
460 depends.push_back(this->EmptyRuleHackDepends);
463 // Write the rule.
464 std::string doc = "Convenience name for \"";
465 doc += pass;
466 doc += "\" pass in the directory.";
467 std::vector<std::string> no_commands;
468 lg->WriteMakeRule(ruleFileStream, doc.c_str(),
469 makeTarget.c_str(), depends, no_commands, true);
472 //----------------------------------------------------------------------------
473 void
474 cmGlobalUnixMakefileGenerator3
475 ::WriteDirectoryRules2(std::ostream& ruleFileStream,
476 cmLocalUnixMakefileGenerator3* lg)
478 // Only subdirectories need these rules.
479 if(!lg->GetParent())
481 return;
484 // Begin the directory-level rules section.
485 std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
486 dir = lg->Convert(dir.c_str(), cmLocalGenerator::HOME_OUTPUT,
487 cmLocalGenerator::MAKEFILE);
488 lg->WriteDivider(ruleFileStream);
489 ruleFileStream
490 << "# Directory level rules for directory "
491 << dir << "\n\n";
493 // Write directory-level rules for "all".
494 this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
496 // Write directory-level rules for "clean".
497 this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false);
499 // Write directory-level rules for "preinstall".
500 this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
504 std::string cmGlobalUnixMakefileGenerator3
505 ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
506 const char* additionalOptions, const char *targetName,
507 const char* config, bool ignoreErrors, bool fast)
509 // Project name and config are not used yet.
510 (void)projectName;
511 (void)config;
513 std::string makeCommand =
514 cmSystemTools::ConvertToUnixOutputPath(makeProgram);
516 // Since we have full control over the invocation of nmake, let us
517 // make it quiet.
518 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
520 makeCommand += " /NOLOGO ";
522 if ( ignoreErrors )
524 makeCommand += " -i";
526 if ( additionalOptions )
528 makeCommand += " ";
529 makeCommand += additionalOptions;
531 if ( targetName && strlen(targetName))
533 cmLocalUnixMakefileGenerator3 *lg;
534 if (this->LocalGenerators.size())
536 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
537 (this->LocalGenerators[0]);
539 else
541 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
542 (this->CreateLocalGenerator());
543 // set the Start directories
544 lg->GetMakefile()->SetStartDirectory
545 (this->CMakeInstance->GetStartDirectory());
546 lg->GetMakefile()->SetStartOutputDirectory
547 (this->CMakeInstance->GetStartOutputDirectory());
548 lg->GetMakefile()->MakeStartDirectoriesCurrent();
551 makeCommand += " \"";
552 std::string tname = targetName;
553 if(fast)
555 tname += "/fast";
557 tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
558 cmLocalGenerator::MAKEFILE);
559 makeCommand += tname.c_str();
560 makeCommand += "\"";
561 if (!this->LocalGenerators.size())
563 delete lg;
566 return makeCommand;
569 //----------------------------------------------------------------------------
570 void
571 cmGlobalUnixMakefileGenerator3
572 ::WriteConvenienceRules(std::ostream& ruleFileStream,
573 std::set<cmStdString> &emitted)
575 std::vector<std::string> depends;
576 std::vector<std::string> commands;
578 depends.push_back("cmake_check_build_system");
580 // write the target convenience rules
581 unsigned int i;
582 cmLocalUnixMakefileGenerator3 *lg;
583 for (i = 0; i < this->LocalGenerators.size(); ++i)
585 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
586 (this->LocalGenerators[i]);
587 // for each target Generate the rule files for each target.
588 cmTargets& targets = lg->GetMakefile()->GetTargets();
589 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
591 // Don't emit the same rule twice (e.g. two targets with the same
592 // simple name)
593 if(t->second.GetName() &&
594 strlen(t->second.GetName()) &&
595 emitted.insert(t->second.GetName()).second &&
596 // Handle user targets here. Global targets are handled in
597 // the local generator on a per-directory basis.
598 ((t->second.GetType() == cmTarget::EXECUTABLE) ||
599 (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
600 (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
601 (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
602 (t->second.GetType() == cmTarget::UTILITY)))
604 // Add a rule to build the target by name.
605 lg->WriteDivider(ruleFileStream);
606 ruleFileStream
607 << "# Target rules for targets named "
608 << t->second.GetName() << "\n\n";
610 // Write the rule.
611 commands.clear();
612 std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
613 tmp += "Makefile2";
614 commands.push_back(lg->GetRecursiveMakeCall
615 (tmp.c_str(),t->second.GetName()));
616 depends.clear();
617 depends.push_back("cmake_check_build_system");
618 lg->WriteMakeRule(ruleFileStream,
619 "Build rule for target.",
620 t->second.GetName(), depends, commands,
621 true);
623 // Add a fast rule to build the target
624 std::string localName = lg->GetRelativeTargetDirectory(t->second);
625 std::string makefileName;
626 makefileName = localName;
627 makefileName += "/build.make";
628 depends.clear();
629 commands.clear();
630 std::string makeTargetName = localName;
631 makeTargetName += "/build";
632 localName = t->second.GetName();
633 localName += "/fast";
634 commands.push_back(lg->GetRecursiveMakeCall
635 (makefileName.c_str(), makeTargetName.c_str()));
636 lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
637 localName.c_str(), depends, commands, true);
639 // Add a local name for the rule to relink the target before
640 // installation.
641 if(t->second.NeedRelinkBeforeInstall())
643 makeTargetName = lg->GetRelativeTargetDirectory(t->second);
644 makeTargetName += "/preinstall";
645 localName = t->second.GetName();
646 localName += "/preinstall";
647 depends.clear();
648 commands.clear();
649 commands.push_back(lg->GetRecursiveMakeCall
650 (makefileName.c_str(), makeTargetName.c_str()));
651 lg->WriteMakeRule(ruleFileStream,
652 "Manual pre-install relink rule for target.",
653 localName.c_str(), depends, commands, true);
661 //----------------------------------------------------------------------------
662 void
663 cmGlobalUnixMakefileGenerator3
664 ::WriteConvenienceRules2(std::ostream& ruleFileStream,
665 cmLocalUnixMakefileGenerator3 *lg)
667 std::vector<std::string> depends;
668 std::vector<std::string> commands;
669 std::string localName;
670 std::string makeTargetName;
673 // write the directory level rules for this local gen
674 this->WriteDirectoryRules2(ruleFileStream,lg);
676 depends.push_back("cmake_check_build_system");
678 // for each target Generate the rule files for each target.
679 cmTargets& targets = lg->GetMakefile()->GetTargets();
680 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
682 if (t->second.GetName()
683 && strlen(t->second.GetName())
684 && ((t->second.GetType() == cmTarget::EXECUTABLE)
685 || (t->second.GetType() == cmTarget::STATIC_LIBRARY)
686 || (t->second.GetType() == cmTarget::SHARED_LIBRARY)
687 || (t->second.GetType() == cmTarget::MODULE_LIBRARY)
688 || (t->second.GetType() == cmTarget::UTILITY)))
690 std::string makefileName;
691 // Add a rule to build the target by name.
692 localName = lg->GetRelativeTargetDirectory(t->second);
693 makefileName = localName;
694 makefileName += "/build.make";
696 bool needRequiresStep = this->NeedRequiresStep(t->second);
698 lg->WriteDivider(ruleFileStream);
699 ruleFileStream
700 << "# Target rules for target "
701 << localName << "\n\n";
703 commands.clear();
704 makeTargetName = localName;
705 makeTargetName += "/depend";
706 commands.push_back(lg->GetRecursiveMakeCall
707 (makefileName.c_str(),makeTargetName.c_str()));
709 // add requires if we need it for this generator
710 if (needRequiresStep)
712 makeTargetName = localName;
713 makeTargetName += "/requires";
714 commands.push_back(lg->GetRecursiveMakeCall
715 (makefileName.c_str(),makeTargetName.c_str()));
717 makeTargetName = localName;
718 makeTargetName += "/build";
719 commands.push_back(lg->GetRecursiveMakeCall
720 (makefileName.c_str(),makeTargetName.c_str()));
722 // Write the rule.
723 localName += "/all";
724 depends.clear();
726 std::string progressDir =
727 lg->GetMakefile()->GetHomeOutputDirectory();
728 progressDir += cmake::GetCMakeFilesDirectory();
730 cmOStringStream progCmd;
731 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
732 // all target counts
733 progCmd << lg->Convert(progressDir.c_str(),
734 cmLocalGenerator::FULL,
735 cmLocalGenerator::SHELL);
736 progCmd << " ";
737 std::vector<int> &progFiles = lg->ProgressFiles[t->first];
738 for (std::vector<int>::iterator i = progFiles.begin();
739 i != progFiles.end(); ++i)
741 progCmd << " " << *i;
743 commands.push_back(progCmd.str());
745 progressDir = "Built target ";
746 progressDir += t->first;
747 lg->AppendEcho(commands,progressDir.c_str());
749 this->AppendGlobalTargetDepends(depends,t->second);
750 lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
751 localName.c_str(), depends, commands, true);
753 // add the all/all dependency
754 if(!this->IsExcluded(this->LocalGenerators[0], t->second))
756 depends.clear();
757 depends.push_back(localName);
758 commands.clear();
759 lg->WriteMakeRule(ruleFileStream, "Include target in all.",
760 "all", depends, commands, true);
763 // Write the rule.
764 commands.clear();
765 progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
766 progressDir += cmake::GetCMakeFilesDirectory();
769 // TODO: Convert the total progress count to a make variable.
770 cmOStringStream progCmd;
771 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
772 // # in target
773 progCmd << lg->Convert(progressDir.c_str(),
774 cmLocalGenerator::FULL,
775 cmLocalGenerator::SHELL);
777 std::set<cmTarget *> emitted;
778 progCmd << " "
779 << this->GetTargetTotalNumberOfActions(t->second,
780 emitted);
781 commands.push_back(progCmd.str());
783 std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
784 tmp += "Makefile2";
785 commands.push_back(lg->GetRecursiveMakeCall
786 (tmp.c_str(),localName.c_str()));
788 cmOStringStream progCmd;
789 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
790 progCmd << lg->Convert(progressDir.c_str(),
791 cmLocalGenerator::FULL,
792 cmLocalGenerator::SHELL);
793 progCmd << " 0";
794 commands.push_back(progCmd.str());
796 depends.clear();
797 depends.push_back("cmake_check_build_system");
798 localName = lg->GetRelativeTargetDirectory(t->second);
799 localName += "/rule";
800 lg->WriteMakeRule(ruleFileStream,
801 "Build rule for subdir invocation for target.",
802 localName.c_str(), depends, commands, true);
804 // Add a target with the canonical name (no prefix, suffix or path).
805 commands.clear();
806 depends.clear();
807 depends.push_back(localName);
808 lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
809 t->second.GetName(), depends, commands, true);
811 // Add rules to prepare the target for installation.
812 if(t->second.NeedRelinkBeforeInstall())
814 localName = lg->GetRelativeTargetDirectory(t->second);
815 localName += "/preinstall";
816 depends.clear();
817 commands.clear();
818 commands.push_back(lg->GetRecursiveMakeCall
819 (makefileName.c_str(), localName.c_str()));
820 lg->WriteMakeRule(ruleFileStream,
821 "Pre-install relink rule for target.",
822 localName.c_str(), depends, commands, true);
824 if(!this->IsExcluded(this->LocalGenerators[0], t->second))
826 depends.clear();
827 depends.push_back(localName);
828 commands.clear();
829 lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
830 "preinstall", depends, commands, true);
834 // add the clean rule
835 localName = lg->GetRelativeTargetDirectory(t->second);
836 makeTargetName = localName;
837 makeTargetName += "/clean";
838 depends.clear();
839 commands.clear();
840 commands.push_back(lg->GetRecursiveMakeCall
841 (makefileName.c_str(), makeTargetName.c_str()));
842 lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
843 makeTargetName.c_str(), depends, commands, true);
844 commands.clear();
845 depends.push_back(makeTargetName);
846 lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
847 "clean", depends, commands, true);
852 //----------------------------------------------------------------------------
853 int cmGlobalUnixMakefileGenerator3
854 ::GetTargetTotalNumberOfActions(cmTarget &target,
855 std::set<cmTarget *> &emitted)
857 // do not double count
858 int result = 0;
860 if(emitted.insert(&target).second)
862 cmLocalUnixMakefileGenerator3 *lg =
863 static_cast<cmLocalUnixMakefileGenerator3 *>
864 (target.GetMakefile()->GetLocalGenerator());
865 result = static_cast<int>(lg->ProgressFiles[target.GetName()].size());
867 TargetDependSet & depends = this->GetTargetDirectDepends(target);
869 TargetDependSet::iterator i;
870 for (i = depends.begin(); i != depends.end(); ++i)
872 result += this->GetTargetTotalNumberOfActions(**i, emitted);
876 return result;
879 unsigned long cmGlobalUnixMakefileGenerator3
880 ::GetNumberOfProgressActionsInAll(cmLocalUnixMakefileGenerator3 *lg)
882 unsigned long result = 0;
883 std::set<cmTarget *> emitted;
884 std::set<cmTarget *>& targets = this->LocalGeneratorToTargetMap[lg];
885 for(std::set<cmTarget *>::iterator t = targets.begin();
886 t != targets.end(); ++t)
888 result += this->GetTargetTotalNumberOfActions(**t,emitted);
890 return result;
894 //----------------------------------------------------------------------------
895 void
896 cmGlobalUnixMakefileGenerator3
897 ::AppendGlobalTargetDepends(std::vector<std::string>& depends,
898 cmTarget& target)
900 TargetDependSet const& depends_set = this->GetTargetDirectDepends(target);
901 for(TargetDependSet::const_iterator i = depends_set.begin();
902 i != depends_set.end(); ++i)
904 // Create the target-level dependency.
905 cmTarget const* dep = *i;
906 cmLocalUnixMakefileGenerator3* lg3 =
907 static_cast<cmLocalUnixMakefileGenerator3*>
908 (dep->GetMakefile()->GetLocalGenerator());
909 std::string tgtName = lg3->GetRelativeTargetDirectory(*dep);
910 tgtName += "/all";
911 depends.push_back(tgtName);
915 //----------------------------------------------------------------------------
916 void cmGlobalUnixMakefileGenerator3::WriteHelpRule
917 (std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
919 // add the help target
920 std::string path;
921 std::vector<std::string> no_depends;
922 std::vector<std::string> commands;
923 lg->AppendEcho(commands,"The following are some of the valid targets "
924 "for this Makefile:");
925 lg->AppendEcho(commands,"... all (the default if no target is provided)");
926 lg->AppendEcho(commands,"... clean");
927 lg->AppendEcho(commands,"... depend");
929 // Keep track of targets already listed.
930 std::set<cmStdString> emittedTargets;
932 // for each local generator
933 unsigned int i;
934 cmLocalUnixMakefileGenerator3 *lg2;
935 for (i = 0; i < this->LocalGenerators.size(); ++i)
937 lg2 =
938 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
939 // for the passed in makefile or if this is the top Makefile wripte out
940 // the targets
941 if (lg2 == lg || !lg->GetParent())
943 // for each target Generate the rule files for each target.
944 cmTargets& targets = lg2->GetMakefile()->GetTargets();
945 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
947 if((t->second.GetType() == cmTarget::EXECUTABLE) ||
948 (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
949 (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
950 (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
951 (t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
952 (t->second.GetType() == cmTarget::UTILITY))
954 if(emittedTargets.insert(t->second.GetName()).second)
956 path = "... ";
957 path += t->second.GetName();
958 lg->AppendEcho(commands,path.c_str());
964 std::vector<cmStdString> const& localHelp = lg->GetLocalHelp();
965 for(std::vector<cmStdString>::const_iterator o = localHelp.begin();
966 o != localHelp.end(); ++o)
968 path = "... ";
969 path += *o;
970 lg->AppendEcho(commands, path.c_str());
972 lg->WriteMakeRule(ruleFileStream, "Help Target",
973 "help",
974 no_depends, commands, true);
975 ruleFileStream << "\n\n";
979 bool cmGlobalUnixMakefileGenerator3
980 ::NeedRequiresStep(cmTarget const& target)
982 std::set<cmStdString> languages;
983 target.GetLanguages(languages);
984 for(std::set<cmStdString>::const_iterator l = languages.begin();
985 l != languages.end(); ++l)
987 std::string var = "CMAKE_NEEDS_REQUIRES_STEP_";
988 var += *l;
989 var += "_FLAG";
990 if(target.GetMakefile()->GetDefinition(var.c_str()))
992 return true;
995 return false;