Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmGlobalUnixMakefileGenerator3.cxx
blobbe4cf797db343d3bb5ecc810cfe329bf30df5ec9
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator3
4 Module: $RCSfile: cmGlobalUnixMakefileGenerator3.cxx,v $
5 Language: C++
6 Date: $Date: 2009-02-06 16:18:56 $
7 Version: $Revision: 1.132 $
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";
356 cmakefileStream << " )\n\n";
358 // CMake must rerun if a byproduct is missing.
360 cmakefileStream
361 << "# Byproducts of CMake generate step:\n"
362 << "SET(CMAKE_MAKEFILE_PRODUCTS\n";
363 const std::vector<std::string>& outfiles =
364 lg->GetMakefile()->GetOutputFiles();
365 for(std::vector<std::string>::const_iterator k = outfiles.begin();
366 k != outfiles.end(); ++k)
368 cmakefileStream << " \"" <<
369 lg->Convert(k->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
370 << "\"\n";
372 cmakefileStream << " )\n\n";
375 this->WriteMainCMakefileLanguageRules(cmakefileStream,
376 this->LocalGenerators);
379 void cmGlobalUnixMakefileGenerator3
380 ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
381 std::vector<cmLocalGenerator *> &lGenerators
384 cmLocalUnixMakefileGenerator3 *lg;
386 // now list all the target info files
387 cmakefileStream
388 << "# Dependency information for all targets:\n";
389 cmakefileStream
390 << "SET(CMAKE_DEPEND_INFO_FILES\n";
391 for (unsigned int i = 0; i < lGenerators.size(); ++i)
393 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
394 // for all of out targets
395 for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
396 l != lg->GetMakefile()->GetTargets().end(); l++)
398 if((l->second.GetType() == cmTarget::EXECUTABLE) ||
399 (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
400 (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
401 (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
402 (l->second.GetType() == cmTarget::UTILITY))
404 std::string tname = lg->GetRelativeTargetDirectory(l->second);
405 tname += "/DependInfo.cmake";
406 cmSystemTools::ConvertToUnixSlashes(tname);
407 cmakefileStream << " \"" << tname.c_str() << "\"\n";
411 cmakefileStream << " )\n";
414 //----------------------------------------------------------------------------
415 void
416 cmGlobalUnixMakefileGenerator3
417 ::WriteDirectoryRule2(std::ostream& ruleFileStream,
418 cmLocalUnixMakefileGenerator3* lg,
419 const char* pass, bool check_all,
420 bool check_relink)
422 // Get the relative path to the subdirectory from the top.
423 std::string makeTarget = lg->GetMakefile()->GetStartOutputDirectory();
424 makeTarget += "/";
425 makeTarget += pass;
427 // The directory-level rule should depend on the target-level rules
428 // for all targets in the directory.
429 std::vector<std::string> depends;
430 for(cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
431 l != lg->GetMakefile()->GetTargets().end(); ++l)
433 if((l->second.GetType() == cmTarget::EXECUTABLE) ||
434 (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
435 (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
436 (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
437 (l->second.GetType() == cmTarget::UTILITY))
439 // Add this to the list of depends rules in this directory.
440 if((!check_all || !l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
441 (!check_relink || l->second.NeedRelinkBeforeInstall()))
443 std::string tname = lg->GetRelativeTargetDirectory(l->second);
444 tname += "/";
445 tname += pass;
446 depends.push_back(tname);
451 // The directory-level rule should depend on the directory-level
452 // rules of the subdirectories.
453 for(std::vector<cmLocalGenerator*>::iterator sdi =
454 lg->GetChildren().begin(); sdi != lg->GetChildren().end(); ++sdi)
456 cmLocalUnixMakefileGenerator3* slg =
457 static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
458 std::string subdir = slg->GetMakefile()->GetStartOutputDirectory();
459 subdir += "/";
460 subdir += pass;
461 depends.push_back(subdir);
464 // Work-around for makes that drop rules that have no dependencies
465 // or commands.
466 if(depends.empty() && this->EmptyRuleHackDepends != "")
468 depends.push_back(this->EmptyRuleHackDepends);
471 // Write the rule.
472 std::string doc = "Convenience name for \"";
473 doc += pass;
474 doc += "\" pass in the directory.";
475 std::vector<std::string> no_commands;
476 lg->WriteMakeRule(ruleFileStream, doc.c_str(),
477 makeTarget.c_str(), depends, no_commands, true);
480 //----------------------------------------------------------------------------
481 void
482 cmGlobalUnixMakefileGenerator3
483 ::WriteDirectoryRules2(std::ostream& ruleFileStream,
484 cmLocalUnixMakefileGenerator3* lg)
486 // Only subdirectories need these rules.
487 if(!lg->GetParent())
489 return;
492 // Begin the directory-level rules section.
493 std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
494 dir = lg->Convert(dir.c_str(), cmLocalGenerator::HOME_OUTPUT,
495 cmLocalGenerator::MAKEFILE);
496 lg->WriteDivider(ruleFileStream);
497 ruleFileStream
498 << "# Directory level rules for directory "
499 << dir << "\n\n";
501 // Write directory-level rules for "all".
502 this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
504 // Write directory-level rules for "clean".
505 this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false);
507 // Write directory-level rules for "preinstall".
508 this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
512 std::string cmGlobalUnixMakefileGenerator3
513 ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
514 const char* additionalOptions, const char *targetName,
515 const char* config, bool ignoreErrors, bool fast)
517 // Project name and config are not used yet.
518 (void)projectName;
519 (void)config;
521 std::string makeCommand =
522 cmSystemTools::ConvertToUnixOutputPath(makeProgram);
524 // Since we have full control over the invocation of nmake, let us
525 // make it quiet.
526 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
528 makeCommand += " /NOLOGO ";
530 if ( ignoreErrors )
532 makeCommand += " -i";
534 if ( additionalOptions )
536 makeCommand += " ";
537 makeCommand += additionalOptions;
539 if ( targetName && strlen(targetName))
541 cmLocalUnixMakefileGenerator3 *lg;
542 if (this->LocalGenerators.size())
544 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
545 (this->LocalGenerators[0]);
547 else
549 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
550 (this->CreateLocalGenerator());
551 // set the Start directories
552 lg->GetMakefile()->SetStartDirectory
553 (this->CMakeInstance->GetStartDirectory());
554 lg->GetMakefile()->SetStartOutputDirectory
555 (this->CMakeInstance->GetStartOutputDirectory());
556 lg->GetMakefile()->MakeStartDirectoriesCurrent();
559 makeCommand += " \"";
560 std::string tname = targetName;
561 if(fast)
563 tname += "/fast";
565 tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
566 cmLocalGenerator::MAKEFILE);
567 makeCommand += tname.c_str();
568 makeCommand += "\"";
569 if (!this->LocalGenerators.size())
571 delete lg;
574 return makeCommand;
577 //----------------------------------------------------------------------------
578 void
579 cmGlobalUnixMakefileGenerator3
580 ::WriteConvenienceRules(std::ostream& ruleFileStream,
581 std::set<cmStdString> &emitted)
583 std::vector<std::string> depends;
584 std::vector<std::string> commands;
586 depends.push_back("cmake_check_build_system");
588 // write the target convenience rules
589 unsigned int i;
590 cmLocalUnixMakefileGenerator3 *lg;
591 for (i = 0; i < this->LocalGenerators.size(); ++i)
593 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
594 (this->LocalGenerators[i]);
595 // for each target Generate the rule files for each target.
596 cmTargets& targets = lg->GetMakefile()->GetTargets();
597 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
599 // Don't emit the same rule twice (e.g. two targets with the same
600 // simple name)
601 if(t->second.GetName() &&
602 strlen(t->second.GetName()) &&
603 emitted.insert(t->second.GetName()).second &&
604 // Handle user targets here. Global targets are handled in
605 // the local generator on a per-directory basis.
606 ((t->second.GetType() == cmTarget::EXECUTABLE) ||
607 (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
608 (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
609 (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
610 (t->second.GetType() == cmTarget::UTILITY)))
612 // Add a rule to build the target by name.
613 lg->WriteDivider(ruleFileStream);
614 ruleFileStream
615 << "# Target rules for targets named "
616 << t->second.GetName() << "\n\n";
618 // Write the rule.
619 commands.clear();
620 std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
621 tmp += "Makefile2";
622 commands.push_back(lg->GetRecursiveMakeCall
623 (tmp.c_str(),t->second.GetName()));
624 depends.clear();
625 depends.push_back("cmake_check_build_system");
626 lg->WriteMakeRule(ruleFileStream,
627 "Build rule for target.",
628 t->second.GetName(), depends, commands,
629 true);
631 // Add a fast rule to build the target
632 std::string localName = lg->GetRelativeTargetDirectory(t->second);
633 std::string makefileName;
634 makefileName = localName;
635 makefileName += "/build.make";
636 depends.clear();
637 commands.clear();
638 std::string makeTargetName = localName;
639 makeTargetName += "/build";
640 localName = t->second.GetName();
641 localName += "/fast";
642 commands.push_back(lg->GetRecursiveMakeCall
643 (makefileName.c_str(), makeTargetName.c_str()));
644 lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
645 localName.c_str(), depends, commands, true);
647 // Add a local name for the rule to relink the target before
648 // installation.
649 if(t->second.NeedRelinkBeforeInstall())
651 makeTargetName = lg->GetRelativeTargetDirectory(t->second);
652 makeTargetName += "/preinstall";
653 localName = t->second.GetName();
654 localName += "/preinstall";
655 depends.clear();
656 commands.clear();
657 commands.push_back(lg->GetRecursiveMakeCall
658 (makefileName.c_str(), makeTargetName.c_str()));
659 lg->WriteMakeRule(ruleFileStream,
660 "Manual pre-install relink rule for target.",
661 localName.c_str(), depends, commands, true);
669 //----------------------------------------------------------------------------
670 void
671 cmGlobalUnixMakefileGenerator3
672 ::WriteConvenienceRules2(std::ostream& ruleFileStream,
673 cmLocalUnixMakefileGenerator3 *lg)
675 std::vector<std::string> depends;
676 std::vector<std::string> commands;
677 std::string localName;
678 std::string makeTargetName;
681 // write the directory level rules for this local gen
682 this->WriteDirectoryRules2(ruleFileStream,lg);
684 depends.push_back("cmake_check_build_system");
686 // for each target Generate the rule files for each target.
687 cmTargets& targets = lg->GetMakefile()->GetTargets();
688 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
690 if (t->second.GetName()
691 && strlen(t->second.GetName())
692 && ((t->second.GetType() == cmTarget::EXECUTABLE)
693 || (t->second.GetType() == cmTarget::STATIC_LIBRARY)
694 || (t->second.GetType() == cmTarget::SHARED_LIBRARY)
695 || (t->second.GetType() == cmTarget::MODULE_LIBRARY)
696 || (t->second.GetType() == cmTarget::UTILITY)))
698 std::string makefileName;
699 // Add a rule to build the target by name.
700 localName = lg->GetRelativeTargetDirectory(t->second);
701 makefileName = localName;
702 makefileName += "/build.make";
704 bool needRequiresStep = this->NeedRequiresStep(t->second);
706 lg->WriteDivider(ruleFileStream);
707 ruleFileStream
708 << "# Target rules for target "
709 << localName << "\n\n";
711 commands.clear();
712 makeTargetName = localName;
713 makeTargetName += "/depend";
714 commands.push_back(lg->GetRecursiveMakeCall
715 (makefileName.c_str(),makeTargetName.c_str()));
717 // add requires if we need it for this generator
718 if (needRequiresStep)
720 makeTargetName = localName;
721 makeTargetName += "/requires";
722 commands.push_back(lg->GetRecursiveMakeCall
723 (makefileName.c_str(),makeTargetName.c_str()));
725 makeTargetName = localName;
726 makeTargetName += "/build";
727 commands.push_back(lg->GetRecursiveMakeCall
728 (makefileName.c_str(),makeTargetName.c_str()));
730 // Write the rule.
731 localName += "/all";
732 depends.clear();
734 std::string progressDir =
735 lg->GetMakefile()->GetHomeOutputDirectory();
736 progressDir += cmake::GetCMakeFilesDirectory();
738 cmOStringStream progCmd;
739 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
740 // all target counts
741 progCmd << lg->Convert(progressDir.c_str(),
742 cmLocalGenerator::FULL,
743 cmLocalGenerator::SHELL);
744 progCmd << " ";
745 std::vector<int> &progFiles = lg->ProgressFiles[t->first];
746 for (std::vector<int>::iterator i = progFiles.begin();
747 i != progFiles.end(); ++i)
749 progCmd << " " << *i;
751 commands.push_back(progCmd.str());
753 progressDir = "Built target ";
754 progressDir += t->first;
755 lg->AppendEcho(commands,progressDir.c_str());
757 this->AppendGlobalTargetDepends(depends,t->second);
758 lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
759 localName.c_str(), depends, commands, true);
761 // add the all/all dependency
762 if(!this->IsExcluded(this->LocalGenerators[0], t->second))
764 depends.clear();
765 depends.push_back(localName);
766 commands.clear();
767 lg->WriteMakeRule(ruleFileStream, "Include target in all.",
768 "all", depends, commands, true);
771 // Write the rule.
772 commands.clear();
773 progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
774 progressDir += cmake::GetCMakeFilesDirectory();
777 // TODO: Convert the total progress count to a make variable.
778 cmOStringStream progCmd;
779 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
780 // # in target
781 progCmd << lg->Convert(progressDir.c_str(),
782 cmLocalGenerator::FULL,
783 cmLocalGenerator::SHELL);
785 std::set<cmTarget *> emitted;
786 progCmd << " "
787 << this->GetTargetTotalNumberOfActions(t->second,
788 emitted);
789 commands.push_back(progCmd.str());
791 std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
792 tmp += "Makefile2";
793 commands.push_back(lg->GetRecursiveMakeCall
794 (tmp.c_str(),localName.c_str()));
796 cmOStringStream progCmd;
797 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
798 progCmd << lg->Convert(progressDir.c_str(),
799 cmLocalGenerator::FULL,
800 cmLocalGenerator::SHELL);
801 progCmd << " 0";
802 commands.push_back(progCmd.str());
804 depends.clear();
805 depends.push_back("cmake_check_build_system");
806 localName = lg->GetRelativeTargetDirectory(t->second);
807 localName += "/rule";
808 lg->WriteMakeRule(ruleFileStream,
809 "Build rule for subdir invocation for target.",
810 localName.c_str(), depends, commands, true);
812 // Add a target with the canonical name (no prefix, suffix or path).
813 commands.clear();
814 depends.clear();
815 depends.push_back(localName);
816 lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
817 t->second.GetName(), depends, commands, true);
819 // Add rules to prepare the target for installation.
820 if(t->second.NeedRelinkBeforeInstall())
822 localName = lg->GetRelativeTargetDirectory(t->second);
823 localName += "/preinstall";
824 depends.clear();
825 commands.clear();
826 commands.push_back(lg->GetRecursiveMakeCall
827 (makefileName.c_str(), localName.c_str()));
828 lg->WriteMakeRule(ruleFileStream,
829 "Pre-install relink rule for target.",
830 localName.c_str(), depends, commands, true);
832 if(!this->IsExcluded(this->LocalGenerators[0], t->second))
834 depends.clear();
835 depends.push_back(localName);
836 commands.clear();
837 lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
838 "preinstall", depends, commands, true);
842 // add the clean rule
843 localName = lg->GetRelativeTargetDirectory(t->second);
844 makeTargetName = localName;
845 makeTargetName += "/clean";
846 depends.clear();
847 commands.clear();
848 commands.push_back(lg->GetRecursiveMakeCall
849 (makefileName.c_str(), makeTargetName.c_str()));
850 lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
851 makeTargetName.c_str(), depends, commands, true);
852 commands.clear();
853 depends.push_back(makeTargetName);
854 lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
855 "clean", depends, commands, true);
860 //----------------------------------------------------------------------------
861 int cmGlobalUnixMakefileGenerator3
862 ::GetTargetTotalNumberOfActions(cmTarget &target,
863 std::set<cmTarget *> &emitted)
865 // do not double count
866 int result = 0;
868 if(emitted.insert(&target).second)
870 cmLocalUnixMakefileGenerator3 *lg =
871 static_cast<cmLocalUnixMakefileGenerator3 *>
872 (target.GetMakefile()->GetLocalGenerator());
873 result = static_cast<int>(lg->ProgressFiles[target.GetName()].size());
875 TargetDependSet & depends = this->GetTargetDirectDepends(target);
877 TargetDependSet::iterator i;
878 for (i = depends.begin(); i != depends.end(); ++i)
880 result += this->GetTargetTotalNumberOfActions(**i, emitted);
884 return result;
887 unsigned long cmGlobalUnixMakefileGenerator3
888 ::GetNumberOfProgressActionsInAll(cmLocalUnixMakefileGenerator3 *lg)
890 unsigned long result = 0;
891 std::set<cmTarget *> emitted;
892 std::set<cmTarget *>& targets = this->LocalGeneratorToTargetMap[lg];
893 for(std::set<cmTarget *>::iterator t = targets.begin();
894 t != targets.end(); ++t)
896 result += this->GetTargetTotalNumberOfActions(**t,emitted);
898 return result;
902 //----------------------------------------------------------------------------
903 void
904 cmGlobalUnixMakefileGenerator3
905 ::AppendGlobalTargetDepends(std::vector<std::string>& depends,
906 cmTarget& target)
908 TargetDependSet const& depends_set = this->GetTargetDirectDepends(target);
909 for(TargetDependSet::const_iterator i = depends_set.begin();
910 i != depends_set.end(); ++i)
912 // Create the target-level dependency.
913 cmTarget const* dep = *i;
914 cmLocalUnixMakefileGenerator3* lg3 =
915 static_cast<cmLocalUnixMakefileGenerator3*>
916 (dep->GetMakefile()->GetLocalGenerator());
917 std::string tgtName = lg3->GetRelativeTargetDirectory(*dep);
918 tgtName += "/all";
919 depends.push_back(tgtName);
923 //----------------------------------------------------------------------------
924 void cmGlobalUnixMakefileGenerator3::WriteHelpRule
925 (std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
927 // add the help target
928 std::string path;
929 std::vector<std::string> no_depends;
930 std::vector<std::string> commands;
931 lg->AppendEcho(commands,"The following are some of the valid targets "
932 "for this Makefile:");
933 lg->AppendEcho(commands,"... all (the default if no target is provided)");
934 lg->AppendEcho(commands,"... clean");
935 lg->AppendEcho(commands,"... depend");
937 // Keep track of targets already listed.
938 std::set<cmStdString> emittedTargets;
940 // for each local generator
941 unsigned int i;
942 cmLocalUnixMakefileGenerator3 *lg2;
943 for (i = 0; i < this->LocalGenerators.size(); ++i)
945 lg2 =
946 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
947 // for the passed in makefile or if this is the top Makefile wripte out
948 // the targets
949 if (lg2 == lg || !lg->GetParent())
951 // for each target Generate the rule files for each target.
952 cmTargets& targets = lg2->GetMakefile()->GetTargets();
953 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
955 if((t->second.GetType() == cmTarget::EXECUTABLE) ||
956 (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
957 (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
958 (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
959 (t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
960 (t->second.GetType() == cmTarget::UTILITY))
962 if(emittedTargets.insert(t->second.GetName()).second)
964 path = "... ";
965 path += t->second.GetName();
966 lg->AppendEcho(commands,path.c_str());
972 std::vector<cmStdString> const& localHelp = lg->GetLocalHelp();
973 for(std::vector<cmStdString>::const_iterator o = localHelp.begin();
974 o != localHelp.end(); ++o)
976 path = "... ";
977 path += *o;
978 lg->AppendEcho(commands, path.c_str());
980 lg->WriteMakeRule(ruleFileStream, "Help Target",
981 "help",
982 no_depends, commands, true);
983 ruleFileStream << "\n\n";
987 bool cmGlobalUnixMakefileGenerator3
988 ::NeedRequiresStep(cmTarget const& target)
990 std::set<cmStdString> languages;
991 target.GetLanguages(languages);
992 for(std::set<cmStdString>::const_iterator l = languages.begin();
993 l != languages.end(); ++l)
995 std::string var = "CMAKE_NEEDS_REQUIRES_STEP_";
996 var += *l;
997 var += "_FLAG";
998 if(target.GetMakefile()->GetDefinition(var.c_str()))
1000 return true;
1003 return false;