Introduce "generator expressions" to add_test()
[cmake.git] / Source / cmGlobalUnixMakefileGenerator3.cxx
blob3f92499f72420791a7800ffe0fff4155987150f1
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator3
4 Module: $RCSfile: cmGlobalUnixMakefileGenerator3.cxx,v $
5 Language: C++
6 Date: $Date: 2009-07-08 17:03:46 $
7 Version: $Revision: 1.137 $
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 "cmMakefileTargetGenerator.h"
21 #include "cmMakefile.h"
22 #include "cmake.h"
23 #include "cmGeneratedFileStream.h"
24 #include "cmSourceFile.h"
25 #include "cmTarget.h"
27 cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
29 // This type of makefile always requires unix style paths
30 this->ForceUnixPaths = true;
31 this->FindMakeProgramFile = "CMakeUnixFindMake.cmake";
32 this->ToolSupportsColor = true;
33 this->ForceVerboseMakefiles = false;
35 #if defined(_WIN32) || defined(__VMS)
36 this->UseLinkScript = false;
37 #else
38 this->UseLinkScript = true;
39 #endif
42 void cmGlobalUnixMakefileGenerator3
43 ::EnableLanguage(std::vector<std::string>const& languages,
44 cmMakefile *mf,
45 bool optional)
47 this->cmGlobalGenerator::EnableLanguage(languages, mf, optional);
48 std::string path;
49 for(std::vector<std::string>::const_iterator l = languages.begin();
50 l != languages.end(); ++l)
52 if(*l == "NONE")
54 continue;
56 const char* lang = l->c_str();
57 std::string langComp = "CMAKE_";
58 langComp += lang;
59 langComp += "_COMPILER";
61 if(!mf->GetDefinition(langComp.c_str()))
63 if(!optional)
65 cmSystemTools::Error(langComp.c_str(),
66 " not set, after EnableLanguage");
68 continue;
70 const char* name = mf->GetRequiredDefinition(langComp.c_str());
71 if(!cmSystemTools::FileIsFullPath(name))
73 path = cmSystemTools::FindProgram(name);
75 else
77 path = name;
79 if((path.size() == 0 || !cmSystemTools::FileExists(path.c_str()))
80 && (optional==false))
82 std::string message = "your ";
83 message += lang;
84 message += " compiler: \"";
85 message += name;
86 message += "\" was not found. Please set ";
87 message += langComp;
88 message += " to a valid compiler path or name.";
89 cmSystemTools::Error(message.c_str());
90 path = name;
92 std::string doc = lang;
93 doc += " compiler.";
94 const char* cname = this->GetCMakeInstance()->
95 GetCacheManager()->GetCacheValue(langComp.c_str());
96 std::string changeVars;
97 if(cname && (path != cname) && (optional==false))
99 std::string cnameString = cname;
100 std::string pathString = path;
101 // get rid of potentially multiple slashes:
102 cmSystemTools::ConvertToUnixSlashes(cnameString);
103 cmSystemTools::ConvertToUnixSlashes(pathString);
104 if (cnameString != pathString)
106 const char* cvars =
107 this->GetCMakeInstance()->GetProperty(
108 "__CMAKE_DELETE_CACHE_CHANGE_VARS_");
109 if(cvars)
111 changeVars += cvars;
112 changeVars += ";";
114 changeVars += langComp;
115 changeVars += ";";
116 changeVars += cname;
117 this->GetCMakeInstance()->SetProperty(
118 "__CMAKE_DELETE_CACHE_CHANGE_VARS_",
119 changeVars.c_str());
122 mf->AddCacheDefinition(langComp.c_str(), path.c_str(),
123 doc.c_str(), cmCacheManager::FILEPATH);
127 ///! Create a local generator appropriate to this Global Generator
128 cmLocalGenerator *cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
130 cmLocalGenerator* lg = new cmLocalUnixMakefileGenerator3;
131 lg->SetGlobalGenerator(this);
132 return lg;
135 //----------------------------------------------------------------------------
136 void cmGlobalUnixMakefileGenerator3
137 ::GetDocumentation(cmDocumentationEntry& entry) const
139 entry.Name = this->GetName();
140 entry.Brief = "Generates standard UNIX makefiles.";
141 entry.Full =
142 "A hierarchy of UNIX makefiles is generated into the build tree. Any "
143 "standard UNIX-style make program can build the project through the "
144 "default make target. A \"make install\" target is also provided.";
147 //----------------------------------------------------------------------------
148 void cmGlobalUnixMakefileGenerator3::Generate()
150 // first do superclass method
151 this->cmGlobalGenerator::Generate();
153 // initialize progress
154 unsigned long total = 0;
155 for(ProgressMapType::const_iterator pmi = this->ProgressMap.begin();
156 pmi != this->ProgressMap.end(); ++pmi)
158 total += pmi->second.NumberOfActions;
161 // write each target's progress.make this loop is done twice. Bascially the
162 // Generate pass counts all the actions, the first loop below determines
163 // how many actions have progress updates for each target and writes to
164 // corrrect variable values for everything except the all targets. The
165 // second loop actually writes out correct values for the all targets as
166 // well. This is because the all targets require more information that is
167 // computed in the first loop.
168 unsigned long current = 0;
169 for(ProgressMapType::iterator pmi = this->ProgressMap.begin();
170 pmi != this->ProgressMap.end(); ++pmi)
172 pmi->second.WriteProgressVariables(total, current);
174 for(unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
176 cmLocalUnixMakefileGenerator3 *lg =
177 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
178 std::string markFileName = lg->GetMakefile()->GetStartOutputDirectory();
179 markFileName += "/";
180 markFileName += cmake::GetCMakeFilesDirectory();
181 markFileName += "/progress.marks";
182 cmGeneratedFileStream markFile(markFileName.c_str());
183 markFile << this->CountProgressMarksInAll(lg) << "\n";
186 // write the main makefile
187 this->WriteMainMakefile2();
188 this->WriteMainCMakefile();
191 void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
193 // Open the output file. This should not be copy-if-different
194 // because the check-build-system step compares the makefile time to
195 // see if the build system must be regenerated.
196 std::string makefileName =
197 this->GetCMakeInstance()->GetHomeOutputDirectory();
198 makefileName += cmake::GetCMakeFilesDirectory();
199 makefileName += "/Makefile2";
200 cmGeneratedFileStream makefileStream(makefileName.c_str());
201 if(!makefileStream)
203 return;
206 // get a local generator for some useful methods
207 cmLocalUnixMakefileGenerator3 *lg =
208 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
210 // Write the do not edit header.
211 lg->WriteDisclaimer(makefileStream);
213 // Write the main entry point target. This must be the VERY first
214 // target so that make with no arguments will run it.
215 // Just depend on the all target to drive the build.
216 std::vector<std::string> depends;
217 std::vector<std::string> no_commands;
218 depends.push_back("all");
220 // Write the rule.
221 lg->WriteMakeRule(makefileStream,
222 "Default target executed when no arguments are "
223 "given to make.",
224 "default_target",
225 depends,
226 no_commands, true);
228 depends.clear();
230 // The all and preinstall rules might never have any dependencies
231 // added to them.
232 if(this->EmptyRuleHackDepends != "")
234 depends.push_back(this->EmptyRuleHackDepends);
237 // Write and empty all:
238 lg->WriteMakeRule(makefileStream,
239 "The main recursive all target", "all",
240 depends, no_commands, true);
242 // Write an empty preinstall:
243 lg->WriteMakeRule(makefileStream,
244 "The main recursive preinstall target", "preinstall",
245 depends, no_commands, true);
247 // Write out the "special" stuff
248 lg->WriteSpecialTargetsTop(makefileStream);
250 // write the target convenience rules
251 unsigned int i;
252 for (i = 0; i < this->LocalGenerators.size(); ++i)
254 lg =
255 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
256 this->WriteConvenienceRules2(makefileStream,lg);
259 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
260 lg->WriteSpecialTargetsBottom(makefileStream);
264 //----------------------------------------------------------------------------
265 void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
267 // Open the output file. This should not be copy-if-different
268 // because the check-build-system step compares the makefile time to
269 // see if the build system must be regenerated.
270 std::string cmakefileName =
271 this->GetCMakeInstance()->GetHomeOutputDirectory();
272 cmakefileName += cmake::GetCMakeFilesDirectory();
273 cmakefileName += "/Makefile.cmake";
274 cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
275 if(!cmakefileStream)
277 return;
280 std::string makefileName =
281 this->GetCMakeInstance()->GetHomeOutputDirectory();
282 makefileName += "/Makefile";
284 // get a local generator for some useful methods
285 cmLocalUnixMakefileGenerator3 *lg =
286 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
288 // Write the do not edit header.
289 lg->WriteDisclaimer(cmakefileStream);
291 // Save the generator name
292 cmakefileStream
293 << "# The generator used is:\n"
294 << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
296 // for each cmMakefile get its list of dependencies
297 std::vector<std::string> lfiles;
298 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
300 lg =
301 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
303 // Get the list of files contributing to this generation step.
304 lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
305 lg->GetMakefile()->GetListFiles().end());
307 // Sort the list and remove duplicates.
308 std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
309 #if !defined(__VMS) // The Compaq STL on VMS crashes, so accept duplicates.
310 std::vector<std::string>::iterator new_end =
311 std::unique(lfiles.begin(),lfiles.end());
312 lfiles.erase(new_end, lfiles.end());
313 #endif
315 // reset lg to the first makefile
316 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
318 // Build the path to the cache file.
319 std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
320 cache += "/CMakeCache.txt";
322 // Save the list to the cmake file.
323 cmakefileStream
324 << "# The top level Makefile was generated from the following files:\n"
325 << "SET(CMAKE_MAKEFILE_DEPENDS\n"
326 << " \""
327 << lg->Convert(cache.c_str(),
328 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
329 for(std::vector<std::string>::const_iterator i = lfiles.begin();
330 i != lfiles.end(); ++i)
332 cmakefileStream
333 << " \""
334 << lg->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT).c_str()
335 << "\"\n";
337 cmakefileStream
338 << " )\n\n";
340 // Build the path to the cache check file.
341 std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
342 check += cmake::GetCMakeFilesDirectory();
343 check += "/cmake.check_cache";
345 // Set the corresponding makefile in the cmake file.
346 cmakefileStream
347 << "# The corresponding makefile is:\n"
348 << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
349 << " \""
350 << lg->Convert(makefileName.c_str(),
351 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n"
352 << " \""
353 << lg->Convert(check.c_str(),
354 cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
356 // add in all the directory information files
357 std::string tmpStr;
358 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
360 lg =
361 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
362 tmpStr = lg->GetMakefile()->GetStartOutputDirectory();
363 tmpStr += cmake::GetCMakeFilesDirectory();
364 tmpStr += "/CMakeDirectoryInformation.cmake";
365 cmakefileStream << " \"" <<
366 lg->Convert(tmpStr.c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
367 << "\"\n";
369 cmakefileStream << " )\n\n";
371 // CMake must rerun if a byproduct is missing.
373 cmakefileStream
374 << "# Byproducts of CMake generate step:\n"
375 << "SET(CMAKE_MAKEFILE_PRODUCTS\n";
376 const std::vector<std::string>& outfiles =
377 lg->GetMakefile()->GetOutputFiles();
378 for(std::vector<std::string>::const_iterator k = outfiles.begin();
379 k != outfiles.end(); ++k)
381 cmakefileStream << " \"" <<
382 lg->Convert(k->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
383 << "\"\n";
385 cmakefileStream << " )\n\n";
388 this->WriteMainCMakefileLanguageRules(cmakefileStream,
389 this->LocalGenerators);
392 void cmGlobalUnixMakefileGenerator3
393 ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
394 std::vector<cmLocalGenerator *> &lGenerators
397 cmLocalUnixMakefileGenerator3 *lg;
399 // now list all the target info files
400 cmakefileStream
401 << "# Dependency information for all targets:\n";
402 cmakefileStream
403 << "SET(CMAKE_DEPEND_INFO_FILES\n";
404 for (unsigned int i = 0; i < lGenerators.size(); ++i)
406 lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
407 // for all of out targets
408 for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
409 l != lg->GetMakefile()->GetTargets().end(); l++)
411 if((l->second.GetType() == cmTarget::EXECUTABLE) ||
412 (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
413 (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
414 (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
415 (l->second.GetType() == cmTarget::UTILITY))
417 std::string tname = lg->GetRelativeTargetDirectory(l->second);
418 tname += "/DependInfo.cmake";
419 cmSystemTools::ConvertToUnixSlashes(tname);
420 cmakefileStream << " \"" << tname.c_str() << "\"\n";
424 cmakefileStream << " )\n";
427 //----------------------------------------------------------------------------
428 void
429 cmGlobalUnixMakefileGenerator3
430 ::WriteDirectoryRule2(std::ostream& ruleFileStream,
431 cmLocalUnixMakefileGenerator3* lg,
432 const char* pass, bool check_all,
433 bool check_relink)
435 // Get the relative path to the subdirectory from the top.
436 std::string makeTarget = lg->GetMakefile()->GetStartOutputDirectory();
437 makeTarget += "/";
438 makeTarget += pass;
440 // The directory-level rule should depend on the target-level rules
441 // for all targets in the directory.
442 std::vector<std::string> depends;
443 for(cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
444 l != lg->GetMakefile()->GetTargets().end(); ++l)
446 if((l->second.GetType() == cmTarget::EXECUTABLE) ||
447 (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
448 (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
449 (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
450 (l->second.GetType() == cmTarget::UTILITY))
452 // Add this to the list of depends rules in this directory.
453 if((!check_all || !l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
454 (!check_relink ||
455 l->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str())))
457 std::string tname = lg->GetRelativeTargetDirectory(l->second);
458 tname += "/";
459 tname += pass;
460 depends.push_back(tname);
465 // The directory-level rule should depend on the directory-level
466 // rules of the subdirectories.
467 for(std::vector<cmLocalGenerator*>::iterator sdi =
468 lg->GetChildren().begin(); sdi != lg->GetChildren().end(); ++sdi)
470 cmLocalUnixMakefileGenerator3* slg =
471 static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
472 std::string subdir = slg->GetMakefile()->GetStartOutputDirectory();
473 subdir += "/";
474 subdir += pass;
475 depends.push_back(subdir);
478 // Work-around for makes that drop rules that have no dependencies
479 // or commands.
480 if(depends.empty() && this->EmptyRuleHackDepends != "")
482 depends.push_back(this->EmptyRuleHackDepends);
485 // Write the rule.
486 std::string doc = "Convenience name for \"";
487 doc += pass;
488 doc += "\" pass in the directory.";
489 std::vector<std::string> no_commands;
490 lg->WriteMakeRule(ruleFileStream, doc.c_str(),
491 makeTarget.c_str(), depends, no_commands, true);
494 //----------------------------------------------------------------------------
495 void
496 cmGlobalUnixMakefileGenerator3
497 ::WriteDirectoryRules2(std::ostream& ruleFileStream,
498 cmLocalUnixMakefileGenerator3* lg)
500 // Only subdirectories need these rules.
501 if(!lg->GetParent())
503 return;
506 // Begin the directory-level rules section.
507 std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
508 dir = lg->Convert(dir.c_str(), cmLocalGenerator::HOME_OUTPUT,
509 cmLocalGenerator::MAKEFILE);
510 lg->WriteDivider(ruleFileStream);
511 ruleFileStream
512 << "# Directory level rules for directory "
513 << dir << "\n\n";
515 // Write directory-level rules for "all".
516 this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
518 // Write directory-level rules for "clean".
519 this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false);
521 // Write directory-level rules for "preinstall".
522 this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
526 std::string cmGlobalUnixMakefileGenerator3
527 ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
528 const char* additionalOptions, const char *targetName,
529 const char* config, bool ignoreErrors, bool fast)
531 // Project name and config are not used yet.
532 (void)projectName;
533 (void)config;
535 std::string makeCommand =
536 cmSystemTools::ConvertToUnixOutputPath(makeProgram);
538 // Since we have full control over the invocation of nmake, let us
539 // make it quiet.
540 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
542 makeCommand += " /NOLOGO ";
544 if ( ignoreErrors )
546 makeCommand += " -i";
548 if ( additionalOptions )
550 makeCommand += " ";
551 makeCommand += additionalOptions;
553 if ( targetName && strlen(targetName))
555 cmLocalUnixMakefileGenerator3 *lg;
556 if (this->LocalGenerators.size())
558 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
559 (this->LocalGenerators[0]);
561 else
563 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
564 (this->CreateLocalGenerator());
565 // set the Start directories
566 lg->GetMakefile()->SetStartDirectory
567 (this->CMakeInstance->GetStartDirectory());
568 lg->GetMakefile()->SetStartOutputDirectory
569 (this->CMakeInstance->GetStartOutputDirectory());
570 lg->GetMakefile()->MakeStartDirectoriesCurrent();
573 makeCommand += " \"";
574 std::string tname = targetName;
575 if(fast)
577 tname += "/fast";
579 tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
580 cmLocalGenerator::MAKEFILE);
581 makeCommand += tname.c_str();
582 makeCommand += "\"";
583 if (!this->LocalGenerators.size())
585 delete lg;
588 return makeCommand;
591 //----------------------------------------------------------------------------
592 void
593 cmGlobalUnixMakefileGenerator3
594 ::WriteConvenienceRules(std::ostream& ruleFileStream,
595 std::set<cmStdString> &emitted)
597 std::vector<std::string> depends;
598 std::vector<std::string> commands;
600 depends.push_back("cmake_check_build_system");
602 // write the target convenience rules
603 unsigned int i;
604 cmLocalUnixMakefileGenerator3 *lg;
605 for (i = 0; i < this->LocalGenerators.size(); ++i)
607 lg = static_cast<cmLocalUnixMakefileGenerator3 *>
608 (this->LocalGenerators[i]);
609 // for each target Generate the rule files for each target.
610 cmTargets& targets = lg->GetMakefile()->GetTargets();
611 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
613 // Don't emit the same rule twice (e.g. two targets with the same
614 // simple name)
615 if(t->second.GetName() &&
616 strlen(t->second.GetName()) &&
617 emitted.insert(t->second.GetName()).second &&
618 // Handle user targets here. Global targets are handled in
619 // the local generator on a per-directory basis.
620 ((t->second.GetType() == cmTarget::EXECUTABLE) ||
621 (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
622 (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
623 (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
624 (t->second.GetType() == cmTarget::UTILITY)))
626 // Add a rule to build the target by name.
627 lg->WriteDivider(ruleFileStream);
628 ruleFileStream
629 << "# Target rules for targets named "
630 << t->second.GetName() << "\n\n";
632 // Write the rule.
633 commands.clear();
634 std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
635 tmp += "Makefile2";
636 commands.push_back(lg->GetRecursiveMakeCall
637 (tmp.c_str(),t->second.GetName()));
638 depends.clear();
639 depends.push_back("cmake_check_build_system");
640 lg->WriteMakeRule(ruleFileStream,
641 "Build rule for target.",
642 t->second.GetName(), depends, commands,
643 true);
645 // Add a fast rule to build the target
646 std::string localName = lg->GetRelativeTargetDirectory(t->second);
647 std::string makefileName;
648 makefileName = localName;
649 makefileName += "/build.make";
650 depends.clear();
651 commands.clear();
652 std::string makeTargetName = localName;
653 makeTargetName += "/build";
654 localName = t->second.GetName();
655 localName += "/fast";
656 commands.push_back(lg->GetRecursiveMakeCall
657 (makefileName.c_str(), makeTargetName.c_str()));
658 lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
659 localName.c_str(), depends, commands, true);
661 // Add a local name for the rule to relink the target before
662 // installation.
663 if(t->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str()))
665 makeTargetName = lg->GetRelativeTargetDirectory(t->second);
666 makeTargetName += "/preinstall";
667 localName = t->second.GetName();
668 localName += "/preinstall";
669 depends.clear();
670 commands.clear();
671 commands.push_back(lg->GetRecursiveMakeCall
672 (makefileName.c_str(), makeTargetName.c_str()));
673 lg->WriteMakeRule(ruleFileStream,
674 "Manual pre-install relink rule for target.",
675 localName.c_str(), depends, commands, true);
683 //----------------------------------------------------------------------------
684 void
685 cmGlobalUnixMakefileGenerator3
686 ::WriteConvenienceRules2(std::ostream& ruleFileStream,
687 cmLocalUnixMakefileGenerator3 *lg)
689 std::vector<std::string> depends;
690 std::vector<std::string> commands;
691 std::string localName;
692 std::string makeTargetName;
695 // write the directory level rules for this local gen
696 this->WriteDirectoryRules2(ruleFileStream,lg);
698 depends.push_back("cmake_check_build_system");
700 // for each target Generate the rule files for each target.
701 cmTargets& targets = lg->GetMakefile()->GetTargets();
702 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
704 if (t->second.GetName()
705 && strlen(t->second.GetName())
706 && ((t->second.GetType() == cmTarget::EXECUTABLE)
707 || (t->second.GetType() == cmTarget::STATIC_LIBRARY)
708 || (t->second.GetType() == cmTarget::SHARED_LIBRARY)
709 || (t->second.GetType() == cmTarget::MODULE_LIBRARY)
710 || (t->second.GetType() == cmTarget::UTILITY)))
712 std::string makefileName;
713 // Add a rule to build the target by name.
714 localName = lg->GetRelativeTargetDirectory(t->second);
715 makefileName = localName;
716 makefileName += "/build.make";
718 bool needRequiresStep = this->NeedRequiresStep(t->second);
720 lg->WriteDivider(ruleFileStream);
721 ruleFileStream
722 << "# Target rules for target "
723 << localName << "\n\n";
725 commands.clear();
726 makeTargetName = localName;
727 makeTargetName += "/depend";
728 commands.push_back(lg->GetRecursiveMakeCall
729 (makefileName.c_str(),makeTargetName.c_str()));
731 // add requires if we need it for this generator
732 if (needRequiresStep)
734 makeTargetName = localName;
735 makeTargetName += "/requires";
736 commands.push_back(lg->GetRecursiveMakeCall
737 (makefileName.c_str(),makeTargetName.c_str()));
739 makeTargetName = localName;
740 makeTargetName += "/build";
741 commands.push_back(lg->GetRecursiveMakeCall
742 (makefileName.c_str(),makeTargetName.c_str()));
744 // Write the rule.
745 localName += "/all";
746 depends.clear();
748 std::string progressDir =
749 lg->GetMakefile()->GetHomeOutputDirectory();
750 progressDir += cmake::GetCMakeFilesDirectory();
752 cmOStringStream progCmd;
753 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
754 // all target counts
755 progCmd << lg->Convert(progressDir.c_str(),
756 cmLocalGenerator::FULL,
757 cmLocalGenerator::SHELL);
758 progCmd << " ";
759 std::vector<int> &progFiles = this->ProgressMap[t->first].Marks;
760 for (std::vector<int>::iterator i = progFiles.begin();
761 i != progFiles.end(); ++i)
763 progCmd << " " << *i;
765 commands.push_back(progCmd.str());
767 progressDir = "Built target ";
768 progressDir += t->first;
769 lg->AppendEcho(commands,progressDir.c_str());
771 this->AppendGlobalTargetDepends(depends,t->second);
772 lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
773 localName.c_str(), depends, commands, true);
775 // add the all/all dependency
776 if(!this->IsExcluded(this->LocalGenerators[0], t->second))
778 depends.clear();
779 depends.push_back(localName);
780 commands.clear();
781 lg->WriteMakeRule(ruleFileStream, "Include target in all.",
782 "all", depends, commands, true);
785 // Write the rule.
786 commands.clear();
787 progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
788 progressDir += cmake::GetCMakeFilesDirectory();
791 // TODO: Convert the total progress count to a make variable.
792 cmOStringStream progCmd;
793 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
794 // # in target
795 progCmd << lg->Convert(progressDir.c_str(),
796 cmLocalGenerator::FULL,
797 cmLocalGenerator::SHELL);
799 std::set<cmTarget *> emitted;
800 progCmd << " "
801 << this->CountProgressMarksInTarget(&t->second, emitted);
802 commands.push_back(progCmd.str());
804 std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
805 tmp += "Makefile2";
806 commands.push_back(lg->GetRecursiveMakeCall
807 (tmp.c_str(),localName.c_str()));
809 cmOStringStream progCmd;
810 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
811 progCmd << lg->Convert(progressDir.c_str(),
812 cmLocalGenerator::FULL,
813 cmLocalGenerator::SHELL);
814 progCmd << " 0";
815 commands.push_back(progCmd.str());
817 depends.clear();
818 depends.push_back("cmake_check_build_system");
819 localName = lg->GetRelativeTargetDirectory(t->second);
820 localName += "/rule";
821 lg->WriteMakeRule(ruleFileStream,
822 "Build rule for subdir invocation for target.",
823 localName.c_str(), depends, commands, true);
825 // Add a target with the canonical name (no prefix, suffix or path).
826 commands.clear();
827 depends.clear();
828 depends.push_back(localName);
829 lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
830 t->second.GetName(), depends, commands, true);
832 // Add rules to prepare the target for installation.
833 if(t->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str()))
835 localName = lg->GetRelativeTargetDirectory(t->second);
836 localName += "/preinstall";
837 depends.clear();
838 commands.clear();
839 commands.push_back(lg->GetRecursiveMakeCall
840 (makefileName.c_str(), localName.c_str()));
841 lg->WriteMakeRule(ruleFileStream,
842 "Pre-install relink rule for target.",
843 localName.c_str(), depends, commands, true);
845 if(!this->IsExcluded(this->LocalGenerators[0], t->second))
847 depends.clear();
848 depends.push_back(localName);
849 commands.clear();
850 lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
851 "preinstall", depends, commands, true);
855 // add the clean rule
856 localName = lg->GetRelativeTargetDirectory(t->second);
857 makeTargetName = localName;
858 makeTargetName += "/clean";
859 depends.clear();
860 commands.clear();
861 commands.push_back(lg->GetRecursiveMakeCall
862 (makefileName.c_str(), makeTargetName.c_str()));
863 lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
864 makeTargetName.c_str(), depends, commands, true);
865 commands.clear();
866 depends.push_back(makeTargetName);
867 lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
868 "clean", depends, commands, true);
873 //----------------------------------------------------------------------------
874 size_t
875 cmGlobalUnixMakefileGenerator3
876 ::CountProgressMarksInTarget(cmTarget* target,
877 std::set<cmTarget*>& emitted)
879 size_t count = 0;
880 if(emitted.insert(target).second)
882 count = this->ProgressMap[target->GetName()].Marks.size();
883 TargetDependSet const& depends = this->GetTargetDirectDepends(*target);
884 for(TargetDependSet::const_iterator di = depends.begin();
885 di != depends.end(); ++di)
887 count += this->CountProgressMarksInTarget(*di, emitted);
890 return count;
893 //----------------------------------------------------------------------------
894 size_t
895 cmGlobalUnixMakefileGenerator3
896 ::CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg)
898 size_t count = 0;
899 std::set<cmTarget*> emitted;
900 std::set<cmTarget*> const& targets = this->LocalGeneratorToTargetMap[lg];
901 for(std::set<cmTarget*>::const_iterator t = targets.begin();
902 t != targets.end(); ++t)
904 count += this->CountProgressMarksInTarget(*t, emitted);
906 return count;
909 //----------------------------------------------------------------------------
910 void
911 cmGlobalUnixMakefileGenerator3::RecordTargetProgress(
912 cmMakefileTargetGenerator* tg)
914 TargetProgress& tp = this->ProgressMap[tg->GetTarget()->GetName()];
915 tp.NumberOfActions = tg->GetNumberOfProgressActions();
916 tp.VariableFile = tg->GetProgressFileNameFull();
919 //----------------------------------------------------------------------------
920 void
921 cmGlobalUnixMakefileGenerator3::TargetProgress
922 ::WriteProgressVariables(unsigned long total, unsigned long &current)
924 cmGeneratedFileStream fout(this->VariableFile.c_str());
925 for(unsigned long i = 1; i <= this->NumberOfActions; ++i)
927 fout << "CMAKE_PROGRESS_" << i << " = ";
928 if (total <= 100)
930 unsigned long num = i + current;
931 fout << num;
932 this->Marks.push_back(num);
934 else if (((i+current)*100)/total > ((i-1+current)*100)/total)
936 unsigned long num = ((i+current)*100)/total;
937 fout << num;
938 this->Marks.push_back(num);
940 fout << "\n";
942 fout << "\n";
943 current += this->NumberOfActions;
946 //----------------------------------------------------------------------------
947 void
948 cmGlobalUnixMakefileGenerator3
949 ::AppendGlobalTargetDepends(std::vector<std::string>& depends,
950 cmTarget& target)
952 TargetDependSet const& depends_set = this->GetTargetDirectDepends(target);
953 for(TargetDependSet::const_iterator i = depends_set.begin();
954 i != depends_set.end(); ++i)
956 // Create the target-level dependency.
957 cmTarget const* dep = *i;
958 cmLocalUnixMakefileGenerator3* lg3 =
959 static_cast<cmLocalUnixMakefileGenerator3*>
960 (dep->GetMakefile()->GetLocalGenerator());
961 std::string tgtName = lg3->GetRelativeTargetDirectory(*dep);
962 tgtName += "/all";
963 depends.push_back(tgtName);
967 //----------------------------------------------------------------------------
968 void cmGlobalUnixMakefileGenerator3::WriteHelpRule
969 (std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
971 // add the help target
972 std::string path;
973 std::vector<std::string> no_depends;
974 std::vector<std::string> commands;
975 lg->AppendEcho(commands,"The following are some of the valid targets "
976 "for this Makefile:");
977 lg->AppendEcho(commands,"... all (the default if no target is provided)");
978 lg->AppendEcho(commands,"... clean");
979 lg->AppendEcho(commands,"... depend");
981 // Keep track of targets already listed.
982 std::set<cmStdString> emittedTargets;
984 // for each local generator
985 unsigned int i;
986 cmLocalUnixMakefileGenerator3 *lg2;
987 for (i = 0; i < this->LocalGenerators.size(); ++i)
989 lg2 =
990 static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
991 // for the passed in makefile or if this is the top Makefile wripte out
992 // the targets
993 if (lg2 == lg || !lg->GetParent())
995 // for each target Generate the rule files for each target.
996 cmTargets& targets = lg2->GetMakefile()->GetTargets();
997 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
999 if((t->second.GetType() == cmTarget::EXECUTABLE) ||
1000 (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
1001 (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
1002 (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
1003 (t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
1004 (t->second.GetType() == cmTarget::UTILITY))
1006 if(emittedTargets.insert(t->second.GetName()).second)
1008 path = "... ";
1009 path += t->second.GetName();
1010 lg->AppendEcho(commands,path.c_str());
1016 std::vector<cmStdString> const& localHelp = lg->GetLocalHelp();
1017 for(std::vector<cmStdString>::const_iterator o = localHelp.begin();
1018 o != localHelp.end(); ++o)
1020 path = "... ";
1021 path += *o;
1022 lg->AppendEcho(commands, path.c_str());
1024 lg->WriteMakeRule(ruleFileStream, "Help Target",
1025 "help",
1026 no_depends, commands, true);
1027 ruleFileStream << "\n\n";
1031 bool cmGlobalUnixMakefileGenerator3
1032 ::NeedRequiresStep(cmTarget const& target)
1034 std::set<cmStdString> languages;
1035 target.GetLanguages(languages);
1036 for(std::set<cmStdString>::const_iterator l = languages.begin();
1037 l != languages.end(); ++l)
1039 std::string var = "CMAKE_NEEDS_REQUIRES_STEP_";
1040 var += *l;
1041 var += "_FLAG";
1042 if(target.GetMakefile()->GetDefinition(var.c_str()))
1044 return true;
1047 return false;