ENH: updates

This commit is contained in:
Ken Martin 2005-05-06 14:49:38 -04:00
parent dc75c22645
commit 0cb20474d8
4 changed files with 650 additions and 643 deletions

View File

@ -90,22 +90,93 @@ void cmGlobalUnixMakefileGenerator3::GetDocumentation(cmDocumentationEntry& entr
"default make target. A \"make install\" target is also provided."; "default make target. A \"make install\" target is also provided.";
} }
//----------------------------------------------------------------------------
void cmGlobalUnixMakefileGenerator3::Generate()
{
// first do superclass method
this->cmGlobalGenerator::Generate();
// write the main makefile
this->WriteMainMakefile();
this->WriteMainCMakefile();
// now write the support Makefiles
this->WriteDependMakefile();
this->WriteBuildMakefile();
this->WriteCleanMakefile();
}
void cmGlobalUnixMakefileGenerator3::WriteMainMakefile()
{
// 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 += "/Makefile";
cmGeneratedFileStream makefileStream(makefileName.c_str());
if(!makefileStream)
{
return;
}
// get a local generator for some useful methods
cmLocalUnixMakefileGenerator3 *lg =
static_cast<cmLocalUnixMakefileGenerator3 *>(m_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);
lg->WriteMakeVariables(makefileStream);
lg->WriteSpecialTargetsTop(makefileStream);
this->WriteAllRules(lg,makefileStream);
// write the target convenience rules
unsigned int i;
for (i = 0; i < m_LocalGenerators.size(); ++i)
{
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
this->WriteConvenienceRules(makefileStream,lg);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
{ {
// Open the output file. This should not be copy-if-different // Open the output file. This should not be copy-if-different
// because the check-build-system step compares the makefile time to // because the check-build-system step compares the makefile time to
// see if the build system must be regenerated. // see if the build system must be regenerated.
std::string cmakefileName = this->GetCMakeInstance()->GetHomeOutputDirectory(); std::string cmakefileName =
this->GetCMakeInstance()->GetHomeOutputDirectory();
cmakefileName += "/Makefile.cmake"; cmakefileName += "/Makefile.cmake";
std::string makefileName = this->GetCMakeInstance()->GetHomeOutputDirectory();
makefileName += "/Makefile";
cmGeneratedFileStream cmakefileStream(cmakefileName.c_str()); cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
if(!cmakefileStream) if(!cmakefileStream)
{ {
return; return;
} }
std::string makefileName =
this->GetCMakeInstance()->GetHomeOutputDirectory();
makefileName += "/Makefile";
// get a local generator for some useful methods // get a local generator for some useful methods
cmLocalUnixMakefileGenerator3 *lg = cmLocalUnixMakefileGenerator3 *lg =
static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]); static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
@ -175,11 +246,19 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
} }
cmakefileStream << " )\n\n"; cmakefileStream << " )\n\n";
this->WriteMainCMakefileLanguageRules(cmakefileStream);
}
void cmGlobalUnixMakefileGenerator3
::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream)
{
cmLocalUnixMakefileGenerator3 *lg;
// now write all the language stuff // now write all the language stuff
// Set the set of files to check for dependency integrity. // Set the set of files to check for dependency integrity.
// loop over all of the local generators to collect this // loop over all of the local generators to collect this
std::set<cmStdString> checkSetLangs; std::set<cmStdString> checkSetLangs;
for (i = 0; i < m_LocalGenerators.size(); ++i) for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
{ {
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]); lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& checkSet = std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& checkSet =
@ -211,7 +290,7 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
cmakefileStream cmakefileStream
<< "SET(CMAKE_DEPENDS_CHECK_" << l->c_str() << "\n"; << "SET(CMAKE_DEPENDS_CHECK_" << l->c_str() << "\n";
// now for each local gen get the checkset // now for each local gen get the checkset
for (i = 0; i < m_LocalGenerators.size(); ++i) for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
{ {
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]); lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
// get the check set for this local gen and language // get the check set for this local gen and language
@ -228,90 +307,6 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
} }
cmakefileStream << " )\n"; cmakefileStream << " )\n";
} }
}
void cmGlobalUnixMakefileGenerator3::WriteMainMakefile()
{
// 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 += "/Makefile";
cmGeneratedFileStream makefileStream(makefileName.c_str());
if(!makefileStream)
{
return;
}
// get a local generator for some useful methods
cmLocalUnixMakefileGenerator3 *lg =
static_cast<cmLocalUnixMakefileGenerator3 *>(m_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);
lg->WriteMakeVariables(makefileStream);
lg->WriteSpecialTargetsTop(makefileStream);
lg->WriteAllRules(makefileStream);
// Write special "cmake_check_build_system" target to run cmake with
// the --check-build-system flag.
// Build command to run CMake to check if anything needs regenerating.
std::string cmakefileName = makefileName;
cmakefileName += ".cmake";
std::string runRule = this->GetCMakeInstance()->GetCacheDefinition("CMAKE_COMMAND");
runRule += " -H";
runRule += this->GetCMakeInstance()->GetHomeDirectory();
runRule += " -B";
runRule += this->GetCMakeInstance()->GetHomeOutputDirectory();
runRule += " --check-build-system ";
runRule += lg->ConvertToRelativeOutputPath(cmakefileName.c_str());
std::vector<std::string> no_depends;
std::vector<std::string> commands;
commands.push_back(runRule);
lg->WriteMakeRule(makefileStream,
"Special rule to run CMake to check the build system "
"integrity.\n"
"No rule that depends on this can have "
"commands that come from listfiles\n"
"because they might be regenerated.",
"cmake_check_build_system",
no_depends,
commands);
// write the target convenience rules
unsigned int i;
for (i = 0; i < m_LocalGenerators.size(); ++i)
{
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
lg->WriteConvenienceRules(makefileStream);
}
}
void cmGlobalUnixMakefileGenerator3::WriteSupportMakefiles()
{
this->WriteDependMakefile();
this->WriteBuildMakefile();
this->WriteCleanMakefile();
} }
void cmGlobalUnixMakefileGenerator3::WriteDependMakefile() void cmGlobalUnixMakefileGenerator3::WriteDependMakefile()
@ -455,15 +450,149 @@ void cmGlobalUnixMakefileGenerator3::WriteCleanMakefile()
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmGlobalUnixMakefileGenerator3::Generate() void cmGlobalUnixMakefileGenerator3
::WriteAllRules(cmLocalUnixMakefileGenerator3 *lg,
std::ostream& makefileStream)
{ {
// first do superclass method // Write section header.
this->cmGlobalGenerator::Generate(); lg->WriteDivider(makefileStream);
makefileStream
<< "# Rules to build dependencies and targets.\n"
<< "\n";
// write the main makefile std::vector<std::string> depends;
this->WriteMainMakefile(); std::vector<std::string> commands;
this->WriteMainCMakefile();
// now write the support Makefiles // Check the build system in this directory.
this->WriteSupportMakefiles(); depends.push_back("cmake_check_build_system");
commands.push_back(this->GetRecursiveMakeCall("depend.make",0));
commands.push_back(this->GetRecursiveMakeCall("build.make",0));
// Write the rule.
lg->WriteMakeRule(makefileStream, "The main all target", "all", depends, commands);
// write the clean
commands.clear();
commands.push_back(this->GetRecursiveMakeCall("clean.make",0));
lg->WriteMakeRule(makefileStream, "default clean target", "clean", depends, commands);
// Write special "cmake_check_build_system" target to run cmake with
// the --check-build-system flag.
// Build command to run CMake to check if anything needs regenerating.
std::string cmakefileName = this->GetCMakeInstance()->GetHomeOutputDirectory();
cmakefileName += "/Makefile.cmake";
std::string runRule = this->GetCMakeInstance()->GetCacheDefinition("CMAKE_COMMAND");
runRule += " -H";
runRule += this->GetCMakeInstance()->GetHomeDirectory();
runRule += " -B";
runRule += this->GetCMakeInstance()->GetHomeOutputDirectory();
runRule += " --check-build-system ";
runRule += lg->ConvertToRelativeOutputPath(cmakefileName.c_str());
std::vector<std::string> no_depends;
commands.clear();
commands.push_back(runRule);
lg->WriteMakeRule(makefileStream,
"Special rule to run CMake to check the build system "
"integrity.\n"
"No rule that depends on this can have "
"commands that come from listfiles\n"
"because they might be regenerated.",
"cmake_check_build_system",
no_depends,
commands);
} }
//----------------------------------------------------------------------------
std::string
cmGlobalUnixMakefileGenerator3
::GetRecursiveMakeCall(const char *Makefile, const char* tgt)
{
cmLocalUnixMakefileGenerator3 *lg =
static_cast<cmLocalUnixMakefileGenerator3*>(m_LocalGenerators[0]);
// Call make on the given file.
std::string cmd;
cmd += "$(MAKE) -f ";
cmd += Makefile;
cmd += " ";
// Pass down verbosity level.
if(lg->GetMakeSilentFlag().size())
{
cmd += lg->GetMakeSilentFlag();
cmd += " ";
}
// Most unix makes will pass the command line flags to make down to
// sub-invoked makes via an environment variable. However, some
// makes do not support that, so you have to pass the flags
// explicitly.
if(lg->GetPassMakeflags())
{
cmd += "-$(MAKEFLAGS) ";
}
// Add the target.
if (tgt && tgt[0] != '\0')
{
cmd += tgt;
}
return cmd;
}
//----------------------------------------------------------------------------
void
cmGlobalUnixMakefileGenerator3
::WriteConvenienceRules(std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
{
std::vector<std::string> depends;
std::vector<std::string> tgt_depends;
std::vector<std::string> commands;
depends.push_back("cmake_check_build_system");
// for each target
// Generate the rule files for each target.
const cmTargets& targets = lg->GetMakefile()->GetTargets();
std::string localName;
std::string makeTargetName;
for(cmTargets::const_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))
{
// Add a rule to build the target by name.
localName = lg->GetRelativeTargetDirectory(t->second);
commands.clear();
makeTargetName = localName;
makeTargetName += "/depend";
commands.push_back(this->GetRecursiveMakeCall("depend.make",makeTargetName.c_str()));
makeTargetName = localName;
makeTargetName += "/build";
commands.push_back(this->GetRecursiveMakeCall("build.make",makeTargetName.c_str()));
// Write the rule.
lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
localName.c_str(), depends, commands);
// Add a target with the canonical name (no prefix, suffix or path).
if(localName != t->second.GetName())
{
commands.clear();
tgt_depends.clear();
tgt_depends.push_back(localName);
lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
t->second.GetName(), tgt_depends, commands);
}
}
}
}

View File

@ -19,6 +19,9 @@
#include "cmGlobalGenerator.h" #include "cmGlobalGenerator.h"
class cmGeneratedFileStream;
class cmLocalUnixMakefileGenerator3;
/** \class cmGlobalUnixMakefileGenerator3 /** \class cmGlobalUnixMakefileGenerator3
* \brief Write a Unix makefiles. * \brief Write a Unix makefiles.
* *
@ -60,7 +63,14 @@ protected:
void WriteDependMakefile(); void WriteDependMakefile();
void WriteBuildMakefile(); void WriteBuildMakefile();
void WriteCleanMakefile(); void WriteCleanMakefile();
void WriteSupportMakefiles(); void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream);
void WriteAllRules(cmLocalUnixMakefileGenerator3 *lg,
std::ostream& makefileStream);
/** used to create a recursive make call */
std::string GetRecursiveMakeCall(const char *makefile, const char* tgt);
void WriteConvenienceRules(std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *);
}; };

View File

@ -34,9 +34,6 @@
#include <memory> // auto_ptr #include <memory> // auto_ptr
#include <queue> #include <queue>
// TODO: Convert makefile name to a runtime switch.
#define CMLUMG_MAKEFILE_NAME "Makefile"
// TODO: Add "help" target. // TODO: Add "help" target.
// TODO: Identify remaining relative path violations. // TODO: Identify remaining relative path violations.
// TODO: Need test for separate executable/library output path. // TODO: Need test for separate executable/library output path.
@ -57,16 +54,6 @@ cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3()
{ {
} }
//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::SetEmptyCommand(const char* cmd)
{
m_EmptyCommands.clear();
if(cmd)
{
m_EmptyCommands.push_back(cmd);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::Generate() void cmLocalUnixMakefileGenerator3::Generate()
{ {
@ -82,20 +69,69 @@ void cmLocalUnixMakefileGenerator3::Generate()
(t->second.GetType() == cmTarget::SHARED_LIBRARY) || (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
(t->second.GetType() == cmTarget::MODULE_LIBRARY)) (t->second.GetType() == cmTarget::MODULE_LIBRARY))
{ {
this->GenerateTargetRuleFile(t->second); this->WriteTargetRuleFiles(t->second);
} }
else if(t->second.GetType() == cmTarget::UTILITY) else if(t->second.GetType() == cmTarget::UTILITY)
{ {
this->GenerateUtilityRuleFile(t->second); this->WriteUtilityRuleFiles(t->second);
} }
} }
this->WriteCustomCommands(); this->WriteCustomCommands();
// Generate the cmake file with information for this directory. // Write the cmake file with information for this directory.
this->GenerateDirectoryInformationFile(); this->WriteDirectoryInformationFile();
} }
//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::ConfigureOutputPaths()
{
// Format the library and executable output paths.
if(const char* libOut = m_Makefile->GetDefinition("LIBRARY_OUTPUT_PATH"))
{
m_LibraryOutputPath = libOut;
this->FormatOutputPath(m_LibraryOutputPath, "LIBRARY");
}
if(const char* exeOut = m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
{
m_ExecutableOutputPath = exeOut;
this->FormatOutputPath(m_ExecutableOutputPath, "EXECUTABLE");
}
}
//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::FormatOutputPath(std::string& path,
const char* name)
{
if(!path.empty())
{
// Convert the output path to a full path in case it is
// specified as a relative path. Treat a relative path as
// relative to the current output directory for this makefile.
path =
cmSystemTools::CollapseFullPath(path.c_str(),
m_Makefile->GetStartOutputDirectory());
// Add a trailing slash for easy appending later.
if(path.empty() || path[path.size()-1] != '/')
{
path += "/";
}
// Make sure the output path exists on disk.
if(!cmSystemTools::MakeDirectory(path.c_str()))
{
cmSystemTools::Error("Error failed to create ",
name, "_OUTPUT_PATH directory:", path.c_str());
}
// Add this as a link directory automatically.
m_Makefile->AddLinkDirectory(path.c_str());
}
}
void cmLocalUnixMakefileGenerator3::WriteCustomCommands() void cmLocalUnixMakefileGenerator3::WriteCustomCommands()
{ {
// Generate the rule files for each custom command. // Generate the rule files for each custom command.
@ -136,7 +172,6 @@ void cmLocalUnixMakefileGenerator3::WriteCustomCommands()
<< "\n"; << "\n";
} }
// now do the clean // now do the clean
ruleFileName = "CMakeCustomRules.dir/clean.make"; ruleFileName = "CMakeCustomRules.dir/clean.make";
@ -182,7 +217,7 @@ void cmLocalUnixMakefileGenerator3::WriteCustomCommands()
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::GenerateDirectoryInformationFile() void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
{ {
std::string infoFileName = m_Makefile->GetStartOutputDirectory(); std::string infoFileName = m_Makefile->GetStartOutputDirectory();
infoFileName += "/CMakeDirectoryInformation.cmake"; infoFileName += "/CMakeDirectoryInformation.cmake";
@ -246,6 +281,29 @@ void cmLocalUnixMakefileGenerator3::GenerateDirectoryInformationFile()
<< "SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN})\n"; << "SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN})\n";
} }
//----------------------------------------------------------------------------
std::string
cmLocalUnixMakefileGenerator3
::ConvertToFullPath(const std::string& localPath)
{
std::string dir = m_Makefile->GetStartOutputDirectory();
dir += "/";
dir += localPath;
return dir;
}
//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::WriteDisclaimer(std::ostream& os)
{
os
<< "# CMAKE generated file: DO NOT EDIT!\n"
<< "# Generated by \"" << m_GlobalGenerator->GetName() << "\""
<< " Generator, CMake Version "
<< cmMakefile::GetMajorVersion() << "."
<< cmMakefile::GetMinorVersion() << "\n\n";
}
std::string cmLocalUnixMakefileGenerator3::GetHomeRelativeOutputPath() std::string cmLocalUnixMakefileGenerator3::GetHomeRelativeOutputPath()
{ {
// Include the rule file for each object. // Include the rule file for each object.
@ -262,7 +320,7 @@ std::string cmLocalUnixMakefileGenerator3::GetHomeRelativeOutputPath()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmLocalUnixMakefileGenerator3 cmLocalUnixMakefileGenerator3
::GenerateTargetRuleFile(const cmTarget& target) ::WriteTargetRuleFiles(const cmTarget& target)
{ {
// Create a directory for this target. // Create a directory for this target.
std::string dir = this->GetTargetDirectory(target); std::string dir = this->GetTargetDirectory(target);
@ -283,8 +341,7 @@ cmLocalUnixMakefileGenerator3
if(!m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str())) if(!m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str()))
{ {
// Generate this object file's rule file. // Generate this object file's rule file.
this->GenerateObjectRuleFile(target, *(*source), objects, this->WriteObjectRuleFiles(target, *(*source), objects,provides_requires);
provides_requires);
} }
else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT")) else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
{ {
@ -303,9 +360,6 @@ cmLocalUnixMakefileGenerator3
std::string ruleFileName = dir; std::string ruleFileName = dir;
ruleFileName += "/build.make"; ruleFileName += "/build.make";
// The rule file must be included by the makefile.
m_IncludeRuleFiles.push_back(ruleFileName);
// Open the rule file. This should be copy-if-different because the // Open the rule file. This should be copy-if-different because the
// rules may depend on this file itself. // rules may depend on this file itself.
std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName); std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
@ -370,13 +424,22 @@ cmLocalUnixMakefileGenerator3
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmLocalUnixMakefileGenerator3 cmLocalUnixMakefileGenerator3
::GenerateObjectDependFile(const std::string& obj, const cmSourceFile& source, ::WriteObjectDependFile(std::string &obj,
std::vector<std::string>& objects, const char * lang,
std::vector<std::string>& provides_requires, const cmSourceFile& source,
const std::string& depMarkFile, std::vector<std::string>& depends,
std::vector<std::string>& depends) std::string& depMakeFile)
{ {
const char* lang = this->GetSourceFileLanguage(source); // TODO: what the heck is this?
// Generate the build-time dependencies file for this object file.
std::string depMarkFile;
if(!this->GenerateDependsMakeFile(lang, obj.c_str(),
depMakeFile, depMarkFile))
{
cmSystemTools::Error("No dependency checker available for language \"",
lang, "\".");
return;
}
// Open the rule file for writing. This should be copy-if-different // Open the rule file for writing. This should be copy-if-different
// because the rules may depend on this file itself. // because the rules may depend on this file itself.
@ -441,68 +504,14 @@ cmLocalUnixMakefileGenerator3
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmLocalUnixMakefileGenerator3 cmLocalUnixMakefileGenerator3
::GenerateObjectRuleFile(const cmTarget& target, const cmSourceFile& source, ::WriteObjectBuildFile(std::string &obj,
std::vector<std::string>& objects, const char *lang,
const cmTarget& target,
const cmSourceFile& source,
std::vector<std::string>& depends,
std::string &depMakeFile,
std::vector<std::string>& provides_requires) std::vector<std::string>& provides_requires)
{ {
// Identify the language of the source file.
const char* lang = this->GetSourceFileLanguage(source);
if(!lang)
{
// If language is not known, this is an error.
cmSystemTools::Error("Source file \"", source.GetFullPath().c_str(),
"\" has unknown type.");
return;
}
// Get the full path name of the object file.
std::string obj = this->GetObjectFileName(target, source);
// Avoid generating duplicate rules.
if(m_ObjectFiles.find(obj) == m_ObjectFiles.end())
{
m_ObjectFiles.insert(obj);
}
else
{
cmOStringStream err;
err << "Warning: Source file \""
<< source.GetSourceName().c_str() << "."
<< source.GetSourceExtension().c_str()
<< "\" is listed multiple times for target \"" << target.GetName()
<< "\".";
cmSystemTools::Message(err.str().c_str(), "Warning");
return;
}
// Create the directory containing the object file. This may be a
// subdirectory under the target's directory.
std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str());
// Generate the build-time dependencies file for this object file.
std::string depMakeFile;
std::string depMarkFile;
if(!this->GenerateDependsMakeFile(lang, obj.c_str(),
depMakeFile, depMarkFile))
{
cmSystemTools::Error("No dependency checker available for language \"",
lang, "\".");
return;
}
// Save this in the target's list of object files.
objects.push_back(obj);
std::string relativeObj = this->GetHomeRelativeOutputPath();
relativeObj += obj;
// The object file should be checked for dependency integrity.
m_CheckDependFiles[lang].insert(obj);
// write the .depends.make file
std::vector<std::string> depends;
this->GenerateObjectDependFile(obj,source,objects,provides_requires,depMarkFile,depends);
// Open the rule file for writing. This should be copy-if-different // Open the rule file for writing. This should be copy-if-different
// because the rules may depend on this file itself. // because the rules may depend on this file itself.
std::string ruleFileName = obj; std::string ruleFileName = obj;
@ -570,6 +579,8 @@ cmLocalUnixMakefileGenerator3
this->ConvertToRelativeOutputPath(obj.c_str()); this->ConvertToRelativeOutputPath(obj.c_str());
// Construct the build message. // Construct the build message.
std::string relativeObj = this->GetHomeRelativeOutputPath();
relativeObj += obj;
std::vector<std::string> commands; std::vector<std::string> commands;
std::string buildEcho = "Building "; std::string buildEcho = "Building ";
buildEcho += lang; buildEcho += lang;
@ -626,6 +637,91 @@ cmLocalUnixMakefileGenerator3
} }
} }
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator3
::WriteObjectRuleFiles(const cmTarget& target, const cmSourceFile& source,
std::vector<std::string>& objects,
std::vector<std::string>& provides_requires)
{
// Identify the language of the source file.
const char* lang = this->GetSourceFileLanguage(source);
if(!lang)
{
// If language is not known, this is an error.
cmSystemTools::Error("Source file \"", source.GetFullPath().c_str(),
"\" has unknown type.");
return;
}
// Get the full path name of the object file.
std::string obj = this->GetObjectFileName(target, source);
// Avoid generating duplicate rules.
if(m_ObjectFiles.find(obj) == m_ObjectFiles.end())
{
m_ObjectFiles.insert(obj);
}
else
{
cmOStringStream err;
err << "Warning: Source file \""
<< source.GetSourceName().c_str() << "."
<< source.GetSourceExtension().c_str()
<< "\" is listed multiple times for target \"" << target.GetName()
<< "\".";
cmSystemTools::Message(err.str().c_str(), "Warning");
return;
}
// Create the directory containing the object file. This may be a
// subdirectory under the target's directory.
std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str());
// Save this in the target's list of object files.
objects.push_back(obj);
std::string relativeObj = this->GetHomeRelativeOutputPath();
relativeObj += obj;
// we compute some depends when writing the depend.make that we will also
// use in the build.make, same with depMakeFile
std::vector<std::string> depends;
std::string depMakeFile;
// generate the depends rule file
this->WriteObjectDependFile(obj, lang, source, depends, depMakeFile);
// generate the build rule file
this->WriteObjectBuildFile(obj, lang, target, source, depends, depMakeFile,
provides_requires);
// The object file should be checked for dependency integrity.
m_CheckDependFiles[lang].insert(relativeObj);
// If the language needs provides-requires mode, create the
// corresponding targets.
/*
if(strcmp(lang, "Fortran") == 0)
{
std::string objectRequires = obj;
std::string objectProvides = obj;
objectRequires += ".requires";
objectProvides += ".provides";
// Add the provides target to build the object file.
std::vector<std::string> no_commands;
std::vector<std::string> p_depends;
p_depends.push_back(obj);
this->WriteMakeRule(ruleFileStream, 0,
objectProvides.c_str(), p_depends, no_commands);
// Add this to the set of provides-requires objects on the target.
provides_requires.push_back(objectRequires);
}
*/
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmLocalUnixMakefileGenerator3 cmLocalUnixMakefileGenerator3
@ -659,9 +755,6 @@ cmLocalUnixMakefileGenerator3
} }
m_CustomRuleFiles.insert(ruleFileName); m_CustomRuleFiles.insert(ruleFileName);
// This rule should be included by the makefile.
m_IncludeRuleFiles.push_back(ruleFileName);
// what is the relative path to the rule file // what is the relative path to the rule file
std::string relRuleFile = this->GetHomeRelativeOutputPath(); std::string relRuleFile = this->GetHomeRelativeOutputPath();
relRuleFile += ruleFileName; relRuleFile += ruleFileName;
@ -707,7 +800,7 @@ cmLocalUnixMakefileGenerator3
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmLocalUnixMakefileGenerator3 cmLocalUnixMakefileGenerator3
::GenerateUtilityRuleFile(const cmTarget& target) ::WriteUtilityRuleFiles(const cmTarget& target)
{ {
// Create a directory for this target. // Create a directory for this target.
std::string dir = this->GetTargetDirectory(target); std::string dir = this->GetTargetDirectory(target);
@ -717,9 +810,6 @@ cmLocalUnixMakefileGenerator3
std::string ruleFileName = dir; std::string ruleFileName = dir;
ruleFileName += "/build.make"; ruleFileName += "/build.make";
// This rule should be included by the makefile.
m_IncludeRuleFiles.push_back(ruleFileName);
// Open the rule file. This should be copy-if-different because the // Open the rule file. This should be copy-if-different because the
// rules may depend on this file itself. // rules may depend on this file itself.
std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName); std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
@ -785,6 +875,8 @@ cmLocalUnixMakefileGenerator3
depMakeFile = checker->GetMakeFileName(); depMakeFile = checker->GetMakeFileName();
depMarkFile = checker->GetMarkFileName(); depMarkFile = checker->GetMarkFileName();
// Todo is this required???
// Check the dependencies. // Check the dependencies.
checker->Check(); checker->Check();
@ -867,6 +959,88 @@ cmLocalUnixMakefileGenerator3
os << "\n"; os << "\n";
} }
//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::WriteDivider(std::ostream& os)
{
os
<< "#======================================"
<< "=======================================\n";
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator3
::WriteMakeVariables(std::ostream& makefileStream)
{
this->WriteDivider(makefileStream);
makefileStream
<< "# Set environment variables for the build.\n"
<< "\n";
if(m_WindowsShell)
{
makefileStream
<< "!IF \"$(OS)\" == \"Windows_NT\"\n"
<< "NULL=\n"
<< "!ELSE\n"
<< "NULL=nul\n"
<< "!ENDIF\n";
}
else
{
makefileStream
<< "# The shell in which to execute make rules.\n"
<< "SHELL = /bin/sh\n"
<< "\n";
}
if(m_Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"))
{
makefileStream
<< "# Produce verbose output by default.\n"
<< "VERBOSE = 1\n"
<< "\n";
}
std::string cmakecommand =
this->ConvertToOutputForExisting(
m_Makefile->GetRequiredDefinition("CMAKE_COMMAND"));
makefileStream
<< "# The CMake executable.\n"
<< "CMAKE_COMMAND = "
<< m_GlobalGenerator->ConvertToHomeRelativeOutputPath
(cmakecommand.c_str()).c_str() << "\n"
<< "\n";
makefileStream
<< "# The command to remove a file.\n"
<< "RM = "
<< this->ConvertToRelativeOutputPath(cmakecommand.c_str()).c_str()
<< " -E remove -f\n"
<< "\n";
if(m_Makefile->GetDefinition("CMAKE_EDIT_COMMAND"))
{
makefileStream
<< "# The program to use to edit the cache.\n"
<< "CMAKE_EDIT_COMMAND = "
<< (this->ConvertToOutputForExisting(
m_Makefile->GetDefinition("CMAKE_EDIT_COMMAND"))) << "\n"
<< "\n";
}
makefileStream
<< "# The top-level source directory on which CMake was run.\n"
<< "CMAKE_SOURCE_DIR = "
<< this->ConvertToRelativeOutputPath(m_Makefile->GetHomeDirectory())
<< "\n"
<< "\n";
makefileStream
<< "# The top-level build directory on which CMake was run.\n"
<< "CMAKE_BINARY_DIR = "
<< this->ConvertToRelativeOutputPath(m_Makefile->GetHomeOutputDirectory())
<< "\n"
<< "\n";
}
void cmLocalUnixMakefileGenerator3::WriteTargetIncludes(std::ostream& makefileStream, void cmLocalUnixMakefileGenerator3::WriteTargetIncludes(std::ostream& makefileStream,
const char *file, const char *file,
const char *rule) const char *rule)
@ -973,98 +1147,6 @@ cmLocalUnixMakefileGenerator3
} }
} }
//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::WriteDivider(std::ostream& os)
{
os
<< "#======================================"
<< "=======================================\n";
}
//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::WriteDisclaimer(std::ostream& os)
{
os
<< "# CMAKE generated file: DO NOT EDIT!\n"
<< "# Generated by \"" << m_GlobalGenerator->GetName() << "\""
<< " Generator, CMake Version "
<< cmMakefile::GetMajorVersion() << "."
<< cmMakefile::GetMinorVersion() << "\n\n";
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator3
::WriteMakeVariables(std::ostream& makefileStream)
{
this->WriteDivider(makefileStream);
makefileStream
<< "# Set environment variables for the build.\n"
<< "\n";
if(m_WindowsShell)
{
makefileStream
<< "!IF \"$(OS)\" == \"Windows_NT\"\n"
<< "NULL=\n"
<< "!ELSE\n"
<< "NULL=nul\n"
<< "!ENDIF\n";
}
else
{
makefileStream
<< "# The shell in which to execute make rules.\n"
<< "SHELL = /bin/sh\n"
<< "\n";
}
if(m_Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"))
{
makefileStream
<< "# Produce verbose output by default.\n"
<< "VERBOSE = 1\n"
<< "\n";
}
std::string cmakecommand =
this->ConvertToOutputForExisting(
m_Makefile->GetRequiredDefinition("CMAKE_COMMAND"));
makefileStream
<< "# The CMake executable.\n"
<< "CMAKE_COMMAND = "
<< m_GlobalGenerator->ConvertToHomeRelativeOutputPath
(cmakecommand.c_str()).c_str() << "\n"
<< "\n";
makefileStream
<< "# The command to remove a file.\n"
<< "RM = "
<< this->ConvertToRelativeOutputPath(cmakecommand.c_str()).c_str()
<< " -E remove -f\n"
<< "\n";
if(m_Makefile->GetDefinition("CMAKE_EDIT_COMMAND"))
{
makefileStream
<< "# The program to use to edit the cache.\n"
<< "CMAKE_EDIT_COMMAND = "
<< (this->ConvertToOutputForExisting(
m_Makefile->GetDefinition("CMAKE_EDIT_COMMAND"))) << "\n"
<< "\n";
}
makefileStream
<< "# The top-level source directory on which CMake was run.\n"
<< "CMAKE_SOURCE_DIR = "
<< this->ConvertToRelativeOutputPath(m_Makefile->GetHomeDirectory())
<< "\n"
<< "\n";
makefileStream
<< "# The top-level build directory on which CMake was run.\n"
<< "CMAKE_BINARY_DIR = "
<< this->ConvertToRelativeOutputPath(m_Makefile->GetHomeOutputDirectory())
<< "\n"
<< "\n";
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
@ -1219,7 +1301,7 @@ cmLocalUnixMakefileGenerator3
{ {
// Build command to run CMake to check if anything needs regenerating. // Build command to run CMake to check if anything needs regenerating.
std::string cmakefileName = m_Makefile->GetStartOutputDirectory(); std::string cmakefileName = m_Makefile->GetStartOutputDirectory();
cmakefileName += "/" CMLUMG_MAKEFILE_NAME ".cmake"; cmakefileName += "/Makefile.cmake";
std::string runRule = std::string runRule =
"$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"; "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
runRule += " --check-build-system "; runRule += " --check-build-system ";
@ -1267,86 +1349,7 @@ cmLocalUnixMakefileGenerator3
".SUFFIXES", depends, no_commands); ".SUFFIXES", depends, no_commands);
} }
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator3
::WriteAllRules(std::ostream& makefileStream)
{
// Write section header.
this->WriteDivider(makefileStream);
makefileStream
<< "# Rules to build dependencies and targets.\n"
<< "\n";
std::vector<std::string> depends;
std::vector<std::string> commands;
// Check the build system in this directory.
depends.push_back("cmake_check_build_system");
commands.push_back(this->GetRecursiveMakeCall("depend.make",0));
commands.push_back(this->GetRecursiveMakeCall("build.make",0));
// Write the rule.
this->WriteMakeRule(makefileStream, "The main all target", "all", depends, commands);
// write the clean
commands.clear();
commands.push_back(this->GetRecursiveMakeCall("clean.make",0));
this->WriteMakeRule(makefileStream, "default clean target", "clean", depends, commands);
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator3
::WriteConvenienceRules(std::ostream& ruleFileStream)
{
std::vector<std::string> depends;
std::vector<std::string> tgt_depends;
std::vector<std::string> commands;
depends.push_back("cmake_check_build_system");
// for each target
// Generate the rule files for each target.
const cmTargets& targets = m_Makefile->GetTargets();
std::string localName;
std::string makeTargetName;
for(cmTargets::const_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))
{
// Add a rule to build the target by name.
localName = this->GetRelativeTargetDirectory(t->second);
commands.clear();
makeTargetName = localName;
makeTargetName += "/depend";
commands.push_back(this->GetRecursiveMakeCall("depend.make",makeTargetName.c_str()));
makeTargetName = localName;
makeTargetName += "/build";
commands.push_back(this->GetRecursiveMakeCall("build.make",makeTargetName.c_str()));
// Write the rule.
this->WriteMakeRule(ruleFileStream, "Convenience name for target.",
localName.c_str(), depends, commands);
// Add a target with the canonical name (no prefix, suffix or path).
if(localName != t->second.GetName())
{
commands.clear();
tgt_depends.clear();
tgt_depends.push_back(localName);
this->WriteMakeRule(ruleFileStream, "Convenience name for target.",
t->second.GetName(), tgt_depends, commands);
}
}
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
@ -1371,35 +1374,6 @@ cmLocalUnixMakefileGenerator3
} }
} }
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator3
::WriteRuleFileIncludes(std::ostream& makefileStream)
{
// Make sure we have some rules to include.
if(m_IncludeRuleFiles.empty())
{
return;
}
// Write section header.
this->WriteDivider(makefileStream);
makefileStream
<< "# Include rule files for this directory.\n"
<< "\n";
// Write the include rules.
for(std::vector<std::string>::const_iterator i = m_IncludeRuleFiles.begin();
i != m_IncludeRuleFiles.end(); ++i)
{
makefileStream
<< m_IncludeDirective << " "
<< this->ConvertToOutputForExisting(i->c_str()).c_str()
<< "\n";
}
makefileStream << "\n";
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmLocalUnixMakefileGenerator3 cmLocalUnixMakefileGenerator3
@ -2061,52 +2035,6 @@ cmLocalUnixMakefileGenerator3
cleanTarget.c_str(), no_depends, commands); cleanTarget.c_str(), no_depends, commands);
} }
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator3
::WriteTargetRequiresRule(std::ostream& ruleFileStream, const cmTarget& target,
const std::vector<std::string>& provides_requires)
{
// Create the driving make target.
std::string targetRequires = target.GetName();
targetRequires += ".requires";
std::string comment = "Directory-level driver rulue for this target.";
if(provides_requires.empty())
{
// No provides-requires mode objects in this target. Anything
// that requires the target can build it directly.
std::vector<std::string> no_commands;
std::vector<std::string> depends;
depends.push_back(target.GetName());
this->WriteMakeRule(ruleFileStream, comment.c_str(),
targetRequires.c_str(), depends, no_commands);
}
else
{
// There are provides-requires mode objects in this target. Use
// provides-requires mode to build the target itself.
std::string targetProvides = target.GetName();
targetProvides += ".provides";
{
std::vector<std::string> no_commands;
std::vector<std::string> depends;
depends.push_back(target.GetName());
this->WriteMakeRule(ruleFileStream, 0,
targetProvides.c_str(), depends, no_commands);
}
{
// Build list of require-level dependencies.
std::vector<std::string> depends;
for(std::vector<std::string>::const_iterator
pr = provides_requires.begin();
pr != provides_requires.end(); ++pr)
{
depends.push_back(*pr);
}
}
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
@ -2239,17 +2167,6 @@ cmLocalUnixMakefileGenerator3
->GetLanguageFromExtension(source.GetSourceExtension().c_str())); ->GetLanguageFromExtension(source.GetSourceExtension().c_str()));
} }
//----------------------------------------------------------------------------
std::string
cmLocalUnixMakefileGenerator3
::ConvertToFullPath(const std::string& localPath)
{
std::string dir = m_Makefile->GetStartOutputDirectory();
dir += "/";
dir += localPath;
return dir;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string std::string
cmLocalUnixMakefileGenerator3::ConvertToRelativeOutputPath(const char* p) cmLocalUnixMakefileGenerator3::ConvertToRelativeOutputPath(const char* p)
@ -2319,53 +2236,6 @@ cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(const char* p)
return result; return result;
} }
//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::ConfigureOutputPaths()
{
// Format the library and executable output paths.
if(const char* libOut = m_Makefile->GetDefinition("LIBRARY_OUTPUT_PATH"))
{
m_LibraryOutputPath = libOut;
this->FormatOutputPath(m_LibraryOutputPath, "LIBRARY");
}
if(const char* exeOut = m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
{
m_ExecutableOutputPath = exeOut;
this->FormatOutputPath(m_ExecutableOutputPath, "EXECUTABLE");
}
}
//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::FormatOutputPath(std::string& path,
const char* name)
{
if(!path.empty())
{
// Convert the output path to a full path in case it is
// specified as a relative path. Treat a relative path as
// relative to the current output directory for this makefile.
path =
cmSystemTools::CollapseFullPath(path.c_str(),
m_Makefile->GetStartOutputDirectory());
// Add a trailing slash for easy appending later.
if(path.empty() || path[path.size()-1] != '/')
{
path += "/";
}
// Make sure the output path exists on disk.
if(!cmSystemTools::MakeDirectory(path.c_str()))
{
cmSystemTools::Error("Error failed to create ",
name, "_OUTPUT_PATH directory:", path.c_str());
}
// Add this as a link directory automatically.
m_Makefile->AddLinkDirectory(path.c_str());
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmLocalUnixMakefileGenerator3 cmLocalUnixMakefileGenerator3
@ -2839,43 +2709,6 @@ cmLocalUnixMakefileGenerator3
} }
//============================================================================ //============================================================================
//----------------------------------------------------------------------------
std::string
cmLocalUnixMakefileGenerator3
::GetRecursiveMakeCall(const char *Makefile, const char* tgt)
{
// Call make on the given file.
std::string cmd;
cmd += "$(MAKE) -f ";
cmd += Makefile;
cmd += " ";
// Pass down verbosity level.
if(m_MakeSilentFlag.size())
{
cmd += m_MakeSilentFlag;
cmd += " ";
}
// Most unix makes will pass the command line flags to make down to
// sub-invoked makes via an environment variable. However, some
// makes do not support that, so you have to pass the flags
// explicitly.
if(m_PassMakeflags)
{
cmd += "-$(MAKEFLAGS) ";
}
// Add the target.
if (tgt && tgt[0] != '\0')
{
std::string tgt2 = this->ConvertToRelativeOutputPath(tgt);
tgt2 = this->ConvertToMakeTarget(tgt2.c_str());
cmd += tgt2;
}
return cmd;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmDepends* cmDepends*
cmLocalUnixMakefileGenerator3::GetDependsChecker(const std::string& lang, cmLocalUnixMakefileGenerator3::GetDependsChecker(const std::string& lang,
@ -3039,3 +2872,4 @@ void cmLocalUnixMakefileGenerator3::CheckDependencies(cmMakefile* mf)
} }
} }
} }

View File

@ -35,15 +35,53 @@ class cmSourceFile;
class cmLocalUnixMakefileGenerator3 : public cmLocalGenerator class cmLocalUnixMakefileGenerator3 : public cmLocalGenerator
{ {
public: public:
///! Set cache only and recurse to false by default.
cmLocalUnixMakefileGenerator3(); cmLocalUnixMakefileGenerator3();
virtual ~cmLocalUnixMakefileGenerator3(); virtual ~cmLocalUnixMakefileGenerator3();
/** Set the command used when there are no dependencies or rules for /**
a target. This is used to avoid errors on some make * Generate the makefile for this directory.
implementations. */ */
void SetEmptyCommand(const char* cmd); virtual void Generate();
/** creates the common disclainer text at the top of each makefile */
void WriteDisclaimer(std::ostream& os);
// this returns the relative path between the HomeOutputDirectory and this
// local generators StartOutputDirectory
std::string GetHomeRelativeOutputPath();
// Write out a make rule
void WriteMakeRule(std::ostream& os,
const char* comment,
const char* target,
const std::vector<std::string>& depends,
const std::vector<std::string>& commands);
// write the main variables used by the makefiles
void WriteMakeVariables(std::ostream& makefileStream);
// write a comment line #====... in the stream
void WriteDivider(std::ostream& os);
/**
* If true, then explicitly pass MAKEFLAGS on the make all target for makes
* that do not use environment variables.
*
*/
void SetPassMakeflags(bool s){m_PassMakeflags = s;}
bool GetPassMakeflags() { return m_PassMakeflags; }
/**
* Set the flag used to keep the make program silent.
*/
void SetMakeSilentFlag(const char* s) { m_MakeSilentFlag = s; }
std::string &GetMakeSilentFlag() { return m_MakeSilentFlag; }
/** Set whether the echo command needs its argument quoted. */ /** Set whether the echo command needs its argument quoted. */
void SetEchoNeedsQuote(bool b) { m_EchoNeedsQuote = b; } void SetEchoNeedsQuote(bool b) { m_EchoNeedsQuote = b; }
@ -62,11 +100,6 @@ public:
void SetIncludeDirective(const char* s) { m_IncludeDirective = s; } void SetIncludeDirective(const char* s) { m_IncludeDirective = s; }
const char *GetIncludeDirective() { return m_IncludeDirective.c_str(); } const char *GetIncludeDirective() { return m_IncludeDirective.c_str(); }
/**
* Set the flag used to keep the make program silent.
*/
void SetMakeSilentFlag(const char* s) { m_MakeSilentFlag = s; }
/** /**
* Set max makefile variable size, default is 0 which means unlimited. * Set max makefile variable size, default is 0 which means unlimited.
*/ */
@ -78,17 +111,9 @@ public:
*/ */
void SetIgnoreLibPrefix(bool s) { m_IgnoreLibPrefix = s; } void SetIgnoreLibPrefix(bool s) { m_IgnoreLibPrefix = s; }
/**
* If true, then explicitly pass MAKEFLAGS on the make all target for makes
* that do not use environment variables.
*
*/
void SetPassMakeflags(bool s){m_PassMakeflags = s;}
/**
* Generate the makefile for this directory.
*/
virtual void Generate();
/** Called from command-line hook to scan dependencies. */ /** Called from command-line hook to scan dependencies. */
static bool ScanDependencies(std::vector<std::string> const& args); static bool ScanDependencies(std::vector<std::string> const& args);
@ -96,27 +121,19 @@ public:
/** Called from command-line hook to check dependencies. */ /** Called from command-line hook to check dependencies. */
static void CheckDependencies(cmMakefile* mf); static void CheckDependencies(cmMakefile* mf);
void WriteDisclaimer(std::ostream& os); /** write some extra rules suahc as make test etc */
void WriteMakeRule(std::ostream& os, void WriteSpecialTargetsTop(std::ostream& makefileStream);
const char* comment,
const char* target,
const std::vector<std::string>& depends,
const std::vector<std::string>& commands);
void WriteAllRules(std::ostream& makefileStream);
void WriteTargetIncludes(std::ostream& makefileStream,const char *file, void WriteTargetIncludes(std::ostream& makefileStream,const char *file,
const char *rule); const char *rule);
void WriteSpecialTargetsTop(std::ostream& makefileStream);
void WriteSpecialTargetsBottom(std::ostream& makefileStream); void WriteSpecialTargetsBottom(std::ostream& makefileStream);
void WriteMakeVariables(std::ostream& makefileStream);
std::string ConvertToRelativeOutputPath(const char* p); std::string ConvertToRelativeOutputPath(const char* p);
void WriteConvenienceRules(std::ostream& ruleFileStream);
std::string GetRelativeTargetDirectory(const cmTarget& target); std::string GetRelativeTargetDirectory(const cmTarget& target);
void WriteLocalCleanRule(std::ostream& makefileStream); void WriteLocalCleanRule(std::ostream& makefileStream);
// this returns the relative path between the HomeOutputDirectory and this
// local generators StartOutputDirectory
std::string GetHomeRelativeOutputPath();
// List the files for which to check dependency integrity. Each // List the files for which to check dependency integrity. Each
// language has its own list because integrity may be checked // language has its own list because integrity may be checked
// differently. // differently.
@ -126,45 +143,69 @@ public:
protected: protected:
void GenerateMakefile(); // these two methods just compute reasonable values for m_LibraryOutputPath and
void GenerateCMakefile(); // m_ExecutableOutputPath
void GenerateDirectoryInformationFile(); void ConfigureOutputPaths();
void GenerateTargetRuleFile(const cmTarget& target); void FormatOutputPath(std::string& path, const char* name);
void GenerateObjectRuleFile(const cmTarget& target,
// this converts a file name that is relative to the StartOuputDirectory
// into a full path
std::string ConvertToFullPath(const std::string& localPath);
// this is responsible for writing all of the rules for all this
// directories custom commands (but not utility targets)
void WriteCustomCommands();
// this method Writes the Directory informaiton files
void WriteDirectoryInformationFile();
// cleanup the name of a potential target
std::string ConvertToMakeTarget(const char* tgt);
// used in writing out Cmake files such as WriteDirectoryInformation
void WriteCMakeArgument(std::ostream& os, const char* s);
// write out all the rules for this target
void WriteTargetRuleFiles(const cmTarget& target);
void WriteUtilityRuleFiles(const cmTarget& target);
// create the rule files for an object
void WriteObjectRuleFiles(const cmTarget& target,
const cmSourceFile& source, const cmSourceFile& source,
std::vector<std::string>& objects, std::vector<std::string>& objects,
std::vector<std::string>& provides_requires); std::vector<std::string>& provides_requires);
void GenerateObjectDependFile(const std::string& obj,
// write the build rule for an object
void WriteObjectBuildFile(std::string &obj,
const char *lang,
const cmTarget& target,
const cmSourceFile& source, const cmSourceFile& source,
std::vector<std::string>& objects, std::vector<std::string>& depends,
std::vector<std::string>& provides_requires, std::string &depMakeFile,
const std::string& depMarkFile, std::vector<std::string>& provides_requires);
std::vector<std::string>& depends);
void GenerateCustomRuleFile(const cmCustomCommand& cc); // write the depend.make file for an object
void GenerateUtilityRuleFile(const cmTarget& target); void WriteObjectDependFile(std::string& obj,
const char *lang,
const cmSourceFile& source,
std::vector<std::string>& depends,
std::string& depMarkFile);
// this is used only by WriteObjectDependFile
bool GenerateDependsMakeFile(const std::string& lang, bool GenerateDependsMakeFile(const std::string& lang,
const char* objFile, const char* objFile,
std::string& depMakeFile, std::string& depMakeFile,
std::string& depMarkFile); std::string& depMarkFile);
void WriteDivider(std::ostream& os);
void WriteRuleFileIncludes(std::ostream& makefileStream); // return the appropriate depends checker
void WriteSubdirRules(std::ostream& makefileStream, const char* pass); static cmDepends* GetDependsChecker(const std::string& lang,
void WriteSubdirRule(std::ostream& makefileStream, const char* pass, const char* dir,
const char* subdir, std::string& last); const char* objFile);
void WriteSubdirDriverRule(std::ostream& makefileStream, const char* pass,
const char* order, const std::string& last);
void WriteLocalRule(std::ostream& ruleFileStream, const char* pass, void GenerateCustomRuleFile(const cmCustomCommand& cc);
const char* dependency);
void WriteConvenienceRule(std::ostream& ruleFileStream, // these three make some simple changes and then call WriteLibraryRule
const char* realTarget,
const char* helpTarget);
void WriteCustomCommands();
void WriteExecutableRule(std::ostream& ruleFileStream,
const char* ruleFileName,
const cmTarget& target,
const std::vector<std::string>& objects,
const std::vector<std::string>& external_objects,
const std::vector<std::string>& provides_requires);
void WriteStaticLibraryRule(std::ostream& ruleFileStream, void WriteStaticLibraryRule(std::ostream& ruleFileStream,
const char* ruleFileName, const char* ruleFileName,
const cmTarget& target, const cmTarget& target,
@ -183,6 +224,16 @@ protected:
const std::vector<std::string>& objects, const std::vector<std::string>& objects,
const std::vector<std::string>& external_objects, const std::vector<std::string>& external_objects,
const std::vector<std::string>& provides_requires); const std::vector<std::string>& provides_requires);
// the main code for writing the Executable target rules
void WriteExecutableRule(std::ostream& ruleFileStream,
const char* ruleFileName,
const cmTarget& target,
const std::vector<std::string>& objects,
const std::vector<std::string>& external_objects,
const std::vector<std::string>& provides_requires);
// the main method for writing library rules
void WriteLibraryRule(std::ostream& ruleFileStream, void WriteLibraryRule(std::ostream& ruleFileStream,
const char* ruleFileName, const char* ruleFileName,
const cmTarget& target, const cmTarget& target,
@ -191,6 +242,17 @@ protected:
const char* linkRuleVar, const char* linkRuleVar,
const char* extraLinkFlags, const char* extraLinkFlags,
const std::vector<std::string>& provides_requires); const std::vector<std::string>& provides_requires);
void WriteLocalRule(std::ostream& ruleFileStream, const char* pass,
const char* dependency);
void WriteConvenienceRule(std::ostream& ruleFileStream,
const char* realTarget,
const char* helpTarget);
void WriteObjectsVariable(std::ostream& ruleFileStream, void WriteObjectsVariable(std::ostream& ruleFileStream,
const cmTarget& target, const cmTarget& target,
const std::vector<std::string>& objects, const std::vector<std::string>& objects,
@ -205,19 +267,13 @@ protected:
const std::vector<std::string>& files, const std::vector<std::string>& files,
const std::vector<std::string>& objects, const std::vector<std::string>& objects,
const std::vector<std::string>& external_objects); const std::vector<std::string>& external_objects);
void WriteTargetRequiresRule(std::ostream& ruleFileStream,
const cmTarget& target,
const std::vector<std::string>& provides_requires);
void WriteCMakeArgument(std::ostream& os, const char* s);
std::string GetTargetDirectory(const cmTarget& target); std::string GetTargetDirectory(const cmTarget& target);
std::string GetSubdirTargetName(const char* pass, const char* subdir); std::string GetSubdirTargetName(const char* pass, const char* subdir);
std::string GetObjectFileName(const cmTarget& target, std::string GetObjectFileName(const cmTarget& target,
const cmSourceFile& source); const cmSourceFile& source);
const char* GetSourceFileLanguage(const cmSourceFile& source); const char* GetSourceFileLanguage(const cmSourceFile& source);
std::string ConvertToFullPath(const std::string& localPath);
std::string ConvertToQuotedOutputPath(const char* p); std::string ConvertToQuotedOutputPath(const char* p);
void ConfigureOutputPaths();
void FormatOutputPath(std::string& path, const char* name);
void AppendTargetDepends(std::vector<std::string>& depends, void AppendTargetDepends(std::vector<std::string>& depends,
const cmTarget& target); const cmTarget& target);
@ -240,33 +296,14 @@ protected:
//========================================================================== //==========================================================================
bool SamePath(const char* path1, const char* path2); bool SamePath(const char* path1, const char* path2);
std::string ConvertToMakeTarget(const char* tgt);
std::string& CreateSafeUniqueObjectFileName(const char* sin); std::string& CreateSafeUniqueObjectFileName(const char* sin);
std::string CreateMakeVariable(const char* sin, const char* s2in); std::string CreateMakeVariable(const char* sin, const char* s2in);
//========================================================================== //==========================================================================
std::string GetRecursiveMakeCall(const char *makefile, const char* tgt);
void WriteJumpAndBuildRules(std::ostream& makefileStream);
static cmDepends* GetDependsChecker(const std::string& lang,
const char* dir,
const char* objFile);
private: private:
// Map from target name to build directory containing it for
// jump-and-build targets.
struct RemoteTarget
{
std::string m_BuildDirectory;
std::string m_FilePath;
};
std::map<cmStdString, RemoteTarget> m_JumpAndBuild;
std::map<cmStdString, IntegrityCheckSet> m_CheckDependFiles; std::map<cmStdString, IntegrityCheckSet> m_CheckDependFiles;
// Command used when a rule has no dependencies or commands.
std::vector<std::string> m_EmptyCommands;
//========================================================================== //==========================================================================
// Configuration settings. // Configuration settings.
int m_MakefileVariableSize; int m_MakefileVariableSize;
@ -283,9 +320,6 @@ private:
// Flag for whether echo command needs quotes. // Flag for whether echo command needs quotes.
bool m_EchoNeedsQuote; bool m_EchoNeedsQuote;
// List of make rule files that need to be included by the makefile.
std::vector<std::string> m_IncludeRuleFiles;
// Set of custom rule files that have been generated. // Set of custom rule files that have been generated.
std::set<cmStdString> m_CustomRuleFiles; std::set<cmStdString> m_CustomRuleFiles;