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