1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator3
4 Module: $RCSfile: cmGlobalUnixMakefileGenerator3.cxx,v $
6 Date: $Date: 2008-07-03 13:31:29 $
7 Version: $Revision: 1.131 $
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()))
64 cmSystemTools::Error(langComp
.c_str(),
65 " not set, after EnableLanguage");
69 const char* name
= mf
->GetRequiredDefinition(langComp
.c_str());
70 if(!cmSystemTools::FileIsFullPath(name
))
72 path
= cmSystemTools::FindProgram(name
);
78 if((path
.size() == 0 || !cmSystemTools::FileExists(path
.c_str()))
81 std::string message
= "your ";
83 message
+= " compiler: \"";
85 message
+= "\" was not found. Please set ";
87 message
+= " to a valid compiler path or name.";
88 cmSystemTools::Error(message
.c_str());
91 std::string doc
= lang
;
93 const char* cname
= this->GetCMakeInstance()->
94 GetCacheManager()->GetCacheValue(langComp
.c_str());
95 std::string changeVars
;
96 if(cname
&& (path
!= cname
) && (optional
==false))
99 this->GetCMakeInstance()->GetProperty(
100 "__CMAKE_DELETE_CACHE_CHANGE_VARS_");
106 changeVars
+= langComp
;
109 this->GetCMakeInstance()->SetProperty(
110 "__CMAKE_DELETE_CACHE_CHANGE_VARS_",
113 mf
->AddCacheDefinition(langComp
.c_str(), path
.c_str(),
114 doc
.c_str(), cmCacheManager::FILEPATH
);
118 ///! Create a local generator appropriate to this Global Generator
119 cmLocalGenerator
*cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
121 cmLocalGenerator
* lg
= new cmLocalUnixMakefileGenerator3
;
122 lg
->SetGlobalGenerator(this);
126 //----------------------------------------------------------------------------
127 void cmGlobalUnixMakefileGenerator3
128 ::GetDocumentation(cmDocumentationEntry
& entry
) const
130 entry
.Name
= this->GetName();
131 entry
.Brief
= "Generates standard UNIX makefiles.";
133 "A hierarchy of UNIX makefiles is generated into the build tree. Any "
134 "standard UNIX-style make program can build the project through the "
135 "default make target. A \"make install\" target is also provided.";
138 //----------------------------------------------------------------------------
139 void cmGlobalUnixMakefileGenerator3::Generate()
141 // first do superclass method
142 this->cmGlobalGenerator::Generate();
144 // initialize progress
146 unsigned long total
= 0;
147 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
149 cmLocalUnixMakefileGenerator3
*lg
=
150 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
151 total
+= lg
->GetNumberOfProgressActions();
154 // write each target's progress.make this loop is done twice. Bascially the
155 // Generate pass counts all the actions, the first loop below determines
156 // how many actions have progress updates for each target and writes to
157 // corrrect variable values for everything except the all targets. The
158 // second loop actually writes out correct values for the all targets as
159 // well. This is because the all targets require more information that is
160 // computed in the first loop.
161 unsigned long current
= 0;
162 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
164 cmLocalUnixMakefileGenerator3
*lg
=
165 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
166 lg
->WriteProgressVariables(total
,current
);
168 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
170 cmLocalUnixMakefileGenerator3
*lg
=
171 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
172 lg
->WriteAllProgressVariable();
175 // write the main makefile
176 this->WriteMainMakefile2();
177 this->WriteMainCMakefile();
180 void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
182 // Open the output file. This should not be copy-if-different
183 // because the check-build-system step compares the makefile time to
184 // see if the build system must be regenerated.
185 std::string makefileName
=
186 this->GetCMakeInstance()->GetHomeOutputDirectory();
187 makefileName
+= cmake::GetCMakeFilesDirectory();
188 makefileName
+= "/Makefile2";
189 cmGeneratedFileStream
makefileStream(makefileName
.c_str());
195 // get a local generator for some useful methods
196 cmLocalUnixMakefileGenerator3
*lg
=
197 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[0]);
199 // Write the do not edit header.
200 lg
->WriteDisclaimer(makefileStream
);
202 // Write the main entry point target. This must be the VERY first
203 // target so that make with no arguments will run it.
204 // Just depend on the all target to drive the build.
205 std::vector
<std::string
> depends
;
206 std::vector
<std::string
> no_commands
;
207 depends
.push_back("all");
210 lg
->WriteMakeRule(makefileStream
,
211 "Default target executed when no arguments are "
219 // The all and preinstall rules might never have any dependencies
221 if(this->EmptyRuleHackDepends
!= "")
223 depends
.push_back(this->EmptyRuleHackDepends
);
226 // Write and empty all:
227 lg
->WriteMakeRule(makefileStream
,
228 "The main recursive all target", "all",
229 depends
, no_commands
, true);
231 // Write an empty preinstall:
232 lg
->WriteMakeRule(makefileStream
,
233 "The main recursive preinstall target", "preinstall",
234 depends
, no_commands
, true);
236 // Write out the "special" stuff
237 lg
->WriteSpecialTargetsTop(makefileStream
);
239 // write the target convenience rules
241 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
244 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
245 this->WriteConvenienceRules2(makefileStream
,lg
);
248 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[0]);
249 lg
->WriteSpecialTargetsBottom(makefileStream
);
253 //----------------------------------------------------------------------------
254 void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
256 // Open the output file. This should not be copy-if-different
257 // because the check-build-system step compares the makefile time to
258 // see if the build system must be regenerated.
259 std::string cmakefileName
=
260 this->GetCMakeInstance()->GetHomeOutputDirectory();
261 cmakefileName
+= cmake::GetCMakeFilesDirectory();
262 cmakefileName
+= "/Makefile.cmake";
263 cmGeneratedFileStream
cmakefileStream(cmakefileName
.c_str());
269 std::string makefileName
=
270 this->GetCMakeInstance()->GetHomeOutputDirectory();
271 makefileName
+= "/Makefile";
273 // get a local generator for some useful methods
274 cmLocalUnixMakefileGenerator3
*lg
=
275 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[0]);
277 // Write the do not edit header.
278 lg
->WriteDisclaimer(cmakefileStream
);
280 // Save the generator name
282 << "# The generator used is:\n"
283 << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
285 // for each cmMakefile get its list of dependencies
286 std::vector
<std::string
> lfiles
;
287 for (unsigned int i
= 0; i
< this->LocalGenerators
.size(); ++i
)
290 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
292 // Get the list of files contributing to this generation step.
293 lfiles
.insert(lfiles
.end(),lg
->GetMakefile()->GetListFiles().begin(),
294 lg
->GetMakefile()->GetListFiles().end());
296 // Sort the list and remove duplicates.
297 std::sort(lfiles
.begin(), lfiles
.end(), std::less
<std::string
>());
298 std::vector
<std::string
>::iterator new_end
=
299 std::unique(lfiles
.begin(),lfiles
.end());
300 lfiles
.erase(new_end
, lfiles
.end());
302 // reset lg to the first makefile
303 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[0]);
305 // Build the path to the cache file.
306 std::string cache
= this->GetCMakeInstance()->GetHomeOutputDirectory();
307 cache
+= "/CMakeCache.txt";
309 // Save the list to the cmake file.
311 << "# The top level Makefile was generated from the following files:\n"
312 << "SET(CMAKE_MAKEFILE_DEPENDS\n"
314 << lg
->Convert(cache
.c_str(),
315 cmLocalGenerator::START_OUTPUT
).c_str() << "\"\n";
316 for(std::vector
<std::string
>::const_iterator i
= lfiles
.begin();
317 i
!= lfiles
.end(); ++i
)
321 << lg
->Convert(i
->c_str(), cmLocalGenerator::START_OUTPUT
).c_str()
327 // Build the path to the cache check file.
328 std::string check
= this->GetCMakeInstance()->GetHomeOutputDirectory();
329 check
+= cmake::GetCMakeFilesDirectory();
330 check
+= "/cmake.check_cache";
332 // Set the corresponding makefile in the cmake file.
334 << "# The corresponding makefile is:\n"
335 << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
337 << lg
->Convert(makefileName
.c_str(),
338 cmLocalGenerator::START_OUTPUT
).c_str() << "\"\n"
340 << lg
->Convert(check
.c_str(),
341 cmLocalGenerator::START_OUTPUT
).c_str() << "\"\n";
343 // add in all the directory information files
345 for (unsigned int i
= 0; i
< this->LocalGenerators
.size(); ++i
)
348 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
349 tmpStr
= lg
->GetMakefile()->GetStartOutputDirectory();
350 tmpStr
+= cmake::GetCMakeFilesDirectory();
351 tmpStr
+= "/CMakeDirectoryInformation.cmake";
352 cmakefileStream
<< " \"" <<
353 lg
->Convert(tmpStr
.c_str(),cmLocalGenerator::HOME_OUTPUT
).c_str()
355 const std::vector
<std::string
>& outfiles
=
356 lg
->GetMakefile()->GetOutputFiles();
357 for(std::vector
<std::string
>::const_iterator k
= outfiles
.begin();
358 k
!= outfiles
.end(); ++k
)
360 cmakefileStream
<< " \"" <<
361 lg
->Convert(k
->c_str(),cmLocalGenerator::HOME_OUTPUT
).c_str()
365 cmakefileStream
<< " )\n\n";
367 this->WriteMainCMakefileLanguageRules(cmakefileStream
,
368 this->LocalGenerators
);
371 void cmGlobalUnixMakefileGenerator3
372 ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream
& cmakefileStream
,
373 std::vector
<cmLocalGenerator
*> &lGenerators
376 cmLocalUnixMakefileGenerator3
*lg
;
378 // now list all the target info files
380 << "# Dependency information for all targets:\n";
382 << "SET(CMAKE_DEPEND_INFO_FILES\n";
383 for (unsigned int i
= 0; i
< lGenerators
.size(); ++i
)
385 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>(lGenerators
[i
]);
386 // for all of out targets
387 for (cmTargets::iterator l
= lg
->GetMakefile()->GetTargets().begin();
388 l
!= lg
->GetMakefile()->GetTargets().end(); l
++)
390 if((l
->second
.GetType() == cmTarget::EXECUTABLE
) ||
391 (l
->second
.GetType() == cmTarget::STATIC_LIBRARY
) ||
392 (l
->second
.GetType() == cmTarget::SHARED_LIBRARY
) ||
393 (l
->second
.GetType() == cmTarget::MODULE_LIBRARY
) ||
394 (l
->second
.GetType() == cmTarget::UTILITY
))
396 std::string tname
= lg
->GetRelativeTargetDirectory(l
->second
);
397 tname
+= "/DependInfo.cmake";
398 cmSystemTools::ConvertToUnixSlashes(tname
);
399 cmakefileStream
<< " \"" << tname
.c_str() << "\"\n";
403 cmakefileStream
<< " )\n";
406 //----------------------------------------------------------------------------
408 cmGlobalUnixMakefileGenerator3
409 ::WriteDirectoryRule2(std::ostream
& ruleFileStream
,
410 cmLocalUnixMakefileGenerator3
* lg
,
411 const char* pass
, bool check_all
,
414 // Get the relative path to the subdirectory from the top.
415 std::string makeTarget
= lg
->GetMakefile()->GetStartOutputDirectory();
419 // The directory-level rule should depend on the target-level rules
420 // for all targets in the directory.
421 std::vector
<std::string
> depends
;
422 for(cmTargets::iterator l
= lg
->GetMakefile()->GetTargets().begin();
423 l
!= lg
->GetMakefile()->GetTargets().end(); ++l
)
425 if((l
->second
.GetType() == cmTarget::EXECUTABLE
) ||
426 (l
->second
.GetType() == cmTarget::STATIC_LIBRARY
) ||
427 (l
->second
.GetType() == cmTarget::SHARED_LIBRARY
) ||
428 (l
->second
.GetType() == cmTarget::MODULE_LIBRARY
) ||
429 (l
->second
.GetType() == cmTarget::UTILITY
))
431 // Add this to the list of depends rules in this directory.
432 if((!check_all
|| !l
->second
.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
433 (!check_relink
|| l
->second
.NeedRelinkBeforeInstall()))
435 std::string tname
= lg
->GetRelativeTargetDirectory(l
->second
);
438 depends
.push_back(tname
);
443 // The directory-level rule should depend on the directory-level
444 // rules of the subdirectories.
445 for(std::vector
<cmLocalGenerator
*>::iterator sdi
=
446 lg
->GetChildren().begin(); sdi
!= lg
->GetChildren().end(); ++sdi
)
448 cmLocalUnixMakefileGenerator3
* slg
=
449 static_cast<cmLocalUnixMakefileGenerator3
*>(*sdi
);
450 std::string subdir
= slg
->GetMakefile()->GetStartOutputDirectory();
453 depends
.push_back(subdir
);
456 // Work-around for makes that drop rules that have no dependencies
458 if(depends
.empty() && this->EmptyRuleHackDepends
!= "")
460 depends
.push_back(this->EmptyRuleHackDepends
);
464 std::string doc
= "Convenience name for \"";
466 doc
+= "\" pass in the directory.";
467 std::vector
<std::string
> no_commands
;
468 lg
->WriteMakeRule(ruleFileStream
, doc
.c_str(),
469 makeTarget
.c_str(), depends
, no_commands
, true);
472 //----------------------------------------------------------------------------
474 cmGlobalUnixMakefileGenerator3
475 ::WriteDirectoryRules2(std::ostream
& ruleFileStream
,
476 cmLocalUnixMakefileGenerator3
* lg
)
478 // Only subdirectories need these rules.
484 // Begin the directory-level rules section.
485 std::string dir
= lg
->GetMakefile()->GetStartOutputDirectory();
486 dir
= lg
->Convert(dir
.c_str(), cmLocalGenerator::HOME_OUTPUT
,
487 cmLocalGenerator::MAKEFILE
);
488 lg
->WriteDivider(ruleFileStream
);
490 << "# Directory level rules for directory "
493 // Write directory-level rules for "all".
494 this->WriteDirectoryRule2(ruleFileStream
, lg
, "all", true, false);
496 // Write directory-level rules for "clean".
497 this->WriteDirectoryRule2(ruleFileStream
, lg
, "clean", false, false);
499 // Write directory-level rules for "preinstall".
500 this->WriteDirectoryRule2(ruleFileStream
, lg
, "preinstall", true, true);
504 std::string cmGlobalUnixMakefileGenerator3
505 ::GenerateBuildCommand(const char* makeProgram
, const char *projectName
,
506 const char* additionalOptions
, const char *targetName
,
507 const char* config
, bool ignoreErrors
, bool fast
)
509 // Project name and config are not used yet.
513 std::string makeCommand
=
514 cmSystemTools::ConvertToUnixOutputPath(makeProgram
);
516 // Since we have full control over the invocation of nmake, let us
518 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
520 makeCommand
+= " /NOLOGO ";
524 makeCommand
+= " -i";
526 if ( additionalOptions
)
529 makeCommand
+= additionalOptions
;
531 if ( targetName
&& strlen(targetName
))
533 cmLocalUnixMakefileGenerator3
*lg
;
534 if (this->LocalGenerators
.size())
536 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>
537 (this->LocalGenerators
[0]);
541 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>
542 (this->CreateLocalGenerator());
543 // set the Start directories
544 lg
->GetMakefile()->SetStartDirectory
545 (this->CMakeInstance
->GetStartDirectory());
546 lg
->GetMakefile()->SetStartOutputDirectory
547 (this->CMakeInstance
->GetStartOutputDirectory());
548 lg
->GetMakefile()->MakeStartDirectoriesCurrent();
551 makeCommand
+= " \"";
552 std::string tname
= targetName
;
557 tname
= lg
->Convert(tname
.c_str(),cmLocalGenerator::HOME_OUTPUT
,
558 cmLocalGenerator::MAKEFILE
);
559 makeCommand
+= tname
.c_str();
561 if (!this->LocalGenerators
.size())
569 //----------------------------------------------------------------------------
571 cmGlobalUnixMakefileGenerator3
572 ::WriteConvenienceRules(std::ostream
& ruleFileStream
,
573 std::set
<cmStdString
> &emitted
)
575 std::vector
<std::string
> depends
;
576 std::vector
<std::string
> commands
;
578 depends
.push_back("cmake_check_build_system");
580 // write the target convenience rules
582 cmLocalUnixMakefileGenerator3
*lg
;
583 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
585 lg
= static_cast<cmLocalUnixMakefileGenerator3
*>
586 (this->LocalGenerators
[i
]);
587 // for each target Generate the rule files for each target.
588 cmTargets
& targets
= lg
->GetMakefile()->GetTargets();
589 for(cmTargets::iterator t
= targets
.begin(); t
!= targets
.end(); ++t
)
591 // Don't emit the same rule twice (e.g. two targets with the same
593 if(t
->second
.GetName() &&
594 strlen(t
->second
.GetName()) &&
595 emitted
.insert(t
->second
.GetName()).second
&&
596 // Handle user targets here. Global targets are handled in
597 // the local generator on a per-directory basis.
598 ((t
->second
.GetType() == cmTarget::EXECUTABLE
) ||
599 (t
->second
.GetType() == cmTarget::STATIC_LIBRARY
) ||
600 (t
->second
.GetType() == cmTarget::SHARED_LIBRARY
) ||
601 (t
->second
.GetType() == cmTarget::MODULE_LIBRARY
) ||
602 (t
->second
.GetType() == cmTarget::UTILITY
)))
604 // Add a rule to build the target by name.
605 lg
->WriteDivider(ruleFileStream
);
607 << "# Target rules for targets named "
608 << t
->second
.GetName() << "\n\n";
612 std::string tmp
= cmake::GetCMakeFilesDirectoryPostSlash();
614 commands
.push_back(lg
->GetRecursiveMakeCall
615 (tmp
.c_str(),t
->second
.GetName()));
617 depends
.push_back("cmake_check_build_system");
618 lg
->WriteMakeRule(ruleFileStream
,
619 "Build rule for target.",
620 t
->second
.GetName(), depends
, commands
,
623 // Add a fast rule to build the target
624 std::string localName
= lg
->GetRelativeTargetDirectory(t
->second
);
625 std::string makefileName
;
626 makefileName
= localName
;
627 makefileName
+= "/build.make";
630 std::string makeTargetName
= localName
;
631 makeTargetName
+= "/build";
632 localName
= t
->second
.GetName();
633 localName
+= "/fast";
634 commands
.push_back(lg
->GetRecursiveMakeCall
635 (makefileName
.c_str(), makeTargetName
.c_str()));
636 lg
->WriteMakeRule(ruleFileStream
, "fast build rule for target.",
637 localName
.c_str(), depends
, commands
, true);
639 // Add a local name for the rule to relink the target before
641 if(t
->second
.NeedRelinkBeforeInstall())
643 makeTargetName
= lg
->GetRelativeTargetDirectory(t
->second
);
644 makeTargetName
+= "/preinstall";
645 localName
= t
->second
.GetName();
646 localName
+= "/preinstall";
649 commands
.push_back(lg
->GetRecursiveMakeCall
650 (makefileName
.c_str(), makeTargetName
.c_str()));
651 lg
->WriteMakeRule(ruleFileStream
,
652 "Manual pre-install relink rule for target.",
653 localName
.c_str(), depends
, commands
, true);
661 //----------------------------------------------------------------------------
663 cmGlobalUnixMakefileGenerator3
664 ::WriteConvenienceRules2(std::ostream
& ruleFileStream
,
665 cmLocalUnixMakefileGenerator3
*lg
)
667 std::vector
<std::string
> depends
;
668 std::vector
<std::string
> commands
;
669 std::string localName
;
670 std::string makeTargetName
;
673 // write the directory level rules for this local gen
674 this->WriteDirectoryRules2(ruleFileStream
,lg
);
676 depends
.push_back("cmake_check_build_system");
678 // for each target Generate the rule files for each target.
679 cmTargets
& targets
= lg
->GetMakefile()->GetTargets();
680 for(cmTargets::iterator t
= targets
.begin(); t
!= targets
.end(); ++t
)
682 if (t
->second
.GetName()
683 && strlen(t
->second
.GetName())
684 && ((t
->second
.GetType() == cmTarget::EXECUTABLE
)
685 || (t
->second
.GetType() == cmTarget::STATIC_LIBRARY
)
686 || (t
->second
.GetType() == cmTarget::SHARED_LIBRARY
)
687 || (t
->second
.GetType() == cmTarget::MODULE_LIBRARY
)
688 || (t
->second
.GetType() == cmTarget::UTILITY
)))
690 std::string makefileName
;
691 // Add a rule to build the target by name.
692 localName
= lg
->GetRelativeTargetDirectory(t
->second
);
693 makefileName
= localName
;
694 makefileName
+= "/build.make";
696 bool needRequiresStep
= this->NeedRequiresStep(t
->second
);
698 lg
->WriteDivider(ruleFileStream
);
700 << "# Target rules for target "
701 << localName
<< "\n\n";
704 makeTargetName
= localName
;
705 makeTargetName
+= "/depend";
706 commands
.push_back(lg
->GetRecursiveMakeCall
707 (makefileName
.c_str(),makeTargetName
.c_str()));
709 // add requires if we need it for this generator
710 if (needRequiresStep
)
712 makeTargetName
= localName
;
713 makeTargetName
+= "/requires";
714 commands
.push_back(lg
->GetRecursiveMakeCall
715 (makefileName
.c_str(),makeTargetName
.c_str()));
717 makeTargetName
= localName
;
718 makeTargetName
+= "/build";
719 commands
.push_back(lg
->GetRecursiveMakeCall
720 (makefileName
.c_str(),makeTargetName
.c_str()));
726 std::string progressDir
=
727 lg
->GetMakefile()->GetHomeOutputDirectory();
728 progressDir
+= cmake::GetCMakeFilesDirectory();
730 cmOStringStream progCmd
;
731 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_report ";
733 progCmd
<< lg
->Convert(progressDir
.c_str(),
734 cmLocalGenerator::FULL
,
735 cmLocalGenerator::SHELL
);
737 std::vector
<int> &progFiles
= lg
->ProgressFiles
[t
->first
];
738 for (std::vector
<int>::iterator i
= progFiles
.begin();
739 i
!= progFiles
.end(); ++i
)
741 progCmd
<< " " << *i
;
743 commands
.push_back(progCmd
.str());
745 progressDir
= "Built target ";
746 progressDir
+= t
->first
;
747 lg
->AppendEcho(commands
,progressDir
.c_str());
749 this->AppendGlobalTargetDepends(depends
,t
->second
);
750 lg
->WriteMakeRule(ruleFileStream
, "All Build rule for target.",
751 localName
.c_str(), depends
, commands
, true);
753 // add the all/all dependency
754 if(!this->IsExcluded(this->LocalGenerators
[0], t
->second
))
757 depends
.push_back(localName
);
759 lg
->WriteMakeRule(ruleFileStream
, "Include target in all.",
760 "all", depends
, commands
, true);
765 progressDir
= lg
->GetMakefile()->GetHomeOutputDirectory();
766 progressDir
+= cmake::GetCMakeFilesDirectory();
769 // TODO: Convert the total progress count to a make variable.
770 cmOStringStream progCmd
;
771 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_start ";
773 progCmd
<< lg
->Convert(progressDir
.c_str(),
774 cmLocalGenerator::FULL
,
775 cmLocalGenerator::SHELL
);
777 std::set
<cmTarget
*> emitted
;
779 << this->GetTargetTotalNumberOfActions(t
->second
,
781 commands
.push_back(progCmd
.str());
783 std::string tmp
= cmake::GetCMakeFilesDirectoryPostSlash();
785 commands
.push_back(lg
->GetRecursiveMakeCall
786 (tmp
.c_str(),localName
.c_str()));
788 cmOStringStream progCmd
;
789 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
790 progCmd
<< lg
->Convert(progressDir
.c_str(),
791 cmLocalGenerator::FULL
,
792 cmLocalGenerator::SHELL
);
794 commands
.push_back(progCmd
.str());
797 depends
.push_back("cmake_check_build_system");
798 localName
= lg
->GetRelativeTargetDirectory(t
->second
);
799 localName
+= "/rule";
800 lg
->WriteMakeRule(ruleFileStream
,
801 "Build rule for subdir invocation for target.",
802 localName
.c_str(), depends
, commands
, true);
804 // Add a target with the canonical name (no prefix, suffix or path).
807 depends
.push_back(localName
);
808 lg
->WriteMakeRule(ruleFileStream
, "Convenience name for target.",
809 t
->second
.GetName(), depends
, commands
, true);
811 // Add rules to prepare the target for installation.
812 if(t
->second
.NeedRelinkBeforeInstall())
814 localName
= lg
->GetRelativeTargetDirectory(t
->second
);
815 localName
+= "/preinstall";
818 commands
.push_back(lg
->GetRecursiveMakeCall
819 (makefileName
.c_str(), localName
.c_str()));
820 lg
->WriteMakeRule(ruleFileStream
,
821 "Pre-install relink rule for target.",
822 localName
.c_str(), depends
, commands
, true);
824 if(!this->IsExcluded(this->LocalGenerators
[0], t
->second
))
827 depends
.push_back(localName
);
829 lg
->WriteMakeRule(ruleFileStream
, "Prepare target for install.",
830 "preinstall", depends
, commands
, true);
834 // add the clean rule
835 localName
= lg
->GetRelativeTargetDirectory(t
->second
);
836 makeTargetName
= localName
;
837 makeTargetName
+= "/clean";
840 commands
.push_back(lg
->GetRecursiveMakeCall
841 (makefileName
.c_str(), makeTargetName
.c_str()));
842 lg
->WriteMakeRule(ruleFileStream
, "clean rule for target.",
843 makeTargetName
.c_str(), depends
, commands
, true);
845 depends
.push_back(makeTargetName
);
846 lg
->WriteMakeRule(ruleFileStream
, "clean rule for target.",
847 "clean", depends
, commands
, true);
852 //----------------------------------------------------------------------------
853 int cmGlobalUnixMakefileGenerator3
854 ::GetTargetTotalNumberOfActions(cmTarget
&target
,
855 std::set
<cmTarget
*> &emitted
)
857 // do not double count
860 if(emitted
.insert(&target
).second
)
862 cmLocalUnixMakefileGenerator3
*lg
=
863 static_cast<cmLocalUnixMakefileGenerator3
*>
864 (target
.GetMakefile()->GetLocalGenerator());
865 result
= static_cast<int>(lg
->ProgressFiles
[target
.GetName()].size());
867 TargetDependSet
& depends
= this->GetTargetDirectDepends(target
);
869 TargetDependSet::iterator i
;
870 for (i
= depends
.begin(); i
!= depends
.end(); ++i
)
872 result
+= this->GetTargetTotalNumberOfActions(**i
, emitted
);
879 unsigned long cmGlobalUnixMakefileGenerator3
880 ::GetNumberOfProgressActionsInAll(cmLocalUnixMakefileGenerator3
*lg
)
882 unsigned long result
= 0;
883 std::set
<cmTarget
*> emitted
;
884 std::set
<cmTarget
*>& targets
= this->LocalGeneratorToTargetMap
[lg
];
885 for(std::set
<cmTarget
*>::iterator t
= targets
.begin();
886 t
!= targets
.end(); ++t
)
888 result
+= this->GetTargetTotalNumberOfActions(**t
,emitted
);
894 //----------------------------------------------------------------------------
896 cmGlobalUnixMakefileGenerator3
897 ::AppendGlobalTargetDepends(std::vector
<std::string
>& depends
,
900 TargetDependSet
const& depends_set
= this->GetTargetDirectDepends(target
);
901 for(TargetDependSet::const_iterator i
= depends_set
.begin();
902 i
!= depends_set
.end(); ++i
)
904 // Create the target-level dependency.
905 cmTarget
const* dep
= *i
;
906 cmLocalUnixMakefileGenerator3
* lg3
=
907 static_cast<cmLocalUnixMakefileGenerator3
*>
908 (dep
->GetMakefile()->GetLocalGenerator());
909 std::string tgtName
= lg3
->GetRelativeTargetDirectory(*dep
);
911 depends
.push_back(tgtName
);
915 //----------------------------------------------------------------------------
916 void cmGlobalUnixMakefileGenerator3::WriteHelpRule
917 (std::ostream
& ruleFileStream
, cmLocalUnixMakefileGenerator3
*lg
)
919 // add the help target
921 std::vector
<std::string
> no_depends
;
922 std::vector
<std::string
> commands
;
923 lg
->AppendEcho(commands
,"The following are some of the valid targets "
924 "for this Makefile:");
925 lg
->AppendEcho(commands
,"... all (the default if no target is provided)");
926 lg
->AppendEcho(commands
,"... clean");
927 lg
->AppendEcho(commands
,"... depend");
929 // Keep track of targets already listed.
930 std::set
<cmStdString
> emittedTargets
;
932 // for each local generator
934 cmLocalUnixMakefileGenerator3
*lg2
;
935 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
938 static_cast<cmLocalUnixMakefileGenerator3
*>(this->LocalGenerators
[i
]);
939 // for the passed in makefile or if this is the top Makefile wripte out
941 if (lg2
== lg
|| !lg
->GetParent())
943 // for each target Generate the rule files for each target.
944 cmTargets
& targets
= lg2
->GetMakefile()->GetTargets();
945 for(cmTargets::iterator t
= targets
.begin(); t
!= targets
.end(); ++t
)
947 if((t
->second
.GetType() == cmTarget::EXECUTABLE
) ||
948 (t
->second
.GetType() == cmTarget::STATIC_LIBRARY
) ||
949 (t
->second
.GetType() == cmTarget::SHARED_LIBRARY
) ||
950 (t
->second
.GetType() == cmTarget::MODULE_LIBRARY
) ||
951 (t
->second
.GetType() == cmTarget::GLOBAL_TARGET
) ||
952 (t
->second
.GetType() == cmTarget::UTILITY
))
954 if(emittedTargets
.insert(t
->second
.GetName()).second
)
957 path
+= t
->second
.GetName();
958 lg
->AppendEcho(commands
,path
.c_str());
964 std::vector
<cmStdString
> const& localHelp
= lg
->GetLocalHelp();
965 for(std::vector
<cmStdString
>::const_iterator o
= localHelp
.begin();
966 o
!= localHelp
.end(); ++o
)
970 lg
->AppendEcho(commands
, path
.c_str());
972 lg
->WriteMakeRule(ruleFileStream
, "Help Target",
974 no_depends
, commands
, true);
975 ruleFileStream
<< "\n\n";
979 bool cmGlobalUnixMakefileGenerator3
980 ::NeedRequiresStep(cmTarget
const& target
)
982 std::set
<cmStdString
> languages
;
983 target
.GetLanguages(languages
);
984 for(std::set
<cmStdString
>::const_iterator l
= languages
.begin();
985 l
!= languages
.end(); ++l
)
987 std::string var
= "CMAKE_NEEDS_REQUIRES_STEP_";
990 if(target
.GetMakefile()->GetDefinition(var
.c_str()))