From 5cfa1b02ab48abe10f323846d9b8886946ac1954 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 7 Aug 2006 23:25:21 -0400 Subject: [PATCH] ENH: Added generation of rules to manually request preprocessed or generated assembly sources. --- Modules/Platform/gcc.cmake | 4 + Source/cmLocalGenerator.cxx | 14 ++++ Source/cmLocalGenerator.h | 4 + Source/cmLocalUnixMakefileGenerator3.cxx | 36 ++++++++- Source/cmLocalUnixMakefileGenerator3.h | 6 ++ Source/cmMakefileTargetGenerator.cxx | 98 ++++++++++++++++++++++++ 6 files changed, 160 insertions(+), 2 deletions(-) diff --git a/Modules/Platform/gcc.cmake b/Modules/Platform/gcc.cmake index 6543f5c03..be09e37c5 100644 --- a/Modules/Platform/gcc.cmake +++ b/Modules/Platform/gcc.cmake @@ -4,6 +4,8 @@ IF(CMAKE_COMPILER_IS_GNUCC) SET (CMAKE_C_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG") SET (CMAKE_C_FLAGS_RELEASE_INIT "-O3 -DNDEBUG") SET (CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g") + SET (CMAKE_C_CREATE_PREPROCESSED_SOURCE " -o -E ") + SET (CMAKE_C_CREATE_ASSEMBLY_SOURCE " -o -S ") ENDIF(CMAKE_COMPILER_IS_GNUCC) IF(CMAKE_COMPILER_IS_GNUCXX) @@ -12,5 +14,7 @@ IF(CMAKE_COMPILER_IS_GNUCXX) SET (CMAKE_CXX_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG") SET (CMAKE_CXX_FLAGS_RELEASE_INIT "-O3 -DNDEBUG") SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g") + SET (CMAKE_CXX_CREATE_PREPROCESSED_SOURCE " -o -E ") + SET (CMAKE_CXX_CREATE_ASSEMBLY_SOURCE " -o -S ") ENDIF(CMAKE_COMPILER_IS_GNUCXX) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index fdeed5bbd..8447cb9c2 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -749,6 +749,20 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable, return replaceValues.Source; } } + if(replaceValues.PreprocessedSource) + { + if(variable == "PREPROCESSED_SOURCE") + { + return replaceValues.PreprocessedSource; + } + } + if(replaceValues.AssemblySource) + { + if(variable == "ASSEMBLY_SOURCE") + { + return replaceValues.AssemblySource; + } + } if(replaceValues.Object) { if(variable == "OBJECT") diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index ec0aafae7..03df6cbb8 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -186,6 +186,8 @@ public: this->Target= 0; this->LinkLibraries= 0; this->Source= 0; + this->AssemblySource = 0; + this->PreprocessedSource = 0; this->Object= 0; this->ObjectDir= 0; this->Flags= 0; @@ -200,6 +202,8 @@ public: const char* Target; const char* LinkLibraries; const char* Source; + const char* AssemblySource; + const char* PreprocessedSource; const char* Object; const char* ObjectDir; const char* Flags; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index dc301deb4..4386ccc56 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -274,16 +274,41 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() static_cast(this->GlobalGenerator); gg->WriteConvenienceRules(ruleFileStream,emittedTargets); } - + + bool do_preprocess_rules = + this->GetCreatePreprocessedSourceRules(); + bool do_assembly_rules = + this->GetCreateAssemblySourceRules(); + // now write out the object rules // for each object file name for (std::map >::iterator lo = this->LocalObjectFiles.begin(); lo != this->LocalObjectFiles.end(); ++lo) { + // Add a convenience rule for building the object file. this->WriteObjectConvenienceRule(ruleFileStream, "target to build an object file", lo->first.c_str(), lo->second); + + // Add convenience rules for preprocessed and assembly files. + if(do_preprocess_rules || do_assembly_rules) + { + std::string::size_type dot_pos = lo->first.rfind("."); + std::string base = lo->first.substr(0, dot_pos); + if(do_preprocess_rules) + { + this->WriteObjectConvenienceRule( + ruleFileStream, "target to preprocess a source file", + (base + ".E").c_str(), lo->second); + } + if(do_assembly_rules) + { + this->WriteObjectConvenienceRule( + ruleFileStream, "target to generate assembly for a file", + (base + ".S").c_str(), lo->second); + } + } } // add a help target as long as there isn;t a real target named help @@ -706,8 +731,15 @@ cmLocalUnixMakefileGenerator3 commands, false); } - // Special target to cleanup operation of make tool. + // Special symbolic target that never exists to force dependers to + // run their rules. std::vector depends; + this->WriteMakeRule + (makefileStream, + "A target that is always out of date.", + "cmake_force", depends, commands, true); + + // Special target to cleanup operation of make tool. this->WriteMakeRule (makefileStream, "Disable implicit rules so canoncical targets will work.", diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 9a61b30a0..7c6597afc 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -209,6 +209,12 @@ public: unsigned long GetNumberOfProgressActions(); unsigned long GetNumberOfProgressActionsForTarget(const char *); + /** Get whether to create rules to generate preprocessed and + assembly sources. This could be converted to a variable lookup + later. */ + bool GetCreatePreprocessedSourceRules() { return true; } + bool GetCreateAssemblySourceRules() { return true; } + protected: // these two methods just compute reasonable values for LibraryOutputPath // and ExecutableOutputPath diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index cadd0cb2d..c85a981bd 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -495,6 +495,104 @@ cmMakefileTargetGenerator relativeObj.c_str(), depends, commands, false); + bool do_preprocess_rules = + this->LocalGenerator->GetCreatePreprocessedSourceRules(); + bool do_assembly_rules = + this->LocalGenerator->GetCreateAssemblySourceRules(); + if(do_preprocess_rules || do_assembly_rules) + { + std::vector force_depends; + force_depends.push_back("cmake_force"); + std::string::size_type dot_pos = relativeObj.rfind("."); + std::string relativeObjBase = relativeObj.substr(0, dot_pos); + + if(do_preprocess_rules) + { + commands.clear(); + std::string relativeObjE = relativeObjBase + ".E"; + + std::string preprocessEcho = "Preprocessing "; + preprocessEcho += lang; + preprocessEcho += " source to "; + preprocessEcho += relativeObjE; + this->LocalGenerator->AppendEcho( + commands, preprocessEcho.c_str(), + cmLocalUnixMakefileGenerator3::EchoBuild + ); + + std::string preprocessRuleVar = "CMAKE_"; + preprocessRuleVar += lang; + preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE"; + if(const char* preprocessRule = + this->Makefile->GetDefinition(preprocessRuleVar.c_str())) + { + cmSystemTools::ExpandListArgument(preprocessRule, commands); + + vars.PreprocessedSource = relativeObjE.c_str(); + + // Expand placeholders in the commands. + for(std::vector::iterator i = commands.begin(); + i != commands.end(); ++i) + { + this->LocalGenerator->ExpandRuleVariables(*i, vars); + } + } + else + { + std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable "; + cmd += preprocessRuleVar; + commands.push_back(cmd); + } + + this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, + relativeObjE.c_str(), + force_depends, commands, false); + } + + if(do_assembly_rules) + { + commands.clear(); + std::string relativeObjS = relativeObjBase + ".S"; + + std::string assemblyEcho = "Compiling "; + assemblyEcho += lang; + assemblyEcho += " source to assembly "; + assemblyEcho += relativeObjS; + this->LocalGenerator->AppendEcho( + commands, assemblyEcho.c_str(), + cmLocalUnixMakefileGenerator3::EchoBuild + ); + + std::string assemblyRuleVar = "CMAKE_"; + assemblyRuleVar += lang; + assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE"; + if(const char* assemblyRule = + this->Makefile->GetDefinition(assemblyRuleVar.c_str())) + { + cmSystemTools::ExpandListArgument(assemblyRule, commands); + + vars.AssemblySource = relativeObjS.c_str(); + + // Expand placeholders in the commands. + for(std::vector::iterator i = commands.begin(); + i != commands.end(); ++i) + { + this->LocalGenerator->ExpandRuleVariables(*i, vars); + } + } + else + { + std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable "; + cmd += assemblyRuleVar; + commands.push_back(cmd); + } + + this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, + relativeObjS.c_str(), + force_depends, commands, false); + } + } + // If the language needs provides-requires mode, create the // corresponding targets. std::string objectRequires = relativeObj;