BUG: Custom command outputs listed explicitly as source files in a target should be generated whether or not an object file in the target needs them. This useful and makes Makefile builds more consistent with VS IDE builds.

This commit is contained in:
Brad King 2006-06-01 11:45:51 -04:00
parent f54d254a81
commit 4189370497
5 changed files with 141 additions and 119 deletions

View File

@ -29,12 +29,15 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
// create the build.make file and directory, put in the common blocks
this->CreateRuleFile();
// Add in any rules for custom commands
this->WriteCustomCommandsForTarget();
// write in rules for object files
// write rules used to help build object files
this->WriteCommonCodeRules();
// write in rules for object files and custom commands
this->WriteTargetBuildRules();
// write the per-target per-language flags
this->WriteTargetLanguageFlags();
// Write the dependency generation rule.
this->WriteTargetDependRules();
@ -379,19 +382,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
depends, commands, false);
}
// Write convenience targets.
std::string dir = this->Makefile->GetStartOutputDirectory();
dir += "/";
dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
std::string buildTargetRuleName = dir;
buildTargetRuleName += relink?"/preinstall":"/build";
buildTargetRuleName =
this->Convert(buildTargetRuleName.c_str(),
cmLocalGenerator::HOME_OUTPUT,
cmLocalGenerator::MAKEFILE);
this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
targetFullPath.c_str(),
buildTargetRuleName.c_str());
// Write the main driver rule to build everything in this target.
this->WriteTargetDriverRule(targetFullPath.c_str(), relink);
// Clean all the possible executable names and symlinks and object files.
this->CleanFiles.insert(this->CleanFiles.end(),

View File

@ -28,13 +28,16 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
{
// create the build.make file and directory, put in the common blocks
this->CreateRuleFile();
// Add in any rules for custom commands
this->WriteCustomCommandsForTarget();
// write in rules for object files
// write rules used to help build object files
this->WriteCommonCodeRules();
// write in rules for object files and custom commands
this->WriteTargetBuildRules();
// write the per-target per-language flags
this->WriteTargetLanguageFlags();
// Write the dependency generation rule.
this->WriteTargetDependRules();
@ -522,18 +525,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
depends, commands, false);
}
// Write convenience targets.
std::string dir = this->Makefile->GetStartOutputDirectory();
dir += "/";
dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
std::string buildTargetRuleName = dir;
buildTargetRuleName += relink?"/preinstall":"/build";
buildTargetRuleName =
this->Convert(buildTargetRuleName.c_str(),
cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
targetFullPath.c_str(),
buildTargetRuleName.c_str());
// Write the main driver rule to build everything in this target.
this->WriteTargetDriverRule(targetFullPath.c_str(), relink);
// Clean all the possible library names and symlinks and object files.
this->CleanFiles.insert(this->CleanFiles.end(),

View File

@ -99,7 +99,7 @@ void cmMakefileTargetGenerator::CreateRuleFile()
}
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteCustomCommandsForTarget()
void cmMakefileTargetGenerator::WriteTargetBuildRules()
{
// write the custom commands for this target
// Look for files registered for cleaning in this directory.
@ -110,7 +110,56 @@ void cmMakefileTargetGenerator::WriteCustomCommandsForTarget()
cmSystemTools::ExpandListArgument(additional_clean_files,
this->CleanFiles);
}
this->WriteCustomCommands();
// add custom commands to the clean rules?
const char* clean_no_custom =
this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
bool clean = cmSystemTools::IsOff(clean_no_custom);
// First generate the object rule files. Save a list of all object
// files for this target.
const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
source != sources.end(); ++source)
{
if(cmCustomCommand* cc = (*source)->GetCustomCommand())
{
this->GenerateCustomRuleFile(*cc);
if (clean)
{
const std::vector<std::string>& outputs = cc->GetOutputs();
for(std::vector<std::string>::const_iterator o = outputs.begin();
o != outputs.end(); ++o)
{
this->CleanFiles.push_back
(this->Convert(o->c_str(),
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::UNCHANGED));
}
}
}
else if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY"))
{
if(!this->GlobalGenerator->IgnoreFile
((*source)->GetSourceExtension().c_str()))
{
// Generate this object file's rule file.
this->WriteObjectRuleFiles(*(*source));
}
else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
{
// This is an external object file. Just add it.
this->ExternalObjects.push_back((*source)->GetFullPath());
}
else
{
// We only get here if a source file is not an external object
// and has an extension that is listed as an ignored file type
// for this language. No message or diagnosis should be
// given.
}
}
}
}
@ -159,37 +208,11 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
cmLocalGenerator::HOME_OUTPUT,
cmLocalGenerator::MAKEFILE)
<< "\n\n";
// First generate the object rule files. Save a list of all object
// files for this target.
const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
source != sources.end(); ++source)
{
if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY") &&
!(*source)->GetCustomCommand())
{
if(!this->GlobalGenerator->IgnoreFile
((*source)->GetSourceExtension().c_str()))
{
// Generate this object file's rule file.
this->WriteObjectRuleFiles(*(*source));
}
else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
{
// This is an external object file. Just add it.
this->ExternalObjects.push_back((*source)->GetFullPath());
}
else
{
// We only get here if a source file is not an external object
// and has an extension that is listed as an ignored file type
// for this language. No message or diagnosis should be
// given.
}
}
}
}
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
{
// write language flags for target
std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>&
checkSet =
@ -653,39 +676,6 @@ void cmMakefileTargetGenerator
}
}
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteCustomCommands()
{
// add custom commands to the clean rules?
const char* clean_no_custom =
this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
bool clean = cmSystemTools::IsOff(clean_no_custom);
// Generate the rule files for each custom command.
const std::vector<cmSourceFile*> &classes =
this->Makefile->GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
i != classes.end(); i++)
{
if(cmCustomCommand* cc = (*i)->GetCustomCommand())
{
this->GenerateCustomRuleFile(*cc);
if (clean)
{
const std::vector<std::string>& outputs = cc->GetOutputs();
for(std::vector<std::string>::const_iterator o = outputs.begin();
o != outputs.end(); ++o)
{
this->CleanFiles.push_back
(this->Convert(o->c_str(),
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::UNCHANGED));
}
}
}
}
}
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator
::GenerateCustomRuleFile(const cmCustomCommand& cc)
@ -815,6 +805,61 @@ cmMakefileTargetGenerator
*this->BuildFileStream << "\n" << "\n";
}
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
bool relink)
{
// Compute the name of the driver target.
std::string dir = this->Makefile->GetStartOutputDirectory();
dir += "/";
dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
std::string buildTargetRuleName = dir;
buildTargetRuleName += relink?"/preinstall":"/build";
buildTargetRuleName = this->Convert(buildTargetRuleName.c_str(),
cmLocalGenerator::HOME_OUTPUT,
cmLocalGenerator::MAKEFILE);
// Build the list of target outputs to drive.
std::vector<std::string> depends;
if(main_output)
{
depends.push_back(main_output);
}
const char* comment = 0;
if(relink)
{
// Setup the comment for the preinstall driver.
comment = "Rule to relink during preinstall.";
}
else
{
// Setup the comment for the main build driver.
comment = "Rule to build all files generated by this target.";
// Make sure all custom command outputs in this target are built.
const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
source != sources.end(); ++source)
{
if(cmCustomCommand* cc = (*source)->GetCustomCommand())
{
const std::vector<std::string>& outputs = cc->GetOutputs();
for(std::vector<std::string>::const_iterator o = outputs.begin();
o != outputs.end(); ++o)
{
depends.push_back(*o);
}
}
}
}
// Write the driver rule.
std::vector<std::string> no_commands;
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
buildTargetRuleName.c_str(),
depends, no_commands, true);
}
//----------------------------------------------------------------------------
std::string cmMakefileTargetGenerator::GetFrameworkFlags()

View File

@ -55,11 +55,13 @@ protected:
// create the file and directory etc
void CreateRuleFile();
// outputs the rules for any custom commands used by this target
void WriteCustomCommandsForTarget();
// outputs the rules for object files and custom commands used by
// this target
void WriteTargetBuildRules();
// write some common code at the top of build.make
void WriteCommonCodeRules();
void WriteTargetLanguageFlags();
// write the provide require rules for this target
void WriteTargetRequiresRules();
@ -83,15 +85,16 @@ protected:
void WriteObjectDependRules(cmSourceFile& source,
std::vector<std::string>& depends);
// this is responsible for writing all of the rules for all this
// directories custom commands (but not utility targets)
void WriteCustomCommands();
// write the build rule for a custom command
void GenerateCustomRuleFile(const cmCustomCommand& cc);
// write out the variable that lists the objects for this target
void WriteObjectsVariable(std::string& variableName,
std::string& variableNameExternal);
// write the driver rule to build target outputs
void WriteTargetDriverRule(const char* main_output, bool relink);
// Return the a string with -F flags on apple
std::string GetFrameworkFlags();

View File

@ -33,7 +33,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
<< "# Utility rule file for " << this->Target->GetName() << ".\n\n";
// write the custom commands for this target
this->WriteCustomCommandsForTarget();
this->WriteTargetBuildRules();
// Collect the commands and dependencies.
std::vector<std::string> commands;
@ -63,19 +63,8 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
this->Target->GetName(),
depends, commands, true);
// Write convenience targets.
std::string dir = this->Makefile->GetStartOutputDirectory();
dir += "/";
dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
std::string buildTargetRuleName = dir;
buildTargetRuleName += "/build";
buildTargetRuleName =
this->LocalGenerator->Convert(buildTargetRuleName.c_str(),
cmLocalGenerator::HOME_OUTPUT,
cmLocalGenerator::MAKEFILE);
this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
this->Target->GetName(),
buildTargetRuleName.c_str());
// Write the main driver rule to build everything in this target.
this->WriteTargetDriverRule(this->Target->GetName(), false);
// Write clean target
this->WriteTargetCleanRules();