1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator3
4 Module: $RCSfile: cmGlobalUnixMakefileGenerator3.cxx,v $
6 Date: $Date: 2008/01/31 03:56:34 $
7 Version: $Revision: 1.125 $
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"
22 #include "cmGeneratedFileStream.h"
23 #include "cmSourceFile.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;
35 this->UseLinkScript
= false;
37 this->UseLinkScript
= true;
41 void cmGlobalUnixMakefileGenerator3
42 ::EnableLanguage(std::vector
<std::string
>const& languages
,
46 this->cmGlobalGenerator::EnableLanguage(languages
, mf
, optional
);
48 for(std::vector
<std::string
>::const_iterator l
= languages
.begin();
49 l
!= languages
.end(); ++l
)
55 const char* lang
= l
->c_str();
56 std::string langComp
= "CMAKE_";
58 langComp
+= "_COMPILER";
60 if(!mf
->GetDefinition(langComp
.c_str()))
62 cmSystemTools::Error(langComp
.c_str(),
63 " not set, after EnableLanguage");
66 const char* name
= mf
->GetRequiredDefinition(langComp
.c_str());
67 if(!cmSystemTools::FileIsFullPath(name
))
69 path
= cmSystemTools::FindProgram(name
);
75 if((path
.size() == 0 || !cmSystemTools::FileExists(path
.c_str()))
78 std::string message
= "your ";
80 message
+= " compiler: \"";
82 message
+= "\" was not found. Please set ";
84 message
+= " to a valid compiler path or name.";
85 cmSystemTools::Error(message
.c_str());
88 std::string doc
= lang
;
90 const char* cname
= this->GetCMakeInstance()->
91 GetCacheManager()->GetCacheValue(langComp
.c_str());
92 std::string changeVars
;
93 if(cname
&& (path
!= cname
))
96 this->GetCMakeInstance()->GetProperty(
97 "__CMAKE_DELETE_CACHE_CHANGE_VARS_");
103 changeVars
+= langComp
;
106 this->GetCMakeInstance()->SetProperty(
107 "__CMAKE_DELETE_CACHE_CHANGE_VARS_",
110 mf
->AddCacheDefinition(langComp
.c_str(), path
.c_str(),
111 doc
.c_str(), cmCacheManager::FILEPATH
);
115 ///! Create a local generator appropriate to this Global Generator
116 cmLocalGenerator
*cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
118 cmLocalGenerator
* lg
= new cmLocalUnixMakefileGenerator3
;
119 lg
->SetGlobalGenerator(this);
123 //----------------------------------------------------------------------------
124 void cmGlobalUnixMakefileGenerator3
125 ::GetDocumentation(cmDocumentationEntry
& entry
) const
127 entry
.Name
= this->GetName();
128 entry
.Brief
= "Generates standard UNIX makefiles.";
130 "A hierarchy of UNIX makefiles is generated into the build tree. Any "
131 "standard UNIX-style make program can build the project through the "
132 "default make target. A \"make install\" target is also provided.";
135 //----------------------------------------------------------------------------
136 void cmGlobalUnixMakefileGenerator3::Generate()
138 // first do superclass method
139 this->cmGlobalGenerator::Generate();
141 // initialize progress
143 unsigned long total
= 0;
144 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
146 cmLocalUnixMakefileGenerator3
*lg
=
147 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
148 total
+= lg
->GetNumberOfProgressActions();
151 // write each target's progress.make this loop is done twice. Bascially the
152 // Generate pass counts all the actions, the first loop below determines
153 // how many actions have progress updates for each target and writes to
154 // corrrect variable values for everything except the all targets. The
155 // second loop actually writes out correct values for the all targets as
156 // well. This is because the all targets require more information that is
157 // computed in the first loop.
158 unsigned long current
= 0;
159 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
161 cmLocalUnixMakefileGenerator3
*lg
=
162 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
163 lg
->WriteProgressVariables(total
,current
);
165 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
167 cmLocalUnixMakefileGenerator3
*lg
=
168 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
169 lg
->WriteAllProgressVariable();
172 // write the main makefile
173 this->WriteMainMakefile2();
174 this->WriteMainCMakefile();
177 void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
179 // Open the output file. This should not be copy-if-different
180 // because the check-build-system step compares the makefile time to
181 // see if the build system must be regenerated.
182 std::string makefileName
=
183 this->GetCMakeInstance()->GetHomeOutputDirectory();
184 makefileName
+= cmake::GetCMakeFilesDirectory();
185 makefileName
+= "/Makefile2";
186 cmGeneratedFileStream
makefileStream(makefileName
.c_str());
192 // get a local generator for some useful methods
193 cmLocalUnixMakefileGenerator3
*lg
=
194 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[0]);
196 // Write the do not edit header.
197 lg
->WriteDisclaimer(makefileStream
);
199 // Write the main entry point target. This must be the VERY first
200 // target so that make with no arguments will run it.
201 // Just depend on the all target to drive the build.
202 std::vector
<std::string
> depends
;
203 std::vector
<std::string
> no_commands
;
204 depends
.push_back("all");
207 lg
->WriteMakeRule(makefileStream
,
208 "Default target executed when no arguments are "
216 // The all and preinstall rules might never have any dependencies
218 if(this->EmptyRuleHackDepends
!= "")
220 depends
.push_back(this->EmptyRuleHackDepends
);
223 // Write and empty all:
224 lg
->WriteMakeRule(makefileStream
,
225 "The main recursive all target", "all",
226 depends
, no_commands
, true);
228 // Write an empty preinstall:
229 lg
->WriteMakeRule(makefileStream
,
230 "The main recursive preinstall target", "preinstall",
231 depends
, no_commands
, true);
233 // Write out the "special" stuff
234 lg
->WriteSpecialTargetsTop(makefileStream
);
236 // write the target convenience rules
238 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
241 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
242 this->WriteConvenienceRules2(makefileStream
,lg
);
245 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[0]);
246 lg
->WriteSpecialTargetsBottom(makefileStream
);
250 //----------------------------------------------------------------------------
251 void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
253 // Open the output file. This should not be copy-if-different
254 // because the check-build-system step compares the makefile time to
255 // see if the build system must be regenerated.
256 std::string cmakefileName
=
257 this->GetCMakeInstance()->GetHomeOutputDirectory();
258 cmakefileName
+= cmake::GetCMakeFilesDirectory();
259 cmakefileName
+= "/Makefile.cmake";
260 cmGeneratedFileStream
cmakefileStream(cmakefileName
.c_str());
266 std::string makefileName
=
267 this->GetCMakeInstance()->GetHomeOutputDirectory();
268 makefileName
+= "/Makefile";
270 // get a local generator for some useful methods
271 cmLocalUnixMakefileGenerator3
*lg
=
272 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[0]);
274 // Write the do not edit header.
275 lg
->WriteDisclaimer(cmakefileStream
);
277 // Save the generator name
279 << "# The generator used is:\n"
280 << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
282 // for each cmMakefile get its list of dependencies
283 std::vector
<std::string
> lfiles
;
284 for (unsigned int i
= 0; i
< this->LocalGenerators
.size(); ++i
)
287 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
289 // Get the list of files contributing to this generation step.
290 lfiles
.insert(lfiles
.end(),lg
->GetMakefile()->GetListFiles().begin(),
291 lg
->GetMakefile()->GetListFiles().end());
293 // Sort the list and remove duplicates.
294 std::sort(lfiles
.begin(), lfiles
.end(), std::less
<std::string
>());
295 std::vector
<std::string
>::iterator new_end
=
296 std::unique(lfiles
.begin(),lfiles
.end());
297 lfiles
.erase(new_end
, lfiles
.end());
299 // reset lg to the first makefile
300 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[0]);
302 // Build the path to the cache file.
303 std::string cache
= this->GetCMakeInstance()->GetHomeOutputDirectory();
304 cache
+= "/CMakeCache.txt";
306 // Save the list to the cmake file.
308 << "# The top level Makefile was generated from the following files:\n"
309 << "SET(CMAKE_MAKEFILE_DEPENDS\n"
311 << lg
->Convert(cache
.c_str(),
312 cmLocalGenerator::START_OUTPUT
).c_str() << "\"\n";
313 for(std::vector
<std::string
>::const_iterator i
= lfiles
.begin();
314 i
!= lfiles
.end(); ++i
)
318 << lg
->Convert(i
->c_str(), cmLocalGenerator::START_OUTPUT
).c_str()
324 // Build the path to the cache check file.
325 std::string check
= this->GetCMakeInstance()->GetHomeOutputDirectory();
326 check
+= cmake::GetCMakeFilesDirectory();
327 check
+= "/cmake.check_cache";
329 // Set the corresponding makefile in the cmake file.
331 << "# The corresponding makefile is:\n"
332 << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
334 << lg
->Convert(makefileName
.c_str(),
335 cmLocalGenerator::START_OUTPUT
).c_str() << "\"\n"
337 << lg
->Convert(check
.c_str(),
338 cmLocalGenerator::START_OUTPUT
).c_str() << "\"\n";
340 // add in all the directory information files
342 for (unsigned int i
= 0; i
< this->LocalGenerators
.size(); ++i
)
345 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
346 tmpStr
= lg
->GetMakefile()->GetStartOutputDirectory();
347 tmpStr
+= cmake::GetCMakeFilesDirectory();
348 tmpStr
+= "/CMakeDirectoryInformation.cmake";
349 cmakefileStream
<< " \"" <<
350 lg
->Convert(tmpStr
.c_str(),cmLocalGenerator::HOME_OUTPUT
).c_str()
352 const std::vector
<std::string
>& outfiles
=
353 lg
->GetMakefile()->GetOutputFiles();
354 for(std::vector
<std::string
>::const_iterator k
= outfiles
.begin();
355 k
!= outfiles
.end(); ++k
)
357 cmakefileStream
<< " \"" <<
358 lg
->Convert(k
->c_str(),cmLocalGenerator::HOME_OUTPUT
).c_str()
362 cmakefileStream
<< " )\n\n";
364 this->WriteMainCMakefileLanguageRules(cmakefileStream
,
365 this->LocalGenerators
);
368 void cmGlobalUnixMakefileGenerator3
369 ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream
& cmakefileStream
,
370 std::vector
<cmLocalGenerator
*> &lGenerators
373 cmLocalUnixMakefileGenerator3
*lg
;
375 // now list all the target info files
377 << "# Dependency information for all targets:\n";
379 << "SET(CMAKE_DEPEND_INFO_FILES\n";
380 for (unsigned int i
= 0; i
< lGenerators
.size(); ++i
)
382 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>(lGenerators
[i
]);
383 // for all of out targets
384 for (cmTargets::iterator l
= lg
->GetMakefile()->GetTargets().begin();
385 l
!= lg
->GetMakefile()->GetTargets().end(); l
++)
387 if((l
->second
.GetType() == cmTarget::EXECUTABLE
) ||
388 (l
->second
.GetType() == cmTarget::STATIC_LIBRARY
) ||
389 (l
->second
.GetType() == cmTarget::SHARED_LIBRARY
) ||
390 (l
->second
.GetType() == cmTarget::MODULE_LIBRARY
) ||
391 (l
->second
.GetType() == cmTarget::UTILITY
))
393 std::string tname
= lg
->GetRelativeTargetDirectory(l
->second
);
394 tname
+= "/DependInfo.cmake";
395 cmSystemTools::ConvertToUnixSlashes(tname
);
396 cmakefileStream
<< " \"" << tname
.c_str() << "\"\n";
400 cmakefileStream
<< " )\n";
403 //----------------------------------------------------------------------------
405 cmGlobalUnixMakefileGenerator3
406 ::WriteDirectoryRule2(std::ostream
& ruleFileStream
,
407 cmLocalUnixMakefileGenerator3
* lg
,
408 const char* pass
, bool check_all
,
411 // Get the relative path to the subdirectory from the top.
412 std::string makeTarget
= lg
->GetMakefile()->GetStartOutputDirectory();
416 // The directory-level rule should depend on the target-level rules
417 // for all targets in the directory.
418 std::vector
<std::string
> depends
;
419 for(cmTargets::iterator l
= lg
->GetMakefile()->GetTargets().begin();
420 l
!= lg
->GetMakefile()->GetTargets().end(); ++l
)
422 if((l
->second
.GetType() == cmTarget::EXECUTABLE
) ||
423 (l
->second
.GetType() == cmTarget::STATIC_LIBRARY
) ||
424 (l
->second
.GetType() == cmTarget::SHARED_LIBRARY
) ||
425 (l
->second
.GetType() == cmTarget::MODULE_LIBRARY
) ||
426 (l
->second
.GetType() == cmTarget::UTILITY
))
428 // Add this to the list of depends rules in this directory.
429 if((!check_all
|| !l
->second
.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
430 (!check_relink
|| l
->second
.NeedRelinkBeforeInstall()))
432 std::string tname
= lg
->GetRelativeTargetDirectory(l
->second
);
435 depends
.push_back(tname
);
440 // The directory-level rule should depend on the directory-level
441 // rules of the subdirectories.
442 for(std::vector
<cmLocalGenerator
*>::iterator sdi
=
443 lg
->GetChildren().begin(); sdi
!= lg
->GetChildren().end(); ++sdi
)
445 cmLocalUnixMakefileGenerator3
* slg
=
446 static_cast<cmLocalUnixMakefileGenerator3
*>(*sdi
);
447 std::string subdir
= slg
->GetMakefile()->GetStartOutputDirectory();
450 depends
.push_back(subdir
);
453 // Work-around for makes that drop rules that have no dependencies
455 if(depends
.empty() && this->EmptyRuleHackDepends
!= "")
457 depends
.push_back(this->EmptyRuleHackDepends
);
461 std::string doc
= "Convenience name for \"";
463 doc
+= "\" pass in the directory.";
464 std::vector
<std::string
> no_commands
;
465 lg
->WriteMakeRule(ruleFileStream
, doc
.c_str(),
466 makeTarget
.c_str(), depends
, no_commands
, true);
469 //----------------------------------------------------------------------------
471 cmGlobalUnixMakefileGenerator3
472 ::WriteDirectoryRules2(std::ostream
& ruleFileStream
,
473 cmLocalUnixMakefileGenerator3
* lg
)
475 // Only subdirectories need these rules.
481 // Begin the directory-level rules section.
482 std::string dir
= lg
->GetMakefile()->GetStartOutputDirectory();
483 dir
= lg
->Convert(dir
.c_str(), cmLocalGenerator::HOME_OUTPUT
,
484 cmLocalGenerator::MAKEFILE
);
485 lg
->WriteDivider(ruleFileStream
);
487 << "# Directory level rules for directory "
490 // Write directory-level rules for "all".
491 this->WriteDirectoryRule2(ruleFileStream
, lg
, "all", true, false);
493 // Write directory-level rules for "clean".
494 this->WriteDirectoryRule2(ruleFileStream
, lg
, "clean", false, false);
496 // Write directory-level rules for "preinstall".
497 this->WriteDirectoryRule2(ruleFileStream
, lg
, "preinstall", true, true);
501 std::string cmGlobalUnixMakefileGenerator3
502 ::GenerateBuildCommand(const char* makeProgram
, const char *projectName
,
503 const char* additionalOptions
, const char *targetName
,
504 const char* config
, bool ignoreErrors
, bool fast
)
506 // Project name and config are not used yet.
510 std::string makeCommand
=
511 cmSystemTools::ConvertToUnixOutputPath(makeProgram
);
513 // Since we have full control over the invocation of nmake, let us
515 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
517 makeCommand
+= " /NOLOGO ";
521 makeCommand
+= " -i";
523 if ( additionalOptions
)
526 makeCommand
+= additionalOptions
;
528 if ( targetName
&& strlen(targetName
))
530 cmLocalUnixMakefileGenerator3
*lg
;
531 if (this->LocalGenerators
.size())
533 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>
534 (this->LocalGenerators
[0]);
538 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>
539 (this->CreateLocalGenerator());
540 // set the Start directories
541 lg
->GetMakefile()->SetStartDirectory
542 (this->CMakeInstance
->GetStartDirectory());
543 lg
->GetMakefile()->SetStartOutputDirectory
544 (this->CMakeInstance
->GetStartOutputDirectory());
545 lg
->GetMakefile()->MakeStartDirectoriesCurrent();
548 makeCommand
+= " \"";
549 std::string tname
= targetName
;
554 tname
= lg
->Convert(tname
.c_str(),cmLocalGenerator::HOME_OUTPUT
,
555 cmLocalGenerator::MAKEFILE
);
556 makeCommand
+= tname
.c_str();
558 if (!this->LocalGenerators
.size())
566 //----------------------------------------------------------------------------
568 cmGlobalUnixMakefileGenerator3
569 ::WriteConvenienceRules(std::ostream
& ruleFileStream
,
570 std::set
<cmStdString
> &emitted
)
572 std::vector
<std::string
> depends
;
573 std::vector
<std::string
> commands
;
575 depends
.push_back("cmake_check_build_system");
577 // write the target convenience rules
579 cmLocalUnixMakefileGenerator3
*lg
;
580 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
582 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>
583 (this->LocalGenerators
[i
]);
584 // for each target Generate the rule files for each target.
585 cmTargets
& targets
= lg
->GetMakefile()->GetTargets();
586 for(cmTargets::iterator t
= targets
.begin(); t
!= targets
.end(); ++t
)
588 // Don't emit the same rule twice (e.g. two targets with the same
590 if(t
->second
.GetName() &&
591 strlen(t
->second
.GetName()) &&
592 emitted
.insert(t
->second
.GetName()).second
&&
593 // Handle user targets here. Global targets are handled in
594 // the local generator on a per-directory basis.
595 ((t
->second
.GetType() == cmTarget::EXECUTABLE
) ||
596 (t
->second
.GetType() == cmTarget::STATIC_LIBRARY
) ||
597 (t
->second
.GetType() == cmTarget::SHARED_LIBRARY
) ||
598 (t
->second
.GetType() == cmTarget::MODULE_LIBRARY
) ||
599 (t
->second
.GetType() == cmTarget::UTILITY
)))
601 // Add a rule to build the target by name.
602 lg
->WriteDivider(ruleFileStream
);
604 << "# Target rules for targets named "
605 << t
->second
.GetName() << "\n\n";
609 std::string tmp
= cmake::GetCMakeFilesDirectoryPostSlash();
611 commands
.push_back(lg
->GetRecursiveMakeCall
612 (tmp
.c_str(),t
->second
.GetName()));
614 depends
.push_back("cmake_check_build_system");
615 lg
->WriteMakeRule(ruleFileStream
,
616 "Build rule for target.",
617 t
->second
.GetName(), depends
, commands
,
620 // Add a fast rule to build the target
621 std::string localName
= lg
->GetRelativeTargetDirectory(t
->second
);
622 std::string makefileName
;
623 makefileName
= localName
;
624 makefileName
+= "/build.make";
627 std::string makeTargetName
= localName
;
628 makeTargetName
+= "/build";
629 localName
= t
->second
.GetName();
630 localName
+= "/fast";
631 commands
.push_back(lg
->GetRecursiveMakeCall
632 (makefileName
.c_str(), makeTargetName
.c_str()));
633 lg
->WriteMakeRule(ruleFileStream
, "fast build rule for target.",
634 localName
.c_str(), depends
, commands
, true);
636 // Add a local name for the rule to relink the target before
638 if(t
->second
.NeedRelinkBeforeInstall())
640 makeTargetName
= lg
->GetRelativeTargetDirectory(t
->second
);
641 makeTargetName
+= "/preinstall";
642 localName
= t
->second
.GetName();
643 localName
+= "/preinstall";
646 commands
.push_back(lg
->GetRecursiveMakeCall
647 (makefileName
.c_str(), makeTargetName
.c_str()));
648 lg
->WriteMakeRule(ruleFileStream
,
649 "Manual pre-install relink rule for target.",
650 localName
.c_str(), depends
, commands
, true);
658 //----------------------------------------------------------------------------
660 cmGlobalUnixMakefileGenerator3
661 ::WriteConvenienceRules2(std::ostream
& ruleFileStream
,
662 cmLocalUnixMakefileGenerator3
*lg
)
664 std::vector
<std::string
> depends
;
665 std::vector
<std::string
> commands
;
666 std::string localName
;
667 std::string makeTargetName
;
670 // write the directory level rules for this local gen
671 this->WriteDirectoryRules2(ruleFileStream
,lg
);
673 depends
.push_back("cmake_check_build_system");
675 // for each target Generate the rule files for each target.
676 cmTargets
& targets
= lg
->GetMakefile()->GetTargets();
677 for(cmTargets::iterator t
= targets
.begin(); t
!= targets
.end(); ++t
)
679 if (t
->second
.GetName()
680 && strlen(t
->second
.GetName())
681 && ((t
->second
.GetType() == cmTarget::EXECUTABLE
)
682 || (t
->second
.GetType() == cmTarget::STATIC_LIBRARY
)
683 || (t
->second
.GetType() == cmTarget::SHARED_LIBRARY
)
684 || (t
->second
.GetType() == cmTarget::MODULE_LIBRARY
)
685 || (t
->second
.GetType() == cmTarget::UTILITY
)))
687 std::string makefileName
;
688 // Add a rule to build the target by name.
689 localName
= lg
->GetRelativeTargetDirectory(t
->second
);
690 makefileName
= localName
;
691 makefileName
+= "/build.make";
693 bool needRequiresStep
= this->NeedRequiresStep(t
->second
);
695 lg
->WriteDivider(ruleFileStream
);
697 << "# Target rules for target "
698 << localName
<< "\n\n";
701 makeTargetName
= localName
;
702 makeTargetName
+= "/depend";
703 commands
.push_back(lg
->GetRecursiveMakeCall
704 (makefileName
.c_str(),makeTargetName
.c_str()));
706 // add requires if we need it for this generator
707 if (needRequiresStep
)
709 makeTargetName
= localName
;
710 makeTargetName
+= "/requires";
711 commands
.push_back(lg
->GetRecursiveMakeCall
712 (makefileName
.c_str(),makeTargetName
.c_str()));
714 makeTargetName
= localName
;
715 makeTargetName
+= "/build";
716 commands
.push_back(lg
->GetRecursiveMakeCall
717 (makefileName
.c_str(),makeTargetName
.c_str()));
723 std::string progressDir
=
724 lg
->GetMakefile()->GetHomeOutputDirectory();
725 progressDir
+= cmake::GetCMakeFilesDirectory();
727 cmOStringStream progCmd
;
728 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_report ";
730 progCmd
<< lg
->Convert(progressDir
.c_str(),
731 cmLocalGenerator::FULL
,
732 cmLocalGenerator::SHELL
);
734 std::vector
<int> &progFiles
= lg
->ProgressFiles
[t
->first
];
735 for (std::vector
<int>::iterator i
= progFiles
.begin();
736 i
!= progFiles
.end(); ++i
)
738 progCmd
<< " " << *i
;
740 commands
.push_back(progCmd
.str());
742 progressDir
= "Built target ";
743 progressDir
+= t
->first
;
744 lg
->AppendEcho(commands
,progressDir
.c_str());
746 this->AppendGlobalTargetDepends(depends
,t
->second
);
747 lg
->WriteMakeRule(ruleFileStream
, "All Build rule for target.",
748 localName
.c_str(), depends
, commands
, true);
750 // add the all/all dependency
751 if(!this->IsExcluded(this->LocalGenerators
[0], t
->second
))
754 depends
.push_back(localName
);
756 lg
->WriteMakeRule(ruleFileStream
, "Include target in all.",
757 "all", depends
, commands
, true);
762 progressDir
= lg
->GetMakefile()->GetHomeOutputDirectory();
763 progressDir
+= cmake::GetCMakeFilesDirectory();
766 // TODO: Convert the total progress count to a make variable.
767 cmOStringStream progCmd
;
768 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_start ";
770 progCmd
<< lg
->Convert(progressDir
.c_str(),
771 cmLocalGenerator::FULL
,
772 cmLocalGenerator::SHELL
);
774 std::set
<cmStdString
> emitted
;
776 << this->GetTargetTotalNumberOfActions(t
->second
,
778 commands
.push_back(progCmd
.str());
780 std::string tmp
= cmake::GetCMakeFilesDirectoryPostSlash();
782 commands
.push_back(lg
->GetRecursiveMakeCall
783 (tmp
.c_str(),localName
.c_str()));
785 cmOStringStream progCmd
;
786 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
787 progCmd
<< lg
->Convert(progressDir
.c_str(),
788 cmLocalGenerator::FULL
,
789 cmLocalGenerator::SHELL
);
791 commands
.push_back(progCmd
.str());
794 depends
.push_back("cmake_check_build_system");
795 localName
= lg
->GetRelativeTargetDirectory(t
->second
);
796 localName
+= "/rule";
797 lg
->WriteMakeRule(ruleFileStream
,
798 "Build rule for subdir invocation for target.",
799 localName
.c_str(), depends
, commands
, true);
801 // Add a target with the canonical name (no prefix, suffix or path).
804 depends
.push_back(localName
);
805 lg
->WriteMakeRule(ruleFileStream
, "Convenience name for target.",
806 t
->second
.GetName(), depends
, commands
, true);
808 // Add rules to prepare the target for installation.
809 if(t
->second
.NeedRelinkBeforeInstall())
811 localName
= lg
->GetRelativeTargetDirectory(t
->second
);
812 localName
+= "/preinstall";
815 commands
.push_back(lg
->GetRecursiveMakeCall
816 (makefileName
.c_str(), localName
.c_str()));
817 lg
->WriteMakeRule(ruleFileStream
,
818 "Pre-install relink rule for target.",
819 localName
.c_str(), depends
, commands
, true);
821 if(!this->IsExcluded(this->LocalGenerators
[0], t
->second
))
824 depends
.push_back(localName
);
826 lg
->WriteMakeRule(ruleFileStream
, "Prepare target for install.",
827 "preinstall", depends
, commands
, true);
831 // add the clean rule
832 localName
= lg
->GetRelativeTargetDirectory(t
->second
);
833 makeTargetName
= localName
;
834 makeTargetName
+= "/clean";
837 commands
.push_back(lg
->GetRecursiveMakeCall
838 (makefileName
.c_str(), makeTargetName
.c_str()));
839 lg
->WriteMakeRule(ruleFileStream
, "clean rule for target.",
840 makeTargetName
.c_str(), depends
, commands
, true);
842 depends
.push_back(makeTargetName
);
843 lg
->WriteMakeRule(ruleFileStream
, "clean rule for target.",
844 "clean", depends
, commands
, true);
849 //----------------------------------------------------------------------------
850 int cmGlobalUnixMakefileGenerator3
851 ::GetTargetTotalNumberOfActions(cmTarget
& target
,
852 std::set
<cmStdString
> &emitted
)
854 // do not double count
857 if(emitted
.insert(target
.GetName()).second
)
859 cmLocalUnixMakefileGenerator3
*lg
=
860 static_cast<cmLocalUnixMakefileGenerator3
*>
861 (target
.GetMakefile()->GetLocalGenerator());
862 result
= static_cast<int>(lg
->ProgressFiles
[target
.GetName()].size());
864 TargetDependSet
& depends
= this->GetTargetDirectDepends(target
);
866 TargetDependSet::iterator i
;
867 for (i
= depends
.begin(); i
!= depends
.end(); ++i
)
869 result
+= this->GetTargetTotalNumberOfActions(**i
, emitted
);
876 unsigned long cmGlobalUnixMakefileGenerator3
877 ::GetNumberOfProgressActionsInAll(cmLocalUnixMakefileGenerator3
*lg
)
879 unsigned long result
= 0;
880 std::set
<cmTarget
*>& targets
= this->LocalGeneratorToTargetMap
[lg
];
881 for(std::set
<cmTarget
*>::iterator t
= targets
.begin();
882 t
!= targets
.end(); ++t
)
884 cmTarget
* target
= *t
;
885 cmLocalUnixMakefileGenerator3
*lg3
=
886 static_cast<cmLocalUnixMakefileGenerator3
*>
887 (target
->GetMakefile()->GetLocalGenerator());
888 std::vector
<int> &progFiles
= lg3
->ProgressFiles
[target
->GetName()];
889 result
+= static_cast<unsigned long>(progFiles
.size());
895 //----------------------------------------------------------------------------
897 cmGlobalUnixMakefileGenerator3
898 ::AppendGlobalTargetDepends(std::vector
<std::string
>& depends
,
901 TargetDependSet
const& depends_set
= this->GetTargetDirectDepends(target
);
902 for(TargetDependSet::const_iterator i
= depends_set
.begin();
903 i
!= depends_set
.end(); ++i
)
905 // Create the target-level dependency.
906 cmTarget
const* dep
= *i
;
907 cmLocalUnixMakefileGenerator3
* lg3
=
908 static_cast<cmLocalUnixMakefileGenerator3
*>
909 (dep
->GetMakefile()->GetLocalGenerator());
910 std::string tgtName
= lg3
->GetRelativeTargetDirectory(*dep
);
912 depends
.push_back(tgtName
);
916 //----------------------------------------------------------------------------
917 void cmGlobalUnixMakefileGenerator3::WriteHelpRule
918 (std::ostream
& ruleFileStream
, cmLocalUnixMakefileGenerator3
*lg
)
920 // add the help target
922 std::vector
<std::string
> no_depends
;
923 std::vector
<std::string
> commands
;
924 lg
->AppendEcho(commands
,"The following are some of the valid targets "
925 "for this Makefile:");
926 lg
->AppendEcho(commands
,"... all (the default if no target is provided)");
927 lg
->AppendEcho(commands
,"... clean");
928 lg
->AppendEcho(commands
,"... depend");
930 // Keep track of targets already listed.
931 std::set
<cmStdString
> emittedTargets
;
933 // for each local generator
935 cmLocalUnixMakefileGenerator3
*lg2
;
936 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
939 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
940 // for the passed in makefile or if this is the top Makefile wripte out
942 if (lg2
== lg
|| !lg
->GetParent())
944 // for each target Generate the rule files for each target.
945 cmTargets
& targets
= lg2
->GetMakefile()->GetTargets();
946 for(cmTargets::iterator t
= targets
.begin(); t
!= targets
.end(); ++t
)
948 if((t
->second
.GetType() == cmTarget::EXECUTABLE
) ||
949 (t
->second
.GetType() == cmTarget::STATIC_LIBRARY
) ||
950 (t
->second
.GetType() == cmTarget::SHARED_LIBRARY
) ||
951 (t
->second
.GetType() == cmTarget::MODULE_LIBRARY
) ||
952 (t
->second
.GetType() == cmTarget::GLOBAL_TARGET
) ||
953 (t
->second
.GetType() == cmTarget::UTILITY
))
955 if(emittedTargets
.insert(t
->second
.GetName()).second
)
958 path
+= t
->second
.GetName();
959 lg
->AppendEcho(commands
,path
.c_str());
963 std::vector
<cmStdString
> const& localHelp
= lg
->GetLocalHelp();
964 for(std::vector
<cmStdString
>::const_iterator o
= localHelp
.begin();
965 o
!= localHelp
.end(); ++o
)
969 lg
->AppendEcho(commands
, path
.c_str());
973 lg
->WriteMakeRule(ruleFileStream
, "Help Target",
975 no_depends
, commands
, true);
976 ruleFileStream
<< "\n\n";
980 bool cmGlobalUnixMakefileGenerator3
981 ::NeedRequiresStep(cmTarget
const& target
)
983 std::set
<cmStdString
> languages
;
984 target
.GetLanguages(languages
);
985 for(std::set
<cmStdString
>::const_iterator l
= languages
.begin();
986 l
!= languages
.end(); ++l
)
988 std::string var
= "CMAKE_NEEDS_REQUIRES_STEP_";
991 if(target
.GetMakefile()->GetDefinition(var
.c_str()))