Prechádzať zdrojové kódy

ENH: Added generation of rules to manually request preprocessed or generated assembly sources.

Brad King 19 rokov pred
rodič
commit
5cfa1b02ab

+ 4 - 0
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 "<CMAKE_C_COMPILER> <FLAGS> -o <PREPROCESSED_SOURCE> -E <SOURCE>")
+  SET (CMAKE_C_CREATE_ASSEMBLY_SOURCE "<CMAKE_C_COMPILER> <FLAGS> -o <ASSEMBLY_SOURCE> -S <SOURCE>")
 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 "<CMAKE_CXX_COMPILER> <FLAGS> -o <PREPROCESSED_SOURCE> -E <SOURCE>")
+  SET (CMAKE_CXX_CREATE_ASSEMBLY_SOURCE "<CMAKE_CXX_COMPILER> <FLAGS> -o <ASSEMBLY_SOURCE> -S <SOURCE>")
 ENDIF(CMAKE_COMPILER_IS_GNUCXX)
 

+ 14 - 0
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")

+ 4 - 0
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;

+ 34 - 2
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -274,16 +274,41 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
       static_cast<cmGlobalUnixMakefileGenerator3*>(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<cmStdString,std::vector<cmTarget *> >::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<std::string> 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.",

+ 6 - 0
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

+ 98 - 0
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<std::string> 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<std::string>::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<std::string>::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;