ENH: Implemented utility targets. This involved pulling part of the custom command rule implementation out into shared methods.

This commit is contained in:
Brad King 2004-12-09 13:52:32 -05:00
parent 729c5644cf
commit 477f328aed
2 changed files with 129 additions and 56 deletions

View File

@ -86,6 +86,10 @@ void cmLocalUnixMakefileGenerator2::Generate(bool fromTheTop)
{
this->GenerateTargetRuleFile(t->second);
}
else if(t->second.GetType() == cmTarget::UTILITY)
{
this->GenerateUtilityRuleFile(t->second);
}
}
// Generate the rule files for each custom command.
@ -93,9 +97,9 @@ void cmLocalUnixMakefileGenerator2::Generate(bool fromTheTop)
for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
i != sources.end(); ++i)
{
if((*i)->GetCustomCommand())
if(const cmCustomCommand* cc = (*i)->GetCustomCommand())
{
this->GenerateCustomRuleFile(*(*i));
this->GenerateCustomRuleFile(*cc);
}
}
@ -512,18 +516,10 @@ cmLocalUnixMakefileGenerator2
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2
::GenerateCustomRuleFile(const cmSourceFile& source)
::GenerateCustomRuleFile(const cmCustomCommand& cc)
{
// Get the custom command for the source.
if(!source.GetCustomCommand())
{
cmSystemTools::Error("GenerateCustomRuleFile called for non-custom source.");
return;
}
const cmCustomCommand& cc = *source.GetCustomCommand();
// Create a directory for custom rule files.
std::string dir = "CMakeCustomCommands.dir";
std::string dir = "CMakeCustomRules.dir";
cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str());
// Construct the name of the rule file.
@ -545,8 +541,6 @@ cmLocalUnixMakefileGenerator2
// This rule should be included by the makefile.
m_IncludeRuleFiles.push_back(ruleFileName);
// TODO: Convert outputs/dependencies (arguments?) to relative paths.
// Open the rule file. This should be copy-if-different because the
// rules may depend on this file itself.
std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
@ -560,51 +554,13 @@ cmLocalUnixMakefileGenerator2
ruleFileStream
<< "# Custom command rule file for " << customName.c_str() << ".\n\n";
// Build the command line in a single string.
// Collect the commands.
std::vector<std::string> commands;
std::string cmd = cc.GetCommand();
cmSystemTools::ReplaceString(cmd, "/./", "/");
cmd = this->ConvertToRelativeOutputPath(cmd.c_str());
if(cc.GetArguments().size() > 0)
{
cmd += " ";
cmd += cc.GetArguments();
}
commands.push_back(cmd);
this->AddCustomCommands(commands, cc);
// Collect the dependencies.
std::vector<std::string> depends;
for(std::vector<std::string>::const_iterator d = cc.GetDepends().begin();
d != cc.GetDepends().end(); ++d)
{
// Get the dependency with variables expanded.
std::string dep = *d;
m_Makefile->ExpandVariablesInString(dep);
// If the rule depends on a target CMake knows how to build,
// convert it to the path where it will be built.
std::string libPath = dep + "_CMAKE_PATH";
const char* cacheValue = m_Makefile->GetDefinition(libPath.c_str());
if(cacheValue && *cacheValue)
{
libPath = cacheValue;
if (m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH") &&
m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH")[0] != '\0')
{
libPath = m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
}
libPath += "/";
libPath += dep;
libPath += cmSystemTools::GetExecutableExtension();
dep = libPath;
}
// Cleanup the dependency and add it.
cmSystemTools::ReplaceString(dep, "/./", "/");
cmSystemTools::ReplaceString(dep, "/$(IntDir)/", "/");
dep = this->ConvertToRelativeOutputPath(dep.c_str());
depends.push_back(dep.c_str());
}
this->AddCustomDepends(depends, cc);
// Add a dependency on the rule file itself.
depends.push_back(ruleFileName);
@ -622,6 +578,60 @@ cmLocalUnixMakefileGenerator2
cc.GetOutput().c_str(), depends, commands);
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2
::GenerateUtilityRuleFile(const cmTarget& target)
{
// Create a directory for utility rule files.
std::string dir = "CMakeCustomRules.dir";
cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str());
// Construct the name of the rule file.
std::string ruleFileName = dir;
ruleFileName += "/";
ruleFileName += target.GetName();
ruleFileName += ".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
// rules may depend on this file itself.
std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str());
ruleFileStream.SetCopyIfDifferent(true);
if(!ruleFileStream)
{
return;
}
this->WriteDisclaimer(ruleFileStream);
ruleFileStream
<< "# Utility rule file for " << target.GetName() << ".\n\n";
// TODO: Pre-build and pre-link rules.
// Collect the commands and dependencies.
std::vector<std::string> commands;
std::vector<std::string> depends;
// Utility targets store their rules in post-build commands.
for(std::vector<cmCustomCommand>::const_iterator
i = target.GetPostBuildCommands().begin();
i != target.GetPostBuildCommands().end(); ++i)
{
this->AddCustomCommands(commands, *i);
this->AddCustomDepends(depends, *i);
}
// Add a dependency on the rule file itself.
depends.push_back(ruleFileName);
// Write the rule.
this->WriteMakeRule(ruleFileStream, 0, 0,
target.GetName(), depends, commands);
}
//----------------------------------------------------------------------------
std::string
cmLocalUnixMakefileGenerator2
@ -2135,6 +2145,64 @@ cmLocalUnixMakefileGenerator2
}
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2
::AddCustomDepends(std::vector<std::string>& depends,
const cmCustomCommand& cc)
{
// TODO: Convert outputs/dependencies (arguments?) to relative paths.
for(std::vector<std::string>::const_iterator d = cc.GetDepends().begin();
d != cc.GetDepends().end(); ++d)
{
// Get the dependency.
std::string dep = *d;
// If the dependency is a target CMake knows how to build, convert
// it to the path where it will be built.
std::string libPath = dep + "_CMAKE_PATH";
const char* cacheValue = m_Makefile->GetDefinition(libPath.c_str());
if(cacheValue && *cacheValue)
{
libPath = cacheValue;
if (m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH") &&
m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH")[0] != '\0')
{
libPath = m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
}
libPath += "/";
libPath += dep;
libPath += cmSystemTools::GetExecutableExtension();
dep = libPath;
}
// Cleanup the dependency and add it.
cmSystemTools::ReplaceString(dep, "/./", "/");
cmSystemTools::ReplaceString(dep, "/$(IntDir)/", "/");
depends.push_back(dep.c_str());
}
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2
::AddCustomCommands(std::vector<std::string>& commands,
const cmCustomCommand& cc)
{
// TODO: Convert outputs/dependencies (arguments?) to relative paths.
// Build the command line in a single string.
std::string cmd = cc.GetCommand();
cmSystemTools::ReplaceString(cmd, "/./", "/");
cmd = this->ConvertToRelativeOutputPath(cmd.c_str());
if(cc.GetArguments().size() > 0)
{
cmd += " ";
cmd += cc.GetArguments();
}
commands.push_back(cmd);
}
//----------------------------------------------------------------------------
std::string
cmLocalUnixMakefileGenerator2

View File

@ -66,7 +66,8 @@ protected:
void GenerateTargetRuleFile(const cmTarget& target);
void GenerateObjectRuleFile(const cmTarget& target,
const cmSourceFile& source);
void GenerateCustomRuleFile(const cmSourceFile& source);
void GenerateCustomRuleFile(const cmCustomCommand& cc);
void GenerateUtilityRuleFile(const cmTarget& target);
std::string GenerateDependsMakeFile(const char* file);
void WriteMakeRule(std::ostream& os,
const char* comment,
@ -145,6 +146,10 @@ protected:
void AppendLibDepends(const cmTarget& target,
std::vector<std::string>& depends);
void AppendLibDepend(std::vector<std::string>& depends, const char* name);
void AddCustomDepends(std::vector<std::string>& depends,
const cmCustomCommand& cc);
void AddCustomCommands(std::vector<std::string>& commands,
const cmCustomCommand& cc);
std::string GetRecursiveMakeCall(const char* tgt);
void WriteJumpAndBuildRules(std::ostream& makefileStream);