Browse Source

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.

pull/1/head
Brad King 19 years ago
parent
commit
4189370497
  1. 26
      Source/cmMakefileExecutableTargetGenerator.cxx
  2. 27
      Source/cmMakefileLibraryTargetGenerator.cxx
  3. 177
      Source/cmMakefileTargetGenerator.cxx
  4. 13
      Source/cmMakefileTargetGenerator.h
  5. 17
      Source/cmMakefileUtilityTargetGenerator.cxx

26
Source/cmMakefileExecutableTargetGenerator.cxx

@ -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(),

27
Source/cmMakefileLibraryTargetGenerator.cxx

@ -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(),

177
Source/cmMakefileTargetGenerator.cxx

@ -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()

13
Source/cmMakefileTargetGenerator.h

@ -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();

17
Source/cmMakefileUtilityTargetGenerator.cxx

@ -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();

Loading…
Cancel
Save