ENH: Implemented generation of custom command rule files.
This commit is contained in:
parent
95f67dca9e
commit
04f958b6d9
|
@ -67,6 +67,17 @@ void cmLocalUnixMakefileGenerator2::Generate(bool fromTheTop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate the rule files for each custom command.
|
||||||
|
const std::vector<cmSourceFile*>& sources = m_Makefile->GetSourceFiles();
|
||||||
|
for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
|
||||||
|
i != sources.end(); ++i)
|
||||||
|
{
|
||||||
|
if((*i)->GetCustomCommand())
|
||||||
|
{
|
||||||
|
this->GenerateCustomRuleFile(*(*i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Generate the main makefile.
|
// Generate the main makefile.
|
||||||
this->GenerateMakefile();
|
this->GenerateMakefile();
|
||||||
|
|
||||||
|
@ -104,8 +115,8 @@ void cmLocalUnixMakefileGenerator2::GenerateMakefile()
|
||||||
// Write the subdirectory driver rules.
|
// Write the subdirectory driver rules.
|
||||||
this->WriteSubdirRules(makefileStream, "all");
|
this->WriteSubdirRules(makefileStream, "all");
|
||||||
|
|
||||||
// Write include statements to get rules for each target.
|
// Write include statements to get rules for this directory.
|
||||||
this->WriteTargetIncludes(makefileStream);
|
this->WriteRuleFileIncludes(makefileStream);
|
||||||
|
|
||||||
// Write jump-and-build rules that were recorded in the map.
|
// Write jump-and-build rules that were recorded in the map.
|
||||||
this->WriteJumpAndBuildRules(makefileStream);
|
this->WriteJumpAndBuildRules(makefileStream);
|
||||||
|
@ -196,6 +207,11 @@ cmLocalUnixMakefileGenerator2
|
||||||
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
|
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
|
||||||
source != sources.end(); ++source)
|
source != sources.end(); ++source)
|
||||||
{
|
{
|
||||||
|
if((*source)->GetCustomCommand())
|
||||||
|
{
|
||||||
|
// Generate this custom command's rule file.
|
||||||
|
std::cout << "Found custom command!" << std::endl;
|
||||||
|
}
|
||||||
if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY") &&
|
if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY") &&
|
||||||
!(*source)->GetCustomCommand() &&
|
!(*source)->GetCustomCommand() &&
|
||||||
!m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str()))
|
!m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str()))
|
||||||
|
@ -214,12 +230,17 @@ cmLocalUnixMakefileGenerator2
|
||||||
depBase += target.GetName();
|
depBase += target.GetName();
|
||||||
std::string depMakeFile = this->GenerateDependsMakeFile(depBase.c_str());
|
std::string depMakeFile = this->GenerateDependsMakeFile(depBase.c_str());
|
||||||
|
|
||||||
// Open the rule file. This should be copy-if-different because the
|
// Construct the rule file name.
|
||||||
// rules may depend on this file itself.
|
|
||||||
std::string ruleFileName = dir;
|
std::string ruleFileName = dir;
|
||||||
ruleFileName += "/";
|
ruleFileName += "/";
|
||||||
ruleFileName += target.GetName();
|
ruleFileName += target.GetName();
|
||||||
ruleFileName += ".make";
|
ruleFileName += ".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
|
||||||
|
// rules may depend on this file itself.
|
||||||
std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
|
std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
|
||||||
cmGeneratedFileStream ruleFile(ruleFileNameFull.c_str());
|
cmGeneratedFileStream ruleFile(ruleFileNameFull.c_str());
|
||||||
std::ostream& ruleFileStream = ruleFile.GetStream();
|
std::ostream& ruleFileStream = ruleFile.GetStream();
|
||||||
|
@ -481,6 +502,115 @@ cmLocalUnixMakefileGenerator2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
cmLocalUnixMakefileGenerator2
|
||||||
|
::GenerateCustomRuleFile(const cmSourceFile& source)
|
||||||
|
{
|
||||||
|
// Get the custom command for the source.
|
||||||
|
if(!source.GetCustomCommand())
|
||||||
|
{
|
||||||
|
cmSystemTools::Error("GenerateCustomRuleFile called for non-custom source.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const cmCustomCommand& cc = *source.GetCustomCommand();
|
||||||
|
|
||||||
|
// Construct the name of the rule file.
|
||||||
|
std::string customName = this->GetCustomBaseName(cc);
|
||||||
|
std::string ruleFileName = customName;
|
||||||
|
ruleFileName += ".make";
|
||||||
|
|
||||||
|
// If this is a duplicate rule produce an error.
|
||||||
|
if(m_CustomRuleFiles.find(ruleFileName) != m_CustomRuleFiles.end())
|
||||||
|
{
|
||||||
|
cmSystemTools::Error("An output was found with multiple rules on how to build it for output: ",
|
||||||
|
cc.GetOutput().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_CustomRuleFiles.insert(ruleFileName);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
cmGeneratedFileStream ruleFile(ruleFileNameFull.c_str());
|
||||||
|
std::ostream& ruleFileStream = ruleFile.GetStream();
|
||||||
|
if(!ruleFileStream)
|
||||||
|
{
|
||||||
|
// TODO: Produce error message that accounts for generated stream
|
||||||
|
// .tmp.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->WriteDisclaimer(ruleFileStream);
|
||||||
|
ruleFileStream
|
||||||
|
<< "# Custom command rule file for " << customName.c_str() << ".\n\n";
|
||||||
|
|
||||||
|
// Build the command line in a single string.
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a dependency on the rule file itself.
|
||||||
|
depends.push_back(ruleFileName);
|
||||||
|
|
||||||
|
// Write the rule.
|
||||||
|
const char* comment = 0;
|
||||||
|
if(cc.GetComment().size())
|
||||||
|
{
|
||||||
|
comment = cc.GetComment().c_str();
|
||||||
|
}
|
||||||
|
std::string preEcho = "Generating ";
|
||||||
|
preEcho += customName;
|
||||||
|
preEcho += "...";
|
||||||
|
this->WriteMakeRule(ruleFileStream, comment, preEcho.c_str(),
|
||||||
|
cc.GetOutput().c_str(), depends, commands);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
std::string
|
std::string
|
||||||
cmLocalUnixMakefileGenerator2
|
cmLocalUnixMakefileGenerator2
|
||||||
|
@ -790,7 +920,7 @@ cmLocalUnixMakefileGenerator2
|
||||||
std::vector<std::string> no_depends;
|
std::vector<std::string> no_depends;
|
||||||
std::vector<std::string> commands;
|
std::vector<std::string> commands;
|
||||||
commands.push_back(
|
commands.push_back(
|
||||||
"$(CMAKE_EDIT_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)");
|
"@$(CMAKE_EDIT_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)");
|
||||||
this->WriteMakeRule(makefileStream,
|
this->WriteMakeRule(makefileStream,
|
||||||
"Special rule to re-run CMake cache editor using make.",
|
"Special rule to re-run CMake cache editor using make.",
|
||||||
"Running CMake cache editor...",
|
"Running CMake cache editor...",
|
||||||
|
@ -1105,43 +1235,30 @@ cmLocalUnixMakefileGenerator2
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
cmLocalUnixMakefileGenerator2
|
cmLocalUnixMakefileGenerator2
|
||||||
::WriteTargetIncludes(std::ostream& makefileStream)
|
::WriteRuleFileIncludes(std::ostream& makefileStream)
|
||||||
{
|
{
|
||||||
bool first = true;
|
// Make sure we have some rules to include.
|
||||||
const cmTargets& targets = m_Makefile->GetTargets();
|
if(m_IncludeRuleFiles.empty())
|
||||||
for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
|
|
||||||
{
|
{
|
||||||
// TODO: Handle the rest of the target types.
|
return;
|
||||||
if((t->second.GetType() == cmTarget::EXECUTABLE) ||
|
|
||||||
(t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
|
|
||||||
(t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
|
|
||||||
(t->second.GetType() == cmTarget::MODULE_LIBRARY))
|
|
||||||
{
|
|
||||||
// Write the header for this section.
|
|
||||||
if(first)
|
|
||||||
{
|
|
||||||
this->WriteDivider(makefileStream);
|
|
||||||
makefileStream
|
|
||||||
<< "# Include rule files for each target in this directory.\n"
|
|
||||||
<< "\n";
|
|
||||||
first = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct the rule file name for this target.
|
// Write section header.
|
||||||
std::string ruleFileName = this->GetTargetDirectory(t->second);
|
this->WriteDivider(makefileStream);
|
||||||
ruleFileName += "/";
|
makefileStream
|
||||||
ruleFileName += t->first;
|
<< "# Include rule files for this directory.\n"
|
||||||
ruleFileName += ".make";
|
<< "\n";
|
||||||
|
|
||||||
|
// Write the include rules.
|
||||||
|
for(std::vector<std::string>::const_iterator i = m_IncludeRuleFiles.begin();
|
||||||
|
i != m_IncludeRuleFiles.end(); ++i)
|
||||||
|
{
|
||||||
makefileStream
|
makefileStream
|
||||||
<< m_IncludeDirective << " "
|
<< m_IncludeDirective << " "
|
||||||
<< this->ConvertToOutputForExisting(ruleFileName.c_str()).c_str()
|
<< this->ConvertToOutputForExisting(i->c_str()).c_str()
|
||||||
<< "\n";
|
<< "\n";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if(!first)
|
|
||||||
{
|
|
||||||
makefileStream << "\n";
|
makefileStream << "\n";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -1620,6 +1737,30 @@ cmLocalUnixMakefileGenerator2
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
std::string
|
||||||
|
cmLocalUnixMakefileGenerator2
|
||||||
|
::GetCustomBaseName(const cmCustomCommand& cc)
|
||||||
|
{
|
||||||
|
// If the full path to the output file includes this build
|
||||||
|
// directory, we want to use the relative path for the filename of
|
||||||
|
// the custom file. Otherwise, we will use just the filename
|
||||||
|
// portion.
|
||||||
|
std::string customName;
|
||||||
|
if(cmSystemTools::FileIsFullPath(cc.GetOutput().c_str()) &&
|
||||||
|
(cc.GetOutput().find(m_Makefile->GetStartOutputDirectory()) == 0))
|
||||||
|
{
|
||||||
|
customName =
|
||||||
|
cmSystemTools::RelativePath(m_Makefile->GetStartOutputDirectory(),
|
||||||
|
cc.GetOutput().c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
customName = cmSystemTools::GetFilenameName(cc.GetOutput().c_str());
|
||||||
|
}
|
||||||
|
return customName;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
const char*
|
const char*
|
||||||
cmLocalUnixMakefileGenerator2
|
cmLocalUnixMakefileGenerator2
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "cmLocalUnixMakefileGenerator.h"
|
#include "cmLocalUnixMakefileGenerator.h"
|
||||||
|
|
||||||
|
class cmCustomCommand;
|
||||||
class cmDependInformation;
|
class cmDependInformation;
|
||||||
class cmMakeDepend;
|
class cmMakeDepend;
|
||||||
class cmTarget;
|
class cmTarget;
|
||||||
|
@ -65,6 +66,7 @@ protected:
|
||||||
void GenerateTargetRuleFile(const cmTarget& target);
|
void GenerateTargetRuleFile(const cmTarget& target);
|
||||||
void GenerateObjectRuleFile(const cmTarget& target,
|
void GenerateObjectRuleFile(const cmTarget& target,
|
||||||
const cmSourceFile& source);
|
const cmSourceFile& source);
|
||||||
|
void GenerateCustomRuleFile(const cmSourceFile& source);
|
||||||
std::string GenerateDependsMakeFile(const char* file);
|
std::string GenerateDependsMakeFile(const char* file);
|
||||||
void WriteMakeRule(std::ostream& os,
|
void WriteMakeRule(std::ostream& os,
|
||||||
const char* comment,
|
const char* comment,
|
||||||
|
@ -78,7 +80,7 @@ protected:
|
||||||
void WriteMakeVariables(std::ostream& makefileStream);
|
void WriteMakeVariables(std::ostream& makefileStream);
|
||||||
void WriteSpecialTargetsTop(std::ostream& makefileStream);
|
void WriteSpecialTargetsTop(std::ostream& makefileStream);
|
||||||
void WriteSpecialTargetsBottom(std::ostream& makefileStream);
|
void WriteSpecialTargetsBottom(std::ostream& makefileStream);
|
||||||
void WriteTargetIncludes(std::ostream& makefileStream);
|
void WriteRuleFileIncludes(std::ostream& makefileStream);
|
||||||
void WriteAllRule(std::ostream& makefileStream);
|
void WriteAllRule(std::ostream& makefileStream);
|
||||||
void WriteSubdirRules(std::ostream& makefileStream, const char* pass);
|
void WriteSubdirRules(std::ostream& makefileStream, const char* pass);
|
||||||
void WriteSubdirRule(std::ostream& makefileStream, const char* pass,
|
void WriteSubdirRule(std::ostream& makefileStream, const char* pass,
|
||||||
|
@ -114,6 +116,7 @@ protected:
|
||||||
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);
|
||||||
|
std::string GetCustomBaseName(const cmCustomCommand& cc);
|
||||||
const char* GetSourceFileLanguage(const cmSourceFile& source);
|
const char* GetSourceFileLanguage(const cmSourceFile& source);
|
||||||
std::string ConvertToFullPath(const std::string& localPath);
|
std::string ConvertToFullPath(const std::string& localPath);
|
||||||
|
|
||||||
|
@ -146,6 +149,12 @@ private:
|
||||||
|
|
||||||
// Command used when a rule has no dependencies or commands.
|
// Command used when a rule has no dependencies or commands.
|
||||||
std::vector<std::string> m_EmptyCommands;
|
std::vector<std::string> m_EmptyCommands;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
std::set<cmStdString> m_CustomRuleFiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue