From 4189370497f4f00c7a7d3ec6ba221879bfc8b58c Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 1 Jun 2006 11:45:51 -0400 Subject: 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. --- Source/cmMakefileExecutableTargetGenerator.cxx | 26 ++-- Source/cmMakefileLibraryTargetGenerator.cxx | 27 ++-- Source/cmMakefileTargetGenerator.cxx | 177 ++++++++++++++++--------- Source/cmMakefileTargetGenerator.h | 13 +- Source/cmMakefileUtilityTargetGenerator.cxx | 17 +-- 5 files changed, 141 insertions(+), 119 deletions(-) diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 7bca8bb..7b30dd2 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/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(), diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index a8a186c..c3df2a5 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/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(), diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 96700b5..5a6df64 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/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& sources = this->Target->GetSourceFiles(); + for(std::vector::const_iterator source = sources.begin(); + source != sources.end(); ++source) + { + if(cmCustomCommand* cc = (*source)->GetCustomCommand()) + { + this->GenerateCustomRuleFile(*cc); + if (clean) + { + const std::vector& outputs = cc->GetOutputs(); + for(std::vector::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& sources = this->Target->GetSourceFiles(); - for(std::vector::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& checkSet = @@ -654,39 +677,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 &classes = - this->Makefile->GetSourceFiles(); - for(std::vector::const_iterator i = classes.begin(); - i != classes.end(); i++) - { - if(cmCustomCommand* cc = (*i)->GetCustomCommand()) - { - this->GenerateCustomRuleFile(*cc); - if (clean) - { - const std::vector& outputs = cc->GetOutputs(); - for(std::vector::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 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& sources = this->Target->GetSourceFiles(); + for(std::vector::const_iterator source = sources.begin(); + source != sources.end(); ++source) + { + if(cmCustomCommand* cc = (*source)->GetCustomCommand()) + { + const std::vector& outputs = cc->GetOutputs(); + for(std::vector::const_iterator o = outputs.begin(); + o != outputs.end(); ++o) + { + depends.push_back(*o); + } + } + } + } + + // Write the driver rule. + std::vector no_commands; + this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment, + buildTargetRuleName.c_str(), + depends, no_commands, true); +} //---------------------------------------------------------------------------- std::string cmMakefileTargetGenerator::GetFrameworkFlags() diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index c2422d7..35c702d 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/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& 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(); diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 474f850..51a848f 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/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 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(); -- cgit v0.12