diff options
author | Brad King <brad.king@kitware.com> | 2004-11-02 22:14:04 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2004-11-02 22:14:04 (GMT) |
commit | 04f958b6d9b024ba7cefd5b914fb946685a71d8d (patch) | |
tree | c63dd7b965f73a56778cb22b6dc77e7cb495edcf /Source/cmLocalUnixMakefileGenerator2.cxx | |
parent | 95f67dca9e93ad789088dec47526acf7331d2969 (diff) | |
download | CMake-04f958b6d9b024ba7cefd5b914fb946685a71d8d.zip CMake-04f958b6d9b024ba7cefd5b914fb946685a71d8d.tar.gz CMake-04f958b6d9b024ba7cefd5b914fb946685a71d8d.tar.bz2 |
ENH: Implemented generation of custom command rule files.
Diffstat (limited to 'Source/cmLocalUnixMakefileGenerator2.cxx')
-rw-r--r-- | Source/cmLocalUnixMakefileGenerator2.cxx | 215 |
1 files changed, 178 insertions, 37 deletions
diff --git a/Source/cmLocalUnixMakefileGenerator2.cxx b/Source/cmLocalUnixMakefileGenerator2.cxx index ac73b96..aaae759 100644 --- a/Source/cmLocalUnixMakefileGenerator2.cxx +++ b/Source/cmLocalUnixMakefileGenerator2.cxx @@ -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. this->GenerateMakefile(); @@ -104,8 +115,8 @@ void cmLocalUnixMakefileGenerator2::GenerateMakefile() // Write the subdirectory driver rules. this->WriteSubdirRules(makefileStream, "all"); - // Write include statements to get rules for each target. - this->WriteTargetIncludes(makefileStream); + // Write include statements to get rules for this directory. + this->WriteRuleFileIncludes(makefileStream); // Write jump-and-build rules that were recorded in the map. this->WriteJumpAndBuildRules(makefileStream); @@ -196,6 +207,11 @@ cmLocalUnixMakefileGenerator2 for(std::vector<cmSourceFile*>::const_iterator source = sources.begin(); 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") && !(*source)->GetCustomCommand() && !m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str())) @@ -214,12 +230,17 @@ cmLocalUnixMakefileGenerator2 depBase += target.GetName(); std::string depMakeFile = this->GenerateDependsMakeFile(depBase.c_str()); - // Open the rule file. This should be copy-if-different because the - // rules may depend on this file itself. + // Construct the rule file name. std::string ruleFileName = dir; ruleFileName += "/"; ruleFileName += target.GetName(); 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); cmGeneratedFileStream ruleFile(ruleFileNameFull.c_str()); std::ostream& ruleFileStream = ruleFile.GetStream(); @@ -482,6 +503,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 cmLocalUnixMakefileGenerator2 ::GenerateDependsMakeFile(const char* file) @@ -790,7 +920,7 @@ cmLocalUnixMakefileGenerator2 std::vector<std::string> no_depends; std::vector<std::string> commands; 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, "Special rule to re-run CMake cache editor using make.", "Running CMake cache editor...", @@ -1105,43 +1235,30 @@ cmLocalUnixMakefileGenerator2 //---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator2 -::WriteTargetIncludes(std::ostream& makefileStream) +::WriteRuleFileIncludes(std::ostream& makefileStream) { - bool first = true; - const cmTargets& targets = m_Makefile->GetTargets(); - for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t) + // Make sure we have some rules to include. + if(m_IncludeRuleFiles.empty()) { - // TODO: Handle the rest of the target types. - 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. - std::string ruleFileName = this->GetTargetDirectory(t->second); - ruleFileName += "/"; - ruleFileName += t->first; - ruleFileName += ".make"; - makefileStream - << m_IncludeDirective << " " - << this->ConvertToOutputForExisting(ruleFileName.c_str()).c_str() - << "\n"; - } + return; } - if(!first) + + // Write section header. + this->WriteDivider(makefileStream); + makefileStream + << "# Include rule files for this directory.\n" + << "\n"; + + // Write the include rules. + for(std::vector<std::string>::const_iterator i = m_IncludeRuleFiles.begin(); + i != m_IncludeRuleFiles.end(); ++i) { - makefileStream << "\n"; + makefileStream + << m_IncludeDirective << " " + << this->ConvertToOutputForExisting(i->c_str()).c_str() + << "\n"; } + makefileStream << "\n"; } //---------------------------------------------------------------------------- @@ -1621,6 +1738,30 @@ cmLocalUnixMakefileGenerator2 } //---------------------------------------------------------------------------- +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* cmLocalUnixMakefileGenerator2 ::GetSourceFileLanguage(const cmSourceFile& source) |