ENH: put the 64 bit paths first
[cmake.git] / Source / cmGlobalUnixMakefileGenerator3.cxx
blob751425b89aff274ed3c4e6e2a34a59a2deebc330
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator3
4 Module: $RCSfile: cmGlobalUnixMakefileGenerator3.cxx,v $
5 Language: C++
6 Date: $Date: 2009-06-10 17:04:04 $
7 Version: $Revision: 1.135 $
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 #if defined(_WIN32) || defined(__VMS)
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 std::string cnameString = cname;
99 std::string pathString = path;
100 // get rid of potentially multiple slashes:
101 cmSystemTools::ConvertToUnixSlashes(cnameString);
102 cmSystemTools::ConvertToUnixSlashes(pathString);
103 if (cnameString != pathString)
105 const char* cvars =
106 this->GetCMakeInstance()->GetProperty(
107 "__CMAKE_DELETE_CACHE_CHANGE_VARS_");
108 if(cvars)
110 changeVars += cvars;
111 changeVars += ";";
113 changeVars += langComp;
114 changeVars += ";";
115 changeVars += cname;
116 this->GetCMakeInstance()->SetProperty(
117 "__CMAKE_DELETE_CACHE_CHANGE_VARS_",
118 changeVars.c_str());
121 mf->AddCacheDefinition(langComp.c_str(), path.c_str(),
122 doc.c_str(), cmCacheManager::FILEPATH);
126 ///! Create a local generator appropriate to this Global Generator
127 cmLocalGenerator *cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
129 cmLocalGenerator* lg = new cmLocalUnixMakefileGenerator3;
130 lg->SetGlobalGenerator(this);
131 return lg;
134 //----------------------------------------------------------------------------
135 void cmGlobalUnixMakefileGenerator3
136 ::GetDocumentation(cmDocumentationEntry& entry) const
138 entry.Name = this->GetName();
139 entry.Brief = "Generates standard UNIX makefiles.";
140 entry.Full =
141 "A hierarchy of UNIX makefiles is generated into the build tree. Any "
142 "standard UNIX-style make program can build the project through the "
143 "default make target. A \"make install\" target is also provided.";
146 //----------------------------------------------------------------------------
147 void cmGlobalUnixMakefileGenerator3::Generate()
149 // first do superclass method
150 this->cmGlobalGenerator::Generate();
152 // initialize progress
153 unsigned int i;
154 unsigned long total = 0;
155 for (i = 0; i < this->LocalGenerators.size(); ++i)
157 cmLocalUnixMakefileGenerator3 *lg =
158 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
159 total += lg->GetNumberOfProgressActions();
162 // write each target's progress.make this loop is done twice. Bascially the
163 // Generate pass counts all the actions, the first loop below determines
164 // how many actions have progress updates for each target and writes to
165 // corrrect variable values for everything except the all targets. The
166 // second loop actually writes out correct values for the all targets as
167 // well. This is because the all targets require more information that is
168 // computed in the first loop.
169 unsigned long current = 0;
170 for (i = 0; i < this->LocalGenerators.size(); ++i)
172 cmLocalUnixMakefileGenerator3 *lg =
173 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
174 lg->WriteProgressVariables(total,current);
176 for (i = 0; i < this->LocalGenerators.size(); ++i)
178 cmLocalUnixMakefileGenerator3 *lg =
179 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
180 lg->WriteAllProgressVariable();
183 // write the main makefile
184 this->WriteMainMakefile2();
185 this->WriteMainCMakefile();
188 void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
190 // Open the output file. This should not be copy-if-different
191 // because the check-build-system step compares the makefile time to
192 // see if the build system must be regenerated.
193 std::string makefileName =
194 this->GetCMakeInstance()->GetHomeOutputDirectory();
195 makefileName += cmake::GetCMakeFilesDirectory();
196 makefileName += "/Makefile2";
197 cmGeneratedFileStream makefileStream(makefileName.c_str());
198 if(!makefileStream)
200 return;
203 // get a local generator for some useful methods
204 cmLocalUnixMakefileGenerator3 *lg =
205 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
207 // Write the do not edit header.
208 lg->WriteDisclaimer(makefileStream);
210 // Write the main entry point target. This must be the VERY first
211 // target so that make with no arguments will run it.
212 // Just depend on the all target to drive the build.
213 std::vector<std::string> depends;
214 std::vector<std::string> no_commands;
215 depends.push_back("all");
217 // Write the rule.
218 lg->WriteMakeRule(makefileStream,
219 "Default target executed when no arguments are "
220 "given to make.",
221 "default_target",
222 depends,
223 no_commands, true);
225 depends.clear();
227 // The all and preinstall rules might never have any dependencies
228 // added to them.
229 if(this->EmptyRuleHackDepends != "")
231 depends.push_back(this->EmptyRuleHackDepends);
234 // Write and empty all:
235 lg->WriteMakeRule(makefileStream,
236 "The main recursive all target", "all",
237 depends, no_commands, true);
239 // Write an empty preinstall:
240 lg->WriteMakeRule(makefileStream,
241 "The main recursive preinstall target", "preinstall",
242 depends, no_commands, true);
244 // Write out the "special" stuff
245 lg->WriteSpecialTargetsTop(makefileStream);
247 // write the target convenience rules
248 unsigned int i;
249 for (i = 0; i < this->LocalGenerators.size(); ++i)
251 lg =
252 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
253 this->WriteConvenienceRules2(makefileStream,lg);
256 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
257 lg->WriteSpecialTargetsBottom(makefileStream);
261 //----------------------------------------------------------------------------
262 void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
264 // Open the output file. This should not be copy-if-different
265 // because the check-build-system step compares the makefile time to
266 // see if the build system must be regenerated.
267 std::string cmakefileName =
268 this->GetCMakeInstance()->GetHomeOutputDirectory();
269 cmakefileName += cmake::GetCMakeFilesDirectory();
270 cmakefileName += "/Makefile.cmake";
271 cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
272 if(!cmakefileStream)
274 return;
277 std::string makefileName =
278 this->GetCMakeInstance()->GetHomeOutputDirectory();
279 makefileName += "/Makefile";
281 // get a local generator for some useful methods
282 cmLocalUnixMakefileGenerator3 *lg =
283 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
285 // Write the do not edit header.
286 lg->WriteDisclaimer(cmakefileStream);
288 // Save the generator name
289 cmakefileStream
290 << "# The generator used is:\n"
291 << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
293 // for each cmMakefile get its list of dependencies
294 std::vector<std::string> lfiles;
295 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
297 lg =
298 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
300 // Get the list of files contributing to this generation step.
301 lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
302 lg->GetMakefile()->GetListFiles().end());
304 // Sort the list and remove duplicates.
305 std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
306 #if !defined(__VMS) // The Compaq STL on VMS crashes, so accept duplicates.
307 std::vector<std::string>::iterator new_end =
308 std::unique(lfiles.begin(),lfiles.end());
309 lfiles.erase(new_end, lfiles.end());
310 #endif
312 // reset lg to the first makefile
313 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
315 // Build the path to the cache file.
316 std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
317 cache += "/CMakeCache.txt";
319 // Save the list to the cmake file.
320 cmakefileStream
321 << "# The top level Makefile was generated from the following files:\n"
322 << "SET(CMAKE_MAKEFILE_DEPENDS\n"
323 << " \""
324 << lg->Convert(cache.c_str(),
325 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
326 for(std::vector<std::string>::const_iterator i = lfiles.begin();
327 i != lfiles.end(); ++i)
329 cmakefileStream
330 << " \""
331 << lg->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT).c_str()
332 << "\"\n";
334 cmakefileStream
335 << " )\n\n";
337 // Build the path to the cache check file.
338 std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
339 check += cmake::GetCMakeFilesDirectory();
340 check += "/cmake.check_cache";
342 // Set the corresponding makefile in the cmake file.
343 cmakefileStream
344 << "# The corresponding makefile is:\n"
345 << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
346 << " \""
347 << lg->Convert(makefileName.c_str(),
348 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n"
349 << " \""
350 << lg->Convert(check.c_str(),
351 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
353 // add in all the directory information files
354 std::string tmpStr;
355 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
357 lg =
358 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
359 tmpStr = lg->GetMakefile()->GetStartOutputDirectory();
360 tmpStr += cmake::GetCMakeFilesDirectory();
361 tmpStr += "/CMakeDirectoryInformation.cmake";
362 cmakefileStream << " \"" <<
363 lg->Convert(tmpStr.c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
364 << "\"\n";
366 cmakefileStream << " )\n\n";
368 // CMake must rerun if a byproduct is missing.
370 cmakefileStream
371 << "# Byproducts of CMake generate step:\n"
372 << "SET(CMAKE_MAKEFILE_PRODUCTS\n";
373 const std::vector<std::string>& outfiles =
374 lg->GetMakefile()->GetOutputFiles();
375 for(std::vector<std::string>::const_iterator k = outfiles.begin();
376 k != outfiles.end(); ++k)
378 cmakefileStream << " \"" <<
379 lg->Convert(k->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
380 << "\"\n";
382 cmakefileStream << " )\n\n";
385 this->WriteMainCMakefileLanguageRules(cmakefileStream,
386 this->LocalGenerators);
389 void cmGlobalUnixMakefileGenerator3
390 ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
391 std::vector<cmLocalGenerator *> &lGenerators
394 cmLocalUnixMakefileGenerator3 *lg;
396 // now list all the target info files
397 cmakefileStream
398 << "# Dependency information for all targets:\n";
399 cmakefileStream
400 << "SET(CMAKE_DEPEND_INFO_FILES\n";
401 for (unsigned int i = 0; i < lGenerators.size(); ++i)
403 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
404 // for all of out targets
405 for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
406 l != lg->GetMakefile()->GetTargets().end(); l++)
408 if((l->second.GetType() == cmTarget::EXECUTABLE) ||
409 (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
410 (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
411 (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
412 (l->second.GetType() == cmTarget::UTILITY))
414 std::string tname = lg->GetRelativeTargetDirectory(l->second);
415 tname += "/DependInfo.cmake";
416 cmSystemTools::ConvertToUnixSlashes(tname);
417 cmakefileStream << " \"" << tname.c_str() << "\"\n";
421 cmakefileStream << " )\n";
424 //----------------------------------------------------------------------------
425 void
426 cmGlobalUnixMakefileGenerator3
427 ::WriteDirectoryRule2(std::ostream& ruleFileStream,
428 cmLocalUnixMakefileGenerator3* lg,
429 const char* pass, bool check_all,
430 bool check_relink)
432 // Get the relative path to the subdirectory from the top.
433 std::string makeTarget = lg->GetMakefile()->GetStartOutputDirectory();
434 makeTarget += "/";
435 makeTarget += pass;
437 // The directory-level rule should depend on the target-level rules
438 // for all targets in the directory.
439 std::vector<std::string> depends;
440 for(cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
441 l != lg->GetMakefile()->GetTargets().end(); ++l)
443 if((l->second.GetType() == cmTarget::EXECUTABLE) ||
444 (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
445 (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
446 (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
447 (l->second.GetType() == cmTarget::UTILITY))
449 // Add this to the list of depends rules in this directory.
450 if((!check_all || !l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
451 (!check_relink || l->second.NeedRelinkBeforeInstall()))
453 std::string tname = lg->GetRelativeTargetDirectory(l->second);
454 tname += "/";
455 tname += pass;
456 depends.push_back(tname);
461 // The directory-level rule should depend on the directory-level
462 // rules of the subdirectories.
463 for(std::vector<cmLocalGenerator*>::iterator sdi =
464 lg->GetChildren().begin(); sdi != lg->GetChildren().end(); ++sdi)
466 cmLocalUnixMakefileGenerator3* slg =
467 static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
468 std::string subdir = slg->GetMakefile()->GetStartOutputDirectory();
469 subdir += "/";
470 subdir += pass;
471 depends.push_back(subdir);
474 // Work-around for makes that drop rules that have no dependencies
475 // or commands.
476 if(depends.empty() && this->EmptyRuleHackDepends != "")
478 depends.push_back(this->EmptyRuleHackDepends);
481 // Write the rule.
482 std::string doc = "Convenience name for \"";
483 doc += pass;
484 doc += "\" pass in the directory.";
485 std::vector<std::string> no_commands;
486 lg->WriteMakeRule(ruleFileStream, doc.c_str(),
487 makeTarget.c_str(), depends, no_commands, true);
490 //----------------------------------------------------------------------------
491 void
492 cmGlobalUnixMakefileGenerator3
493 ::WriteDirectoryRules2(std::ostream& ruleFileStream,
494 cmLocalUnixMakefileGenerator3* lg)
496 // Only subdirectories need these rules.
497 if(!lg->GetParent())
499 return;
502 // Begin the directory-level rules section.
503 std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
504 dir = lg->Convert(dir.c_str(), cmLocalGenerator::HOME_OUTPUT,
505 cmLocalGenerator::MAKEFILE);
506 lg->WriteDivider(ruleFileStream);
507 ruleFileStream
508 << "# Directory level rules for directory "
509 << dir << "\n\n";
511 // Write directory-level rules for "all".
512 this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
514 // Write directory-level rules for "clean".
515 this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false);
517 // Write directory-level rules for "preinstall".
518 this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
522 std::string cmGlobalUnixMakefileGenerator3
523 ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
524 const char* additionalOptions, const char *targetName,
525 const char* config, bool ignoreErrors, bool fast)
527 // Project name and config are not used yet.
528 (void)projectName;
529 (void)config;
531 std::string makeCommand =
532 cmSystemTools::ConvertToUnixOutputPath(makeProgram);
534 // Since we have full control over the invocation of nmake, let us
535 // make it quiet.
536 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
538 makeCommand += " /NOLOGO ";
540 if ( ignoreErrors )
542 makeCommand += " -i";
544 if ( additionalOptions )
546 makeCommand += " ";
547 makeCommand += additionalOptions;
549 if ( targetName && strlen(targetName))
551 cmLocalUnixMakefileGenerator3 *lg;
552 if (this->LocalGenerators.size())
554 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
555 (this->LocalGenerators[0]);
557 else
559 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
560 (this->CreateLocalGenerator());
561 // set the Start directories
562 lg->GetMakefile()->SetStartDirectory
563 (this->CMakeInstance->GetStartDirectory());
564 lg->GetMakefile()->SetStartOutputDirectory
565 (this->CMakeInstance->GetStartOutputDirectory());
566 lg->GetMakefile()->MakeStartDirectoriesCurrent();
569 makeCommand += " \"";
570 std::string tname = targetName;
571 if(fast)
573 tname += "/fast";
575 tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
576 cmLocalGenerator::MAKEFILE);
577 makeCommand += tname.c_str();
578 makeCommand += "\"";
579 if (!this->LocalGenerators.size())
581 delete lg;
584 return makeCommand;
587 //----------------------------------------------------------------------------
588 void
589 cmGlobalUnixMakefileGenerator3
590 ::WriteConvenienceRules(std::ostream& ruleFileStream,
591 std::set<cmStdString> &emitted)
593 std::vector<std::string> depends;
594 std::vector<std::string> commands;
596 depends.push_back("cmake_check_build_system");
598 // write the target convenience rules
599 unsigned int i;
600 cmLocalUnixMakefileGenerator3 *lg;
601 for (i = 0; i < this->LocalGenerators.size(); ++i)
603 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
604 (this->LocalGenerators[i]);
605 // for each target Generate the rule files for each target.
606 cmTargets& targets = lg->GetMakefile()->GetTargets();
607 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
609 // Don't emit the same rule twice (e.g. two targets with the same
610 // simple name)
611 if(t->second.GetName() &&
612 strlen(t->second.GetName()) &&
613 emitted.insert(t->second.GetName()).second &&
614 // Handle user targets here. Global targets are handled in
615 // the local generator on a per-directory basis.
616 ((t->second.GetType() == cmTarget::EXECUTABLE) ||
617 (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
618 (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
619 (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
620 (t->second.GetType() == cmTarget::UTILITY)))
622 // Add a rule to build the target by name.
623 lg->WriteDivider(ruleFileStream);
624 ruleFileStream
625 << "# Target rules for targets named "
626 << t->second.GetName() << "\n\n";
628 // Write the rule.
629 commands.clear();
630 std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
631 tmp += "Makefile2";
632 commands.push_back(lg->GetRecursiveMakeCall
633 (tmp.c_str(),t->second.GetName()));
634 depends.clear();
635 depends.push_back("cmake_check_build_system");
636 lg->WriteMakeRule(ruleFileStream,
637 "Build rule for target.",
638 t->second.GetName(), depends, commands,
639 true);
641 // Add a fast rule to build the target
642 std::string localName = lg->GetRelativeTargetDirectory(t->second);
643 std::string makefileName;
644 makefileName = localName;
645 makefileName += "/build.make";
646 depends.clear();
647 commands.clear();
648 std::string makeTargetName = localName;
649 makeTargetName += "/build";
650 localName = t->second.GetName();
651 localName += "/fast";
652 commands.push_back(lg->GetRecursiveMakeCall
653 (makefileName.c_str(), makeTargetName.c_str()));
654 lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
655 localName.c_str(), depends, commands, true);
657 // Add a local name for the rule to relink the target before
658 // installation.
659 if(t->second.NeedRelinkBeforeInstall())
661 makeTargetName = lg->GetRelativeTargetDirectory(t->second);
662 makeTargetName += "/preinstall";
663 localName = t->second.GetName();
664 localName += "/preinstall";
665 depends.clear();
666 commands.clear();
667 commands.push_back(lg->GetRecursiveMakeCall
668 (makefileName.c_str(), makeTargetName.c_str()));
669 lg->WriteMakeRule(ruleFileStream,
670 "Manual pre-install relink rule for target.",
671 localName.c_str(), depends, commands, true);
679 //----------------------------------------------------------------------------
680 void
681 cmGlobalUnixMakefileGenerator3
682 ::WriteConvenienceRules2(std::ostream& ruleFileStream,
683 cmLocalUnixMakefileGenerator3 *lg)
685 std::vector<std::string> depends;
686 std::vector<std::string> commands;
687 std::string localName;
688 std::string makeTargetName;
691 // write the directory level rules for this local gen
692 this->WriteDirectoryRules2(ruleFileStream,lg);
694 depends.push_back("cmake_check_build_system");
696 // for each target Generate the rule files for each target.
697 cmTargets& targets = lg->GetMakefile()->GetTargets();
698 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
700 if (t->second.GetName()
701 && strlen(t->second.GetName())
702 && ((t->second.GetType() == cmTarget::EXECUTABLE)
703 || (t->second.GetType() == cmTarget::STATIC_LIBRARY)
704 || (t->second.GetType() == cmTarget::SHARED_LIBRARY)
705 || (t->second.GetType() == cmTarget::MODULE_LIBRARY)
706 || (t->second.GetType() == cmTarget::UTILITY)))
708 std::string makefileName;
709 // Add a rule to build the target by name.
710 localName = lg->GetRelativeTargetDirectory(t->second);
711 makefileName = localName;
712 makefileName += "/build.make";
714 bool needRequiresStep = this->NeedRequiresStep(t->second);
716 lg->WriteDivider(ruleFileStream);
717 ruleFileStream
718 << "# Target rules for target "
719 << localName << "\n\n";
721 commands.clear();
722 makeTargetName = localName;
723 makeTargetName += "/depend";
724 commands.push_back(lg->GetRecursiveMakeCall
725 (makefileName.c_str(),makeTargetName.c_str()));
727 // add requires if we need it for this generator
728 if (needRequiresStep)
730 makeTargetName = localName;
731 makeTargetName += "/requires";
732 commands.push_back(lg->GetRecursiveMakeCall
733 (makefileName.c_str(),makeTargetName.c_str()));
735 makeTargetName = localName;
736 makeTargetName += "/build";
737 commands.push_back(lg->GetRecursiveMakeCall
738 (makefileName.c_str(),makeTargetName.c_str()));
740 // Write the rule.
741 localName += "/all";
742 depends.clear();
744 std::string progressDir =
745 lg->GetMakefile()->GetHomeOutputDirectory();
746 progressDir += cmake::GetCMakeFilesDirectory();
748 cmOStringStream progCmd;
749 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
750 // all target counts
751 progCmd << lg->Convert(progressDir.c_str(),
752 cmLocalGenerator::FULL,
753 cmLocalGenerator::SHELL);
754 progCmd << " ";
755 std::vector<int> &progFiles = lg->ProgressFiles[t->first];
756 for (std::vector<int>::iterator i = progFiles.begin();
757 i != progFiles.end(); ++i)
759 progCmd << " " << *i;
761 commands.push_back(progCmd.str());
763 progressDir = "Built target ";
764 progressDir += t->first;
765 lg->AppendEcho(commands,progressDir.c_str());
767 this->AppendGlobalTargetDepends(depends,t->second);
768 lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
769 localName.c_str(), depends, commands, true);
771 // add the all/all dependency
772 if(!this->IsExcluded(this->LocalGenerators[0], t->second))
774 depends.clear();
775 depends.push_back(localName);
776 commands.clear();
777 lg->WriteMakeRule(ruleFileStream, "Include target in all.",
778 "all", depends, commands, true);
781 // Write the rule.
782 commands.clear();
783 progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
784 progressDir += cmake::GetCMakeFilesDirectory();
787 // TODO: Convert the total progress count to a make variable.
788 cmOStringStream progCmd;
789 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
790 // # in target
791 progCmd << lg->Convert(progressDir.c_str(),
792 cmLocalGenerator::FULL,
793 cmLocalGenerator::SHELL);
795 std::set<cmTarget *> emitted;
796 progCmd << " "
797 << this->GetTargetTotalNumberOfActions(t->second,
798 emitted);
799 commands.push_back(progCmd.str());
801 std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
802 tmp += "Makefile2";
803 commands.push_back(lg->GetRecursiveMakeCall
804 (tmp.c_str(),localName.c_str()));
806 cmOStringStream progCmd;
807 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
808 progCmd << lg->Convert(progressDir.c_str(),
809 cmLocalGenerator::FULL,
810 cmLocalGenerator::SHELL);
811 progCmd << " 0";
812 commands.push_back(progCmd.str());
814 depends.clear();
815 depends.push_back("cmake_check_build_system");
816 localName = lg->GetRelativeTargetDirectory(t->second);
817 localName += "/rule";
818 lg->WriteMakeRule(ruleFileStream,
819 "Build rule for subdir invocation for target.",
820 localName.c_str(), depends, commands, true);
822 // Add a target with the canonical name (no prefix, suffix or path).
823 commands.clear();
824 depends.clear();
825 depends.push_back(localName);
826 lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
827 t->second.GetName(), depends, commands, true);
829 // Add rules to prepare the target for installation.
830 if(t->second.NeedRelinkBeforeInstall())
832 localName = lg->GetRelativeTargetDirectory(t->second);
833 localName += "/preinstall";
834 depends.clear();
835 commands.clear();
836 commands.push_back(lg->GetRecursiveMakeCall
837 (makefileName.c_str(), localName.c_str()));
838 lg->WriteMakeRule(ruleFileStream,
839 "Pre-install relink rule for target.",
840 localName.c_str(), depends, commands, true);
842 if(!this->IsExcluded(this->LocalGenerators[0], t->second))
844 depends.clear();
845 depends.push_back(localName);
846 commands.clear();
847 lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
848 "preinstall", depends, commands, true);
852 // add the clean rule
853 localName = lg->GetRelativeTargetDirectory(t->second);
854 makeTargetName = localName;
855 makeTargetName += "/clean";
856 depends.clear();
857 commands.clear();
858 commands.push_back(lg->GetRecursiveMakeCall
859 (makefileName.c_str(), makeTargetName.c_str()));
860 lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
861 makeTargetName.c_str(), depends, commands, true);
862 commands.clear();
863 depends.push_back(makeTargetName);
864 lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
865 "clean", depends, commands, true);
870 //----------------------------------------------------------------------------
871 int cmGlobalUnixMakefileGenerator3
872 ::GetTargetTotalNumberOfActions(cmTarget &target,
873 std::set<cmTarget *> &emitted)
875 // do not double count
876 int result = 0;
878 if(emitted.insert(&target).second)
880 cmLocalUnixMakefileGenerator3 *lg =
881 static_cast<cmLocalUnixMakefileGenerator3 *>
882 (target.GetMakefile()->GetLocalGenerator());
883 result = static_cast<int>(lg->ProgressFiles[target.GetName()].size());
885 TargetDependSet & depends = this->GetTargetDirectDepends(target);
887 TargetDependSet::iterator i;
888 for (i = depends.begin(); i != depends.end(); ++i)
890 result += this->GetTargetTotalNumberOfActions(**i, emitted);
894 return result;
897 unsigned long cmGlobalUnixMakefileGenerator3
898 ::GetNumberOfProgressActionsInAll(cmLocalUnixMakefileGenerator3 *lg)
900 unsigned long result = 0;
901 std::set<cmTarget *> emitted;
902 std::set<cmTarget *>& targets = this->LocalGeneratorToTargetMap[lg];
903 for(std::set<cmTarget *>::iterator t = targets.begin();
904 t != targets.end(); ++t)
906 result += this->GetTargetTotalNumberOfActions(**t,emitted);
908 return result;
912 //----------------------------------------------------------------------------
913 void
914 cmGlobalUnixMakefileGenerator3
915 ::AppendGlobalTargetDepends(std::vector<std::string>& depends,
916 cmTarget& target)
918 TargetDependSet const& depends_set = this->GetTargetDirectDepends(target);
919 for(TargetDependSet::const_iterator i = depends_set.begin();
920 i != depends_set.end(); ++i)
922 // Create the target-level dependency.
923 cmTarget const* dep = *i;
924 cmLocalUnixMakefileGenerator3* lg3 =
925 static_cast<cmLocalUnixMakefileGenerator3*>
926 (dep->GetMakefile()->GetLocalGenerator());
927 std::string tgtName = lg3->GetRelativeTargetDirectory(*dep);
928 tgtName += "/all";
929 depends.push_back(tgtName);
933 //----------------------------------------------------------------------------
934 void cmGlobalUnixMakefileGenerator3::WriteHelpRule
935 (std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
937 // add the help target
938 std::string path;
939 std::vector<std::string> no_depends;
940 std::vector<std::string> commands;
941 lg->AppendEcho(commands,"The following are some of the valid targets "
942 "for this Makefile:");
943 lg->AppendEcho(commands,"... all (the default if no target is provided)");
944 lg->AppendEcho(commands,"... clean");
945 lg->AppendEcho(commands,"... depend");
947 // Keep track of targets already listed.
948 std::set<cmStdString> emittedTargets;
950 // for each local generator
951 unsigned int i;
952 cmLocalUnixMakefileGenerator3 *lg2;
953 for (i = 0; i < this->LocalGenerators.size(); ++i)
955 lg2 =
956 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
957 // for the passed in makefile or if this is the top Makefile wripte out
958 // the targets
959 if (lg2 == lg || !lg->GetParent())
961 // for each target Generate the rule files for each target.
962 cmTargets& targets = lg2->GetMakefile()->GetTargets();
963 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
965 if((t->second.GetType() == cmTarget::EXECUTABLE) ||
966 (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
967 (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
968 (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
969 (t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
970 (t->second.GetType() == cmTarget::UTILITY))
972 if(emittedTargets.insert(t->second.GetName()).second)
974 path = "... ";
975 path += t->second.GetName();
976 lg->AppendEcho(commands,path.c_str());
982 std::vector<cmStdString> const& localHelp = lg->GetLocalHelp();
983 for(std::vector<cmStdString>::const_iterator o = localHelp.begin();
984 o != localHelp.end(); ++o)
986 path = "... ";
987 path += *o;
988 lg->AppendEcho(commands, path.c_str());
990 lg->WriteMakeRule(ruleFileStream, "Help Target",
991 "help",
992 no_depends, commands, true);
993 ruleFileStream << "\n\n";
997 bool cmGlobalUnixMakefileGenerator3
998 ::NeedRequiresStep(cmTarget const& target)
1000 std::set<cmStdString> languages;
1001 target.GetLanguages(languages);
1002 for(std::set<cmStdString>::const_iterator l = languages.begin();
1003 l != languages.end(); ++l)
1005 std::string var = "CMAKE_NEEDS_REQUIRES_STEP_";
1006 var += *l;
1007 var += "_FLAG";
1008 if(target.GetMakefile()->GetDefinition(var.c_str()))
1010 return true;
1013 return false;