浏览代码

implement cxx command output

Manuel Klimek 15 年之前
父节点
当前提交
fe07b0557b

+ 41 - 0
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -31,6 +31,7 @@ cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
 #else
   this->UseLinkScript = true;
 #endif
+  this->CommandDatabase = NULL;
 }
 
 void cmGlobalUnixMakefileGenerator3
@@ -139,6 +140,17 @@ void cmGlobalUnixMakefileGenerator3
 }
 
 //----------------------------------------------------------------------------
+std::string EscapeJSON(const std::string& s) {
+  std::string result;
+  for (int i = 0; i < s.size(); ++i) {
+    if (s[i] == '"' || s[i] == '\\') {
+      result += '\\';
+    }
+    result += s[i];
+  }
+  return result;
+}
+
 void cmGlobalUnixMakefileGenerator3::Generate()
 {
   // first do superclass method
@@ -189,6 +201,35 @@ void cmGlobalUnixMakefileGenerator3::Generate()
   // write the main makefile
   this->WriteMainMakefile2();
   this->WriteMainCMakefile();
+
+  if (this->CommandDatabase != NULL) {
+    *this->CommandDatabase << std::endl << "]";
+    delete this->CommandDatabase;
+    this->CommandDatabase = NULL;
+  }
+}
+
+void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand(
+    const std::string &sourceFile, const std::string &workingDirectory,
+    const std::string &compileCommand) {
+  if (this->CommandDatabase == NULL)
+    {
+    std::string commandDatabaseName =
+      std::string(this->GetCMakeInstance()->GetHomeOutputDirectory())
+      + "/cxx_commands.json";
+    this->CommandDatabase =
+      new cmGeneratedFileStream(commandDatabaseName.c_str());
+    *this->CommandDatabase << "[" << std::endl;
+    } else {
+    *this->CommandDatabase << "," << std::endl;
+    }
+  *this->CommandDatabase << "{" << std::endl
+      << "  \"directory\": \"" << EscapeJSON(workingDirectory) << "\","
+      << std::endl
+      << "  \"command\": \"" << EscapeJSON(compileCommand) << "\","
+      << std::endl
+      << "  \"file\": \"" << EscapeJSON(sourceFile) << "\""
+      << std::endl << "}";
 }
 
 void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()

+ 6 - 0
Source/cmGlobalUnixMakefileGenerator3.h

@@ -112,6 +112,10 @@ public:
   /** Record per-target progress information.  */
   void RecordTargetProgress(cmMakefileTargetGenerator* tg);
 
+  void AddCXXCompileCommand(const std::string &sourceFile,
+                            const std::string &workingDirectory,
+                            const std::string &compileCommand);
+
 protected:
   void WriteMainMakefile2();
   void WriteMainCMakefile();
@@ -178,6 +182,8 @@ protected:
   size_t CountProgressMarksInTarget(cmTarget* target,
                                     std::set<cmTarget*>& emitted);
   size_t CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg);
+
+  cmGeneratedFileStream *CommandDatabase;
 };
 
 #endif

+ 19 - 2
Source/cmMakefileTargetGenerator.cxx

@@ -658,6 +658,9 @@ cmMakefileTargetGenerator
   vars.Flags = flags.c_str();
   vars.Defines = defines.c_str();
 
+  bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) ||
+                           (strcmp(lang, "CXX") == 0));
+
   // Construct the compile rules.
   {
   std::string compileRuleVar = "CMAKE_";
@@ -668,6 +671,22 @@ cmMakefileTargetGenerator
   std::vector<std::string> compileCommands;
   cmSystemTools::ExpandListArgument(compileRule, compileCommands);
 
+  if (lang_is_c_or_cxx && compileCommands.size() == 1)
+    {
+    std::string compileCommand = compileCommands[0];
+    this->LocalGenerator->ExpandRuleVariables(compileCommand, vars);
+    std::string workingDirectory =
+      this->LocalGenerator->Convert(
+        this->Makefile->GetStartOutputDirectory(), cmLocalGenerator::FULL);
+    compileCommand.replace(compileCommand.find(langFlags),
+                           langFlags.size(), this->GetFlags(lang));
+    std::string langDefines = std::string("$(") + lang + "_DEFINES)";
+    compileCommand.replace(compileCommand.find(langDefines),
+                           langDefines.size(), this->GetDefines(lang));
+    this->GlobalGenerator->AddCXXCompileCommand(
+      source.GetFullPath(), workingDirectory, compileCommand);
+    }
+
   // Expand placeholders in the commands.
   for(std::vector<std::string>::iterator i = compileCommands.begin();
       i != compileCommands.end(); ++i)
@@ -708,8 +727,6 @@ cmMakefileTargetGenerator
       }
     }
 
-  bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) ||
-                           (strcmp(lang, "CXX") == 0));
   bool do_preprocess_rules = lang_is_c_or_cxx &&
     this->LocalGenerator->GetCreatePreprocessedSourceRules();
   bool do_assembly_rules = lang_is_c_or_cxx &&