1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator3
4 Module: $RCSfile: cmGlobalUnixMakefileGenerator3.cxx,v $
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"
23 #include "cmGeneratedFileStream.h"
24 #include "cmSourceFile.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;
38 this->UseLinkScript
= true;
42 void cmGlobalUnixMakefileGenerator3
43 ::EnableLanguage(std::vector
<std::string
>const& languages
,
47 this->cmGlobalGenerator::EnableLanguage(languages
, mf
, optional
);
49 for(std::vector
<std::string
>::const_iterator l
= languages
.begin();
50 l
!= languages
.end(); ++l
)
56 const char* lang
= l
->c_str();
57 std::string langComp
= "CMAKE_";
59 langComp
+= "_COMPILER";
61 if(!mf
->GetDefinition(langComp
.c_str()))
65 cmSystemTools::Error(langComp
.c_str(),
66 " not set, after EnableLanguage");
70 const char* name
= mf
->GetRequiredDefinition(langComp
.c_str());
71 if(!cmSystemTools::FileIsFullPath(name
))
73 path
= cmSystemTools::FindProgram(name
);
79 if((path
.size() == 0 || !cmSystemTools::FileExists(path
.c_str()))
82 std::string message
= "your ";
84 message
+= " compiler: \"";
86 message
+= "\" was not found. Please set ";
88 message
+= " to a valid compiler path or name.";
89 cmSystemTools::Error(message
.c_str());
92 std::string doc
= lang
;
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
)
107 this->GetCMakeInstance()->GetProperty(
108 "__CMAKE_DELETE_CACHE_CHANGE_VARS_");
114 changeVars
+= langComp
;
117 this->GetCMakeInstance()->SetProperty(
118 "__CMAKE_DELETE_CACHE_CHANGE_VARS_",
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);
135 //----------------------------------------------------------------------------
136 void cmGlobalUnixMakefileGenerator3
137 ::GetDocumentation(cmDocumentationEntry
& entry
) const
139 entry
.Name
= this->GetName();
140 entry
.Brief
= "Generates standard UNIX makefiles.";
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();
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());
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");
221 lg
->WriteMakeRule(makefileStream
,
222 "Default target executed when no arguments are "
230 // The all and preinstall rules might never have any dependencies
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
252 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
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());
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
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
)
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());
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.
324 << "# The top level Makefile was generated from the following files:\n"
325 << "SET(CMAKE_MAKEFILE_DEPENDS\n"
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
)
334 << lg
->Convert(i
->c_str(), cmLocalGenerator::START_OUTPUT
).c_str()
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.
347 << "# The corresponding makefile is:\n"
348 << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
350 << lg
->Convert(makefileName
.c_str(),
351 cmLocalGenerator::START_OUTPUT
).c_str() << "\"\n"
353 << lg
->Convert(check
.c_str(),
354 cmLocalGenerator::START_OUTPUT
).c_str() << "\"\n";
356 // add in all the directory information files
358 for (unsigned int i
= 0; i
< this->LocalGenerators
.size(); ++i
)
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()
369 cmakefileStream
<< " )\n\n";
371 // CMake must rerun if a byproduct is missing.
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()
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
401 << "# Dependency information for all targets:\n";
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 //----------------------------------------------------------------------------
429 cmGlobalUnixMakefileGenerator3
430 ::WriteDirectoryRule2(std::ostream
& ruleFileStream
,
431 cmLocalUnixMakefileGenerator3
* lg
,
432 const char* pass
, bool check_all
,
435 // Get the relative path to the subdirectory from the top.
436 std::string makeTarget
= lg
->GetMakefile()->GetStartOutputDirectory();
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")) &&
455 l
->second
.NeedRelinkBeforeInstall(lg
->ConfigurationName
.c_str())))
457 std::string tname
= lg
->GetRelativeTargetDirectory(l
->second
);
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();
475 depends
.push_back(subdir
);
478 // Work-around for makes that drop rules that have no dependencies
480 if(depends
.empty() && this->EmptyRuleHackDepends
!= "")
482 depends
.push_back(this->EmptyRuleHackDepends
);
486 std::string doc
= "Convenience name for \"";
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 //----------------------------------------------------------------------------
496 cmGlobalUnixMakefileGenerator3
497 ::WriteDirectoryRules2(std::ostream
& ruleFileStream
,
498 cmLocalUnixMakefileGenerator3
* lg
)
500 // Only subdirectories need these rules.
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
);
512 << "# Directory level rules for directory "
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.
535 std::string makeCommand
=
536 cmSystemTools::ConvertToUnixOutputPath(makeProgram
);
538 // Since we have full control over the invocation of nmake, let us
540 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
542 makeCommand
+= " /NOLOGO ";
546 makeCommand
+= " -i";
548 if ( additionalOptions
)
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]);
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
;
579 tname
= lg
->Convert(tname
.c_str(),cmLocalGenerator::HOME_OUTPUT
,
580 cmLocalGenerator::MAKEFILE
);
581 makeCommand
+= tname
.c_str();
583 if (!this->LocalGenerators
.size())
591 //----------------------------------------------------------------------------
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
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
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
);
629 << "# Target rules for targets named "
630 << t
->second
.GetName() << "\n\n";
634 std::string tmp
= cmake::GetCMakeFilesDirectoryPostSlash();
636 commands
.push_back(lg
->GetRecursiveMakeCall
637 (tmp
.c_str(),t
->second
.GetName()));
639 depends
.push_back("cmake_check_build_system");
640 lg
->WriteMakeRule(ruleFileStream
,
641 "Build rule for target.",
642 t
->second
.GetName(), depends
, commands
,
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";
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
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";
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 //----------------------------------------------------------------------------
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
);
722 << "# Target rules for target "
723 << localName
<< "\n\n";
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()));
748 std::string progressDir
=
749 lg
->GetMakefile()->GetHomeOutputDirectory();
750 progressDir
+= cmake::GetCMakeFilesDirectory();
752 cmOStringStream progCmd
;
753 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_report ";
755 progCmd
<< lg
->Convert(progressDir
.c_str(),
756 cmLocalGenerator::FULL
,
757 cmLocalGenerator::SHELL
);
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
))
779 depends
.push_back(localName
);
781 lg
->WriteMakeRule(ruleFileStream
, "Include target in all.",
782 "all", depends
, commands
, true);
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 ";
795 progCmd
<< lg
->Convert(progressDir
.c_str(),
796 cmLocalGenerator::FULL
,
797 cmLocalGenerator::SHELL
);
799 std::set
<cmTarget
*> emitted
;
801 << this->CountProgressMarksInTarget(&t
->second
, emitted
);
802 commands
.push_back(progCmd
.str());
804 std::string tmp
= cmake::GetCMakeFilesDirectoryPostSlash();
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
);
815 commands
.push_back(progCmd
.str());
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).
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";
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
))
848 depends
.push_back(localName
);
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";
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);
866 depends
.push_back(makeTargetName
);
867 lg
->WriteMakeRule(ruleFileStream
, "clean rule for target.",
868 "clean", depends
, commands
, true);
873 //----------------------------------------------------------------------------
875 cmGlobalUnixMakefileGenerator3
876 ::CountProgressMarksInTarget(cmTarget
* target
,
877 std::set
<cmTarget
*>& emitted
)
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
);
893 //----------------------------------------------------------------------------
895 cmGlobalUnixMakefileGenerator3
896 ::CountProgressMarksInAll(cmLocalUnixMakefileGenerator3
* lg
)
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
);
909 //----------------------------------------------------------------------------
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 //----------------------------------------------------------------------------
921 cmGlobalUnixMakefileGenerator3::TargetProgress
922 ::WriteProgressVariables(unsigned long total
, unsigned long ¤t
)
924 cmGeneratedFileStream
fout(this->VariableFile
.c_str());
925 for(unsigned long i
= 1; i
<= this->NumberOfActions
; ++i
)
927 fout
<< "CMAKE_PROGRESS_" << i
<< " = ";
930 unsigned long num
= i
+ current
;
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
;
938 this->Marks
.push_back(num
);
943 current
+= this->NumberOfActions
;
946 //----------------------------------------------------------------------------
948 cmGlobalUnixMakefileGenerator3
949 ::AppendGlobalTargetDepends(std::vector
<std::string
>& depends
,
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
);
963 depends
.push_back(tgtName
);
967 //----------------------------------------------------------------------------
968 void cmGlobalUnixMakefileGenerator3::WriteHelpRule
969 (std::ostream
& ruleFileStream
, cmLocalUnixMakefileGenerator3
*lg
)
971 // add the help target
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
986 cmLocalUnixMakefileGenerator3
*lg2
;
987 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
990 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
991 // for the passed in makefile or if this is the top Makefile wripte out
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
)
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
)
1022 lg
->AppendEcho(commands
, path
.c_str());
1024 lg
->WriteMakeRule(ruleFileStream
, "Help Target",
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_";
1042 if(target
.GetMakefile()->GetDefinition(var
.c_str()))