mirror of
https://github.com/reactos/CMake.git
synced 2024-12-15 07:41:15 +00:00
4878c00905
"imported" executable target. This can then be used e.g. with ADD_CUSTOM_COMMAND() to generate stuff. It adds a second container for "imported" targets, and FindTarget() now takes an additional argument bool useImportedTargets to specify whether you also want to search in the imported targets or only in the "normal" targets. Alex
1184 lines
41 KiB
C++
1184 lines
41 KiB
C++
/*=========================================================================
|
|
|
|
Program: CMake - Cross-Platform Makefile Generator3
|
|
Module: $RCSfile$
|
|
Language: C++
|
|
Date: $Date$
|
|
Version: $Revision$
|
|
|
|
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
|
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notices for more information.
|
|
|
|
=========================================================================*/
|
|
|
|
#include "cmGlobalUnixMakefileGenerator3.h"
|
|
#include "cmLocalUnixMakefileGenerator3.h"
|
|
#include "cmMakefile.h"
|
|
#include "cmake.h"
|
|
#include "cmGeneratedFileStream.h"
|
|
#include "cmSourceFile.h"
|
|
#include "cmTarget.h"
|
|
|
|
cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
|
|
{
|
|
// This type of makefile always requires unix style paths
|
|
this->ForceUnixPaths = true;
|
|
this->FindMakeProgramFile = "CMakeUnixFindMake.cmake";
|
|
this->ToolSupportsColor = true;
|
|
#ifdef _WIN32
|
|
this->UseLinkScript = false;
|
|
#else
|
|
this->UseLinkScript = true;
|
|
#endif
|
|
}
|
|
|
|
void cmGlobalUnixMakefileGenerator3
|
|
::EnableLanguage(std::vector<std::string>const& languages, cmMakefile *mf)
|
|
{
|
|
this->cmGlobalGenerator::EnableLanguage(languages, mf);
|
|
std::string path;
|
|
for(std::vector<std::string>::const_iterator l = languages.begin();
|
|
l != languages.end(); ++l)
|
|
{
|
|
if(*l == "NONE")
|
|
{
|
|
continue;
|
|
}
|
|
const char* lang = l->c_str();
|
|
std::string langComp = "CMAKE_";
|
|
langComp += lang;
|
|
langComp += "_COMPILER";
|
|
|
|
if(!mf->GetDefinition(langComp.c_str()))
|
|
{
|
|
cmSystemTools::Error(langComp.c_str(),
|
|
" not set, after EnableLanguage");
|
|
continue;
|
|
}
|
|
const char* name = mf->GetRequiredDefinition(langComp.c_str());
|
|
if(!cmSystemTools::FileIsFullPath(name))
|
|
{
|
|
path = cmSystemTools::FindProgram(name);
|
|
}
|
|
else
|
|
{
|
|
path = name;
|
|
}
|
|
if(path.size() == 0 || !cmSystemTools::FileExists(path.c_str()))
|
|
{
|
|
std::string message = "your ";
|
|
message += lang;
|
|
message += " compiler: \"";
|
|
message += name;
|
|
message += "\" was not found. Please set ";
|
|
message += langComp;
|
|
message += " to a valid compiler path or name.";
|
|
cmSystemTools::Error(message.c_str());
|
|
path = name;
|
|
}
|
|
std::string doc = lang;
|
|
doc += " compiler.";
|
|
mf->AddCacheDefinition(langComp.c_str(), path.c_str(),
|
|
doc.c_str(), cmCacheManager::FILEPATH);
|
|
}
|
|
}
|
|
|
|
///! Create a local generator appropriate to this Global Generator
|
|
cmLocalGenerator *cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
|
|
{
|
|
cmLocalGenerator* lg = new cmLocalUnixMakefileGenerator3;
|
|
lg->SetGlobalGenerator(this);
|
|
return lg;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmGlobalUnixMakefileGenerator3
|
|
::GetDocumentation(cmDocumentationEntry& entry) const
|
|
{
|
|
entry.name = this->GetName();
|
|
entry.brief = "Generates standard UNIX makefiles.";
|
|
entry.full =
|
|
"A hierarchy of UNIX makefiles is generated into the build tree. Any "
|
|
"standard UNIX-style make program can build the project through the "
|
|
"default make target. A \"make install\" target is also provided.";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
cmGlobalUnixMakefileGenerator3
|
|
::AddMultipleOutputPair(const char* depender, const char* dependee)
|
|
{
|
|
MultipleOutputPairsType::value_type p(depender, dependee);
|
|
this->MultipleOutputPairs.insert(p);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmGlobalUnixMakefileGenerator3::Generate()
|
|
{
|
|
// first do superclass method
|
|
this->cmGlobalGenerator::Generate();
|
|
|
|
// initialize progress
|
|
unsigned int i;
|
|
unsigned long total = 0;
|
|
for (i = 0; i < this->LocalGenerators.size(); ++i)
|
|
{
|
|
cmLocalUnixMakefileGenerator3 *lg =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
|
|
total += lg->GetNumberOfProgressActions();
|
|
}
|
|
|
|
// write each target's progress.make this loop is done twice. Bascially the
|
|
// Generate pass counts all the actions, the first loop below determines
|
|
// how many actions have progress updates for each target and writes to
|
|
// corrrect variable values for everything except the all targets. The
|
|
// second loop actually writes out correct values for the all targets as
|
|
// well. This is because the all targets require more information that is
|
|
// computed in the first loop.
|
|
unsigned long current = 0;
|
|
for (i = 0; i < this->LocalGenerators.size(); ++i)
|
|
{
|
|
cmLocalUnixMakefileGenerator3 *lg =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
|
|
lg->WriteProgressVariables(total,current);
|
|
}
|
|
for (i = 0; i < this->LocalGenerators.size(); ++i)
|
|
{
|
|
cmLocalUnixMakefileGenerator3 *lg =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
|
|
lg->WriteAllProgressVariable();
|
|
}
|
|
|
|
// write the main makefile
|
|
this->WriteMainMakefile2();
|
|
this->WriteMainCMakefile();
|
|
}
|
|
|
|
void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
|
|
{
|
|
// Open the output file. This should not be copy-if-different
|
|
// because the check-build-system step compares the makefile time to
|
|
// see if the build system must be regenerated.
|
|
std::string makefileName =
|
|
this->GetCMakeInstance()->GetHomeOutputDirectory();
|
|
makefileName += cmake::GetCMakeFilesDirectory();
|
|
makefileName += "/Makefile2";
|
|
cmGeneratedFileStream makefileStream(makefileName.c_str());
|
|
if(!makefileStream)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// get a local generator for some useful methods
|
|
cmLocalUnixMakefileGenerator3 *lg =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
|
|
|
|
// Write the do not edit header.
|
|
lg->WriteDisclaimer(makefileStream);
|
|
|
|
// Write the main entry point target. This must be the VERY first
|
|
// target so that make with no arguments will run it.
|
|
// Just depend on the all target to drive the build.
|
|
std::vector<std::string> depends;
|
|
std::vector<std::string> no_commands;
|
|
depends.push_back("all");
|
|
|
|
// Write the rule.
|
|
lg->WriteMakeRule(makefileStream,
|
|
"Default target executed when no arguments are "
|
|
"given to make.",
|
|
"default_target",
|
|
depends,
|
|
no_commands, true);
|
|
|
|
depends.clear();
|
|
|
|
// The all and preinstall rules might never have any dependencies
|
|
// added to them.
|
|
if(this->EmptyRuleHackDepends != "")
|
|
{
|
|
depends.push_back(this->EmptyRuleHackDepends);
|
|
}
|
|
|
|
// Write and empty all:
|
|
lg->WriteMakeRule(makefileStream,
|
|
"The main recursive all target", "all",
|
|
depends, no_commands, true);
|
|
|
|
// Write an empty preinstall:
|
|
lg->WriteMakeRule(makefileStream,
|
|
"The main recursive preinstall target", "preinstall",
|
|
depends, no_commands, true);
|
|
|
|
// Write out the "special" stuff
|
|
lg->WriteSpecialTargetsTop(makefileStream);
|
|
|
|
// write the target convenience rules
|
|
unsigned int i;
|
|
for (i = 0; i < this->LocalGenerators.size(); ++i)
|
|
{
|
|
lg =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
|
|
// are any parents excluded
|
|
bool exclude = false;
|
|
cmLocalGenerator *lg3 = lg;
|
|
while (lg3)
|
|
{
|
|
if (lg3->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
|
|
{
|
|
exclude = true;
|
|
break;
|
|
}
|
|
lg3 = lg3->GetParent();
|
|
}
|
|
this->WriteConvenienceRules2(makefileStream,lg,exclude);
|
|
}
|
|
|
|
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
|
|
lg->WriteSpecialTargetsBottom(makefileStream);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
|
|
{
|
|
// Open the output file. This should not be copy-if-different
|
|
// because the check-build-system step compares the makefile time to
|
|
// see if the build system must be regenerated.
|
|
std::string cmakefileName =
|
|
this->GetCMakeInstance()->GetHomeOutputDirectory();
|
|
cmakefileName += cmake::GetCMakeFilesDirectory();
|
|
cmakefileName += "/Makefile.cmake";
|
|
cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
|
|
if(!cmakefileStream)
|
|
{
|
|
return;
|
|
}
|
|
|
|
std::string makefileName =
|
|
this->GetCMakeInstance()->GetHomeOutputDirectory();
|
|
makefileName += "/Makefile";
|
|
|
|
// get a local generator for some useful methods
|
|
cmLocalUnixMakefileGenerator3 *lg =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
|
|
|
|
// Write the do not edit header.
|
|
lg->WriteDisclaimer(cmakefileStream);
|
|
|
|
// Save the generator name
|
|
cmakefileStream
|
|
<< "# The generator used is:\n"
|
|
<< "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
|
|
|
|
// for each cmMakefile get its list of dependencies
|
|
std::vector<std::string> lfiles;
|
|
for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
|
|
{
|
|
lg =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
|
|
|
|
// Get the list of files contributing to this generation step.
|
|
lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
|
|
lg->GetMakefile()->GetListFiles().end());
|
|
}
|
|
// Sort the list and remove duplicates.
|
|
std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
|
|
std::vector<std::string>::iterator new_end =
|
|
std::unique(lfiles.begin(),lfiles.end());
|
|
lfiles.erase(new_end, lfiles.end());
|
|
|
|
// reset lg to the first makefile
|
|
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
|
|
|
|
// Build the path to the cache file.
|
|
std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
|
|
cache += "/CMakeCache.txt";
|
|
|
|
// Save the list to the cmake file.
|
|
cmakefileStream
|
|
<< "# The top level Makefile was generated from the following files:\n"
|
|
<< "SET(CMAKE_MAKEFILE_DEPENDS\n"
|
|
<< " \""
|
|
<< lg->Convert(cache.c_str(),
|
|
cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
|
|
for(std::vector<std::string>::const_iterator i = lfiles.begin();
|
|
i != lfiles.end(); ++i)
|
|
{
|
|
cmakefileStream
|
|
<< " \""
|
|
<< lg->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT).c_str()
|
|
<< "\"\n";
|
|
}
|
|
cmakefileStream
|
|
<< " )\n\n";
|
|
|
|
// Build the path to the cache check file.
|
|
std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
|
|
check += cmake::GetCMakeFilesDirectory();
|
|
check += "/cmake.check_cache";
|
|
|
|
// Set the corresponding makefile in the cmake file.
|
|
cmakefileStream
|
|
<< "# The corresponding makefile is:\n"
|
|
<< "SET(CMAKE_MAKEFILE_OUTPUTS\n"
|
|
<< " \""
|
|
<< lg->Convert(makefileName.c_str(),
|
|
cmLocalGenerator::START_OUTPUT).c_str() << "\"\n"
|
|
<< " \""
|
|
<< lg->Convert(check.c_str(),
|
|
cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
|
|
|
|
// add in all the directory information files
|
|
std::string tmpStr;
|
|
for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
|
|
{
|
|
lg =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
|
|
tmpStr = lg->GetMakefile()->GetStartOutputDirectory();
|
|
tmpStr += cmake::GetCMakeFilesDirectory();
|
|
tmpStr += "/CMakeDirectoryInformation.cmake";
|
|
cmakefileStream << " \"" <<
|
|
lg->Convert(tmpStr.c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
|
|
<< "\"\n";
|
|
const std::vector<std::string>& outfiles =
|
|
lg->GetMakefile()->GetOutputFiles();
|
|
for(std::vector<std::string>::const_iterator k= outfiles.begin();
|
|
k != outfiles.end(); ++k)
|
|
{
|
|
cmakefileStream << " \"" <<
|
|
lg->Convert(k->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
|
|
<< "\"\n";
|
|
}
|
|
}
|
|
cmakefileStream << " )\n\n";
|
|
|
|
this->WriteMainCMakefileLanguageRules(cmakefileStream,
|
|
this->LocalGenerators);
|
|
|
|
if(!this->MultipleOutputPairs.empty())
|
|
{
|
|
cmakefileStream
|
|
<< "\n"
|
|
<< "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
|
|
for(MultipleOutputPairsType::const_iterator pi =
|
|
this->MultipleOutputPairs.begin();
|
|
pi != this->MultipleOutputPairs.end(); ++pi)
|
|
{
|
|
cmakefileStream << " \"" << pi->first << "\" \""
|
|
<< pi->second << "\"\n";
|
|
}
|
|
cmakefileStream << " )\n\n";
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmGlobalUnixMakefileGenerator3::CheckMultipleOutputs(cmMakefile* mf,
|
|
bool verbose)
|
|
{
|
|
// Get the string listing the multiple output pairs.
|
|
const char* pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
|
|
if(!pairs_string)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Convert the string to a list and preserve empty entries.
|
|
std::vector<std::string> pairs;
|
|
cmSystemTools::ExpandListArgument(pairs_string, pairs, true);
|
|
for(std::vector<std::string>::const_iterator i = pairs.begin();
|
|
i != pairs.end(); ++i)
|
|
{
|
|
const std::string& depender = *i;
|
|
if(++i != pairs.end())
|
|
{
|
|
const std::string& dependee = *i;
|
|
|
|
// If the depender is missing then delete the dependee to make
|
|
// sure both will be regenerated.
|
|
if(cmSystemTools::FileExists(dependee.c_str()) &&
|
|
!cmSystemTools::FileExists(depender.c_str()))
|
|
{
|
|
if(verbose)
|
|
{
|
|
cmOStringStream msg;
|
|
msg << "Deleting primary custom command output \"" << dependee
|
|
<< "\" because another output \""
|
|
<< depender << "\" does not exist." << std::endl;
|
|
cmSystemTools::Stdout(msg.str().c_str());
|
|
}
|
|
cmSystemTools::RemoveFile(dependee.c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void cmGlobalUnixMakefileGenerator3
|
|
::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
|
|
std::vector<cmLocalGenerator *> &lGenerators
|
|
)
|
|
{
|
|
cmLocalUnixMakefileGenerator3 *lg;
|
|
|
|
// now list all the target info files
|
|
cmakefileStream
|
|
<< "# The set of files whose dependency integrity should be checked:\n";
|
|
cmakefileStream
|
|
<< "SET(CMAKE_DEPEND_INFO_FILES\n";
|
|
for (unsigned int i = 0; i < lGenerators.size(); ++i)
|
|
{
|
|
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
|
|
// for all of out targets
|
|
for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
|
|
l != lg->GetMakefile()->GetTargets().end(); l++)
|
|
{
|
|
if((l->second.GetType() == cmTarget::EXECUTABLE) ||
|
|
(l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
|
|
(l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
|
|
(l->second.GetType() == cmTarget::MODULE_LIBRARY) )
|
|
{
|
|
std::string tname = lg->GetRelativeTargetDirectory(l->second);
|
|
tname += "/DependInfo.cmake";
|
|
cmSystemTools::ConvertToUnixSlashes(tname);
|
|
cmakefileStream << " \"" << tname.c_str() << "\"\n";
|
|
}
|
|
}
|
|
}
|
|
cmakefileStream << " )\n";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
cmGlobalUnixMakefileGenerator3
|
|
::WriteDirectoryRule2(std::ostream& ruleFileStream,
|
|
cmLocalUnixMakefileGenerator3* lg,
|
|
const char* pass, bool check_all,
|
|
bool check_relink)
|
|
{
|
|
// Get the relative path to the subdirectory from the top.
|
|
std::string makeTarget = lg->GetMakefile()->GetStartOutputDirectory();
|
|
makeTarget += "/";
|
|
makeTarget += pass;
|
|
|
|
// The directory-level rule should depend on the target-level rules
|
|
// for all targets in the directory.
|
|
std::vector<std::string> depends;
|
|
for(cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
|
|
l != lg->GetMakefile()->GetTargets().end(); ++l)
|
|
{
|
|
if((l->second.GetType() == cmTarget::EXECUTABLE) ||
|
|
(l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
|
|
(l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
|
|
(l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
|
|
(l->second.GetType() == cmTarget::UTILITY))
|
|
{
|
|
// Add this to the list of depends rules in this directory.
|
|
if((!check_all || !l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
|
|
(!check_relink || l->second.NeedRelinkBeforeInstall()))
|
|
{
|
|
std::string tname = lg->GetRelativeTargetDirectory(l->second);
|
|
tname += "/";
|
|
tname += pass;
|
|
depends.push_back(tname);
|
|
}
|
|
}
|
|
}
|
|
|
|
// The directory-level rule should depend on the directory-level
|
|
// rules of the subdirectories.
|
|
for(std::vector<cmLocalGenerator*>::iterator sdi =
|
|
lg->GetChildren().begin(); sdi != lg->GetChildren().end(); ++sdi)
|
|
{
|
|
cmLocalUnixMakefileGenerator3* slg =
|
|
static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
|
|
std::string subdir = slg->GetMakefile()->GetStartOutputDirectory();
|
|
subdir += "/";
|
|
subdir += pass;
|
|
depends.push_back(subdir);
|
|
}
|
|
|
|
// Work-around for makes that drop rules that have no dependencies
|
|
// or commands.
|
|
if(depends.empty() && this->EmptyRuleHackDepends != "")
|
|
{
|
|
depends.push_back(this->EmptyRuleHackDepends);
|
|
}
|
|
|
|
// Write the rule.
|
|
std::string doc = "Convenience name for \"";
|
|
doc += pass;
|
|
doc += "\" pass in the directory.";
|
|
std::vector<std::string> no_commands;
|
|
lg->WriteMakeRule(ruleFileStream, doc.c_str(),
|
|
makeTarget.c_str(), depends, no_commands, true);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
cmGlobalUnixMakefileGenerator3
|
|
::WriteDirectoryRules2(std::ostream& ruleFileStream,
|
|
cmLocalUnixMakefileGenerator3* lg)
|
|
{
|
|
// Only subdirectories need these rules.
|
|
if(!lg->GetParent())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Begin the directory-level rules section.
|
|
std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
|
|
dir = lg->Convert(dir.c_str(), cmLocalGenerator::HOME_OUTPUT,
|
|
cmLocalGenerator::MAKEFILE);
|
|
lg->WriteDivider(ruleFileStream);
|
|
ruleFileStream
|
|
<< "# Directory level rules for directory "
|
|
<< dir << "\n\n";
|
|
|
|
// Write directory-level rules for "all".
|
|
this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
|
|
|
|
// Write directory-level rules for "clean".
|
|
this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false);
|
|
|
|
// Write directory-level rules for "preinstall".
|
|
this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", false, true);
|
|
}
|
|
|
|
|
|
std::string cmGlobalUnixMakefileGenerator3
|
|
::GenerateBuildCommand(const char* makeProgram, const char *projectName,
|
|
const char* additionalOptions, const char *targetName,
|
|
const char* config, bool ignoreErrors, bool fast)
|
|
{
|
|
// Project name and config are not used yet.
|
|
(void)projectName;
|
|
(void)config;
|
|
|
|
std::string makeCommand =
|
|
cmSystemTools::ConvertToUnixOutputPath(makeProgram);
|
|
|
|
// Since we have full control over the invocation of nmake, let us
|
|
// make it quiet.
|
|
if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
|
|
{
|
|
makeCommand += " /NOLOGO ";
|
|
}
|
|
if ( ignoreErrors )
|
|
{
|
|
makeCommand += " -i";
|
|
}
|
|
if ( additionalOptions )
|
|
{
|
|
makeCommand += " ";
|
|
makeCommand += additionalOptions;
|
|
}
|
|
if ( targetName && strlen(targetName))
|
|
{
|
|
cmLocalUnixMakefileGenerator3 *lg;
|
|
if (this->LocalGenerators.size())
|
|
{
|
|
lg = static_cast<cmLocalUnixMakefileGenerator3 *>
|
|
(this->LocalGenerators[0]);
|
|
}
|
|
else
|
|
{
|
|
lg = static_cast<cmLocalUnixMakefileGenerator3 *>
|
|
(this->CreateLocalGenerator());
|
|
// set the Start directories
|
|
lg->GetMakefile()->SetStartDirectory
|
|
(this->CMakeInstance->GetStartDirectory());
|
|
lg->GetMakefile()->SetStartOutputDirectory
|
|
(this->CMakeInstance->GetStartOutputDirectory());
|
|
lg->GetMakefile()->MakeStartDirectoriesCurrent();
|
|
}
|
|
|
|
makeCommand += " \"";
|
|
std::string tname = targetName;
|
|
if(fast)
|
|
{
|
|
tname += "/fast";
|
|
}
|
|
tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
|
|
cmLocalGenerator::MAKEFILE);
|
|
makeCommand += tname.c_str();
|
|
makeCommand += "\"";
|
|
if (!this->LocalGenerators.size())
|
|
{
|
|
delete lg;
|
|
}
|
|
}
|
|
return makeCommand;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
cmGlobalUnixMakefileGenerator3
|
|
::WriteConvenienceRules(std::ostream& ruleFileStream,
|
|
std::set<cmStdString> &emitted)
|
|
{
|
|
std::vector<std::string> depends;
|
|
std::vector<std::string> commands;
|
|
|
|
depends.push_back("cmake_check_build_system");
|
|
|
|
// write the target convenience rules
|
|
unsigned int i;
|
|
cmLocalUnixMakefileGenerator3 *lg;
|
|
for (i = 0; i < this->LocalGenerators.size(); ++i)
|
|
{
|
|
lg = static_cast<cmLocalUnixMakefileGenerator3 *>
|
|
(this->LocalGenerators[i]);
|
|
// for each target Generate the rule files for each target.
|
|
cmTargets& targets = lg->GetMakefile()->GetTargets();
|
|
for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
|
|
{
|
|
// Don't emit the same rule twice (e.g. two targets with the same
|
|
// simple name)
|
|
if(t->second.GetName() &&
|
|
strlen(t->second.GetName()) &&
|
|
emitted.insert(t->second.GetName()).second &&
|
|
// Handle user targets here. Global targets are handled in
|
|
// the local generator on a per-directory basis.
|
|
((t->second.GetType() == cmTarget::EXECUTABLE) ||
|
|
(t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
|
|
(t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
|
|
(t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
|
|
(t->second.GetType() == cmTarget::UTILITY)))
|
|
{
|
|
// Add a rule to build the target by name.
|
|
lg->WriteDivider(ruleFileStream);
|
|
ruleFileStream
|
|
<< "# Target rules for targets named "
|
|
<< t->second.GetName() << "\n\n";
|
|
|
|
// Write the rule.
|
|
commands.clear();
|
|
std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
|
|
tmp += "Makefile2";
|
|
commands.push_back(lg->GetRecursiveMakeCall
|
|
(tmp.c_str(),t->second.GetName()));
|
|
depends.clear();
|
|
depends.push_back("cmake_check_build_system");
|
|
lg->WriteMakeRule(ruleFileStream,
|
|
"Build rule for target.",
|
|
t->second.GetName(), depends, commands,
|
|
true);
|
|
|
|
// Add a fast rule to build the target
|
|
std::string localName = lg->GetRelativeTargetDirectory(t->second);
|
|
std::string makefileName;
|
|
makefileName = localName;
|
|
makefileName += "/build.make";
|
|
depends.clear();
|
|
commands.clear();
|
|
std::string makeTargetName = localName;
|
|
makeTargetName += "/build";
|
|
localName = t->second.GetName();
|
|
localName += "/fast";
|
|
commands.push_back(lg->GetRecursiveMakeCall
|
|
(makefileName.c_str(), makeTargetName.c_str()));
|
|
lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
|
|
localName.c_str(), depends, commands, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
cmGlobalUnixMakefileGenerator3
|
|
::WriteConvenienceRules2(std::ostream& ruleFileStream,
|
|
cmLocalUnixMakefileGenerator3 *lg,
|
|
bool exclude)
|
|
{
|
|
std::vector<std::string> depends;
|
|
std::vector<std::string> commands;
|
|
std::string localName;
|
|
std::string makeTargetName;
|
|
|
|
|
|
// write the directory level rules for this local gen
|
|
this->WriteDirectoryRules2(ruleFileStream,lg);
|
|
|
|
depends.push_back("cmake_check_build_system");
|
|
|
|
// for each target Generate the rule files for each target.
|
|
cmTargets& targets = lg->GetMakefile()->GetTargets();
|
|
for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
|
|
{
|
|
if (t->second.GetName()
|
|
&& strlen(t->second.GetName())
|
|
&& ((t->second.GetType() == cmTarget::EXECUTABLE)
|
|
|| (t->second.GetType() == cmTarget::STATIC_LIBRARY)
|
|
|| (t->second.GetType() == cmTarget::SHARED_LIBRARY)
|
|
|| (t->second.GetType() == cmTarget::MODULE_LIBRARY)
|
|
|| (t->second.GetType() == cmTarget::UTILITY)))
|
|
{
|
|
std::string makefileName;
|
|
// Add a rule to build the target by name.
|
|
localName = lg->GetRelativeTargetDirectory(t->second);
|
|
makefileName = localName;
|
|
makefileName += "/build.make";
|
|
|
|
bool needRequiresStep =
|
|
this->NeedRequiresStep(lg,t->second.GetName());
|
|
|
|
lg->WriteDivider(ruleFileStream);
|
|
ruleFileStream
|
|
<< "# Target rules for target "
|
|
<< localName << "\n\n";
|
|
|
|
commands.clear();
|
|
if (t->second.GetType() != cmTarget::UTILITY)
|
|
{
|
|
makeTargetName = localName;
|
|
makeTargetName += "/depend";
|
|
commands.push_back(lg->GetRecursiveMakeCall
|
|
(makefileName.c_str(),makeTargetName.c_str()));
|
|
|
|
// add requires if we need it for this generator
|
|
if (needRequiresStep)
|
|
{
|
|
makeTargetName = localName;
|
|
makeTargetName += "/requires";
|
|
commands.push_back(lg->GetRecursiveMakeCall
|
|
(makefileName.c_str(),makeTargetName.c_str()));
|
|
}
|
|
}
|
|
makeTargetName = localName;
|
|
makeTargetName += "/build";
|
|
commands.push_back(lg->GetRecursiveMakeCall
|
|
(makefileName.c_str(),makeTargetName.c_str()));
|
|
|
|
// Write the rule.
|
|
localName += "/all";
|
|
depends.clear();
|
|
|
|
std::string progressDir =
|
|
lg->GetMakefile()->GetHomeOutputDirectory();
|
|
progressDir += cmake::GetCMakeFilesDirectory();
|
|
{
|
|
cmOStringStream progCmd;
|
|
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
|
|
// all target counts
|
|
progCmd << lg->Convert(progressDir.c_str(),
|
|
cmLocalGenerator::FULL,
|
|
cmLocalGenerator::SHELL);
|
|
progCmd << " ";
|
|
std::vector<int> &progFiles = lg->ProgressFiles[t->first];
|
|
for (std::vector<int>::iterator i = progFiles.begin();
|
|
i != progFiles.end(); ++i)
|
|
{
|
|
progCmd << " " << *i;
|
|
}
|
|
commands.push_back(progCmd.str());
|
|
}
|
|
progressDir = "Built target ";
|
|
progressDir += t->first;
|
|
lg->AppendEcho(commands,progressDir.c_str());
|
|
|
|
this->AppendGlobalTargetDepends(depends,t->second);
|
|
lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
|
|
localName.c_str(), depends, commands, true);
|
|
|
|
// add the all/all dependency
|
|
if (!exclude && !t->second.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
|
|
{
|
|
depends.clear();
|
|
depends.push_back(localName);
|
|
commands.clear();
|
|
lg->WriteMakeRule(ruleFileStream, "Include target in all.",
|
|
"all", depends, commands, true);
|
|
}
|
|
|
|
// Write the rule.
|
|
commands.clear();
|
|
progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
|
|
progressDir += cmake::GetCMakeFilesDirectory();
|
|
|
|
{
|
|
// TODO: Convert the total progress count to a make variable.
|
|
cmOStringStream progCmd;
|
|
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
|
|
// # in target
|
|
progCmd << lg->Convert(progressDir.c_str(),
|
|
cmLocalGenerator::FULL,
|
|
cmLocalGenerator::SHELL);
|
|
//
|
|
std::set<cmStdString> emitted;
|
|
progCmd << " "
|
|
<< this->GetTargetTotalNumberOfActions(t->second,
|
|
emitted);
|
|
commands.push_back(progCmd.str());
|
|
}
|
|
std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
|
|
tmp += "Makefile2";
|
|
commands.push_back(lg->GetRecursiveMakeCall
|
|
(tmp.c_str(),localName.c_str()));
|
|
{
|
|
cmOStringStream progCmd;
|
|
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
|
|
progCmd << lg->Convert(progressDir.c_str(),
|
|
cmLocalGenerator::FULL,
|
|
cmLocalGenerator::SHELL);
|
|
progCmd << " 0";
|
|
commands.push_back(progCmd.str());
|
|
}
|
|
depends.clear();
|
|
depends.push_back("cmake_check_build_system");
|
|
localName = lg->GetRelativeTargetDirectory(t->second);
|
|
localName += "/rule";
|
|
lg->WriteMakeRule(ruleFileStream,
|
|
"Build rule for subdir invocation for target.",
|
|
localName.c_str(), depends, commands, true);
|
|
|
|
// Add a target with the canonical name (no prefix, suffix or path).
|
|
commands.clear();
|
|
depends.clear();
|
|
depends.push_back(localName);
|
|
lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
|
|
t->second.GetName(), depends, commands, true);
|
|
|
|
// Add rules to prepare the target for installation.
|
|
if(t->second.NeedRelinkBeforeInstall())
|
|
{
|
|
localName = lg->GetRelativeTargetDirectory(t->second);
|
|
localName += "/preinstall";
|
|
depends.clear();
|
|
commands.clear();
|
|
commands.push_back(lg->GetRecursiveMakeCall
|
|
(makefileName.c_str(), localName.c_str()));
|
|
lg->WriteMakeRule(ruleFileStream,
|
|
"Pre-install relink rule for target.",
|
|
localName.c_str(), depends, commands, true);
|
|
depends.clear();
|
|
depends.push_back(localName);
|
|
commands.clear();
|
|
lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
|
|
"preinstall", depends, commands, true);
|
|
}
|
|
|
|
// add the clean rule
|
|
localName = lg->GetRelativeTargetDirectory(t->second);
|
|
makeTargetName = localName;
|
|
makeTargetName += "/clean";
|
|
depends.clear();
|
|
commands.clear();
|
|
commands.push_back(lg->GetRecursiveMakeCall
|
|
(makefileName.c_str(), makeTargetName.c_str()));
|
|
lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
|
|
makeTargetName.c_str(), depends, commands, true);
|
|
commands.clear();
|
|
depends.push_back(makeTargetName);
|
|
lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
|
|
"clean", depends, commands, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int cmGlobalUnixMakefileGenerator3
|
|
::GetTargetTotalNumberOfActions(cmTarget& target,
|
|
std::set<cmStdString> &emitted)
|
|
{
|
|
// do not double count
|
|
int result = 0;
|
|
|
|
if(emitted.insert(target.GetName()).second)
|
|
{
|
|
cmLocalUnixMakefileGenerator3 *lg =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>
|
|
(target.GetMakefile()->GetLocalGenerator());
|
|
result = static_cast<int>(lg->ProgressFiles[target.GetName()].size());
|
|
|
|
std::vector<cmTarget *>& depends = this->GetTargetDepends(target);
|
|
|
|
std::vector<cmTarget *>::iterator i;
|
|
for (i = depends.begin(); i != depends.end(); ++i)
|
|
{
|
|
result += this->GetTargetTotalNumberOfActions(**i, emitted);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
unsigned long cmGlobalUnixMakefileGenerator3
|
|
::GetNumberOfProgressActionsInAll(cmLocalUnixMakefileGenerator3 *lg)
|
|
{
|
|
unsigned long result = 0;
|
|
|
|
// if this is a project
|
|
if (!lg->GetParent() ||
|
|
strcmp(lg->GetMakefile()->GetProjectName(),
|
|
lg->GetParent()->GetMakefile()->GetProjectName()))
|
|
{
|
|
// use the new project to target map
|
|
std::set<cmTarget*> &targets =
|
|
this->ProjectToTargetMap[lg->GetMakefile()->GetProjectName()];
|
|
std::set<cmTarget*>::iterator t = targets.begin();
|
|
for(; t != targets.end(); ++t)
|
|
{
|
|
cmTarget* target = *t;
|
|
cmLocalUnixMakefileGenerator3 *lg3 =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>
|
|
(target->GetMakefile()->GetLocalGenerator());
|
|
std::vector<int> &progFiles = lg3->ProgressFiles[target->GetName()];
|
|
result += static_cast<unsigned long>(progFiles.size());
|
|
}
|
|
}
|
|
// for subdirectories
|
|
else
|
|
{
|
|
std::deque<cmLocalUnixMakefileGenerator3 *> lg3Stack;
|
|
lg3Stack.push_back(lg);
|
|
std::vector<cmStdString> targetsInAll;
|
|
std::set<cmTarget *> targets;
|
|
while (lg3Stack.size())
|
|
{
|
|
cmLocalUnixMakefileGenerator3 *lg3 = lg3Stack.front();
|
|
lg3Stack.pop_front();
|
|
for(cmTargets::iterator l = lg3->GetMakefile()->GetTargets().begin();
|
|
l != lg3->GetMakefile()->GetTargets().end(); ++l)
|
|
{
|
|
if((l->second.GetType() == cmTarget::EXECUTABLE) ||
|
|
(l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
|
|
(l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
|
|
(l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
|
|
(l->second.GetType() == cmTarget::UTILITY))
|
|
{
|
|
// Add this to the list of depends rules in this directory.
|
|
if (!l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL") &&
|
|
targets.find(&l->second) == targets.end())
|
|
{
|
|
std::deque<cmTarget *> activeTgts;
|
|
activeTgts.push_back(&(l->second));
|
|
// trace depth of target dependencies
|
|
while (activeTgts.size())
|
|
{
|
|
if (targets.find(activeTgts.front()) == targets.end())
|
|
{
|
|
targets.insert(activeTgts.front());
|
|
cmLocalUnixMakefileGenerator3 *lg4 =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>
|
|
(activeTgts.front()->GetMakefile()->GetLocalGenerator());
|
|
std::vector<int> &progFiles2 =
|
|
lg4->ProgressFiles[activeTgts.front()->GetName()];
|
|
result += static_cast<unsigned long>(progFiles2.size());
|
|
std::vector<cmTarget *> deps2 =
|
|
this->GetTargetDepends(*activeTgts.front());
|
|
for (std::vector<cmTarget *>::const_iterator di =
|
|
deps2.begin(); di != deps2.end(); ++di)
|
|
{
|
|
activeTgts.push_back(*di);
|
|
}
|
|
}
|
|
activeTgts.pop_front();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// The directory-level rule depends on the directory-level
|
|
// rules of the subdirectories.
|
|
for(std::vector<cmLocalGenerator*>::iterator sdi =
|
|
lg3->GetChildren().begin();
|
|
sdi != lg3->GetChildren().end(); ++sdi)
|
|
{
|
|
cmLocalUnixMakefileGenerator3* slg =
|
|
static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
|
|
lg3Stack.push_back(slg);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
cmGlobalUnixMakefileGenerator3
|
|
::AppendGlobalTargetDepends(std::vector<std::string>& depends,
|
|
cmTarget& target)
|
|
{
|
|
// Keep track of dependencies already listed.
|
|
std::set<cmStdString> emitted;
|
|
|
|
// A target should not depend on itself.
|
|
emitted.insert(target.GetName());
|
|
|
|
// Loop over all library dependencies but not for static libs
|
|
if (target.GetType() != cmTarget::STATIC_LIBRARY)
|
|
{
|
|
const cmTarget::LinkLibraryVectorType& tlibs = target.GetLinkLibraries();
|
|
for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
|
|
lib != tlibs.end(); ++lib)
|
|
{
|
|
// Don't emit the same library twice for this target.
|
|
if(emitted.insert(lib->first).second)
|
|
{
|
|
// Add this dependency.
|
|
this->AppendAnyGlobalDepend(depends, lib->first.c_str(),
|
|
emitted, target);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Loop over all utility dependencies.
|
|
const std::set<cmStdString>& tutils = target.GetUtilities();
|
|
for(std::set<cmStdString>::const_iterator util = tutils.begin();
|
|
util != tutils.end(); ++util)
|
|
{
|
|
// Don't emit the same utility twice for this target.
|
|
if(emitted.insert(*util).second)
|
|
{
|
|
// Add this dependency.
|
|
this->AppendAnyGlobalDepend(depends, util->c_str(), emitted, target);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
cmGlobalUnixMakefileGenerator3
|
|
::AppendAnyGlobalDepend(std::vector<std::string>& depends, const char* name,
|
|
std::set<cmStdString>& emitted, cmTarget &target)
|
|
{
|
|
cmTarget *result;
|
|
cmLocalUnixMakefileGenerator3 *lg3;
|
|
|
|
// first check the same dir as the current target
|
|
lg3 = static_cast<cmLocalUnixMakefileGenerator3 *>
|
|
(target.GetMakefile()->GetLocalGenerator());
|
|
result = target.GetMakefile()->FindTarget(name, false);
|
|
|
|
// search each local generator until a match is found
|
|
if (!result)
|
|
{
|
|
result = this->FindTarget(0, name, false);
|
|
if (result)
|
|
{
|
|
lg3 = static_cast<cmLocalUnixMakefileGenerator3 *>
|
|
(result->GetMakefile()->GetLocalGenerator());
|
|
}
|
|
}
|
|
|
|
// if a match was found then ...
|
|
if (result)
|
|
{
|
|
std::string tgtName = lg3->GetRelativeTargetDirectory(*result);
|
|
tgtName += "/all";
|
|
depends.push_back(tgtName);
|
|
if(result->GetType() == cmTarget::STATIC_LIBRARY)
|
|
{
|
|
// Since the static library itself does not list dependencies we
|
|
// need to chain its dependencies here.
|
|
const cmTarget::LinkLibraryVectorType& tlibs
|
|
= result->GetLinkLibraries();
|
|
for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
|
|
lib != tlibs.end(); ++lib)
|
|
{
|
|
// Don't emit the same library twice for this target.
|
|
if(emitted.insert(lib->first).second)
|
|
{
|
|
// Add this dependency.
|
|
this->AppendAnyGlobalDepend(depends, lib->first.c_str(),
|
|
emitted, *result);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmGlobalUnixMakefileGenerator3::WriteHelpRule
|
|
(std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
|
|
{
|
|
// add the help target
|
|
std::string path;
|
|
std::vector<std::string> no_depends;
|
|
std::vector<std::string> commands;
|
|
lg->AppendEcho(commands,"The following are some of the valid targets "
|
|
"for this Makefile:");
|
|
lg->AppendEcho(commands,"... all (the default if no target is provided)");
|
|
lg->AppendEcho(commands,"... clean");
|
|
lg->AppendEcho(commands,"... depend");
|
|
|
|
// Keep track of targets already listed.
|
|
std::set<cmStdString> emittedTargets;
|
|
|
|
// for each local generator
|
|
unsigned int i;
|
|
cmLocalUnixMakefileGenerator3 *lg2;
|
|
for (i = 0; i < this->LocalGenerators.size(); ++i)
|
|
{
|
|
lg2 =
|
|
static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
|
|
// for the passed in makefile or if this is the top Makefile wripte out
|
|
// the targets
|
|
if (lg2 == lg || !lg->GetParent())
|
|
{
|
|
// for each target Generate the rule files for each target.
|
|
cmTargets& targets = lg2->GetMakefile()->GetTargets();
|
|
for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
|
|
{
|
|
if((t->second.GetType() == cmTarget::EXECUTABLE) ||
|
|
(t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
|
|
(t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
|
|
(t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
|
|
(t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
|
|
(t->second.GetType() == cmTarget::UTILITY))
|
|
{
|
|
if(emittedTargets.insert(t->second.GetName()).second)
|
|
{
|
|
path = "... ";
|
|
path += t->second.GetName();
|
|
lg->AppendEcho(commands,path.c_str());
|
|
}
|
|
}
|
|
}
|
|
std::vector<cmStdString> const& localHelp = lg->GetLocalHelp();
|
|
for(std::vector<cmStdString>::const_iterator o = localHelp.begin();
|
|
o != localHelp.end(); ++o)
|
|
{
|
|
path = "... ";
|
|
path += *o;
|
|
lg->AppendEcho(commands, path.c_str());
|
|
}
|
|
}
|
|
}
|
|
lg->WriteMakeRule(ruleFileStream, "Help Target",
|
|
"help:",
|
|
no_depends, commands, true);
|
|
ruleFileStream << "\n\n";
|
|
}
|
|
|
|
|
|
bool cmGlobalUnixMakefileGenerator3
|
|
::NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg,const char *name)
|
|
{
|
|
std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>&
|
|
checkSet = lg->GetIntegrityCheckSet()[name];
|
|
for(std::map<cmStdString,
|
|
cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
|
|
l = checkSet.begin(); l != checkSet.end(); ++l)
|
|
{
|
|
std::string name2 = "CMAKE_NEEDS_REQUIRES_STEP_";
|
|
name2 += l->first;
|
|
name2 += "_FLAG";
|
|
if(lg->GetMakefile()->GetDefinition(name2.c_str()))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|