فهرست منبع

Adds a test for the compile command line output.

Manuel Klimek 14 سال پیش
والد
کامیت
0e6b05fcba

+ 3 - 0
Tests/CMakeLib/CMakeLists.txt

@@ -30,3 +30,6 @@ endif()
 foreach(test ${CMakeLib_TESTS})
   add_test(CMakeLib.${test} CMakeLibTests ${test})
 endforeach()
+
+ADD_EXECUTABLE(runcompilecommands run_compile_commands.cxx)
+TARGET_LINK_LIBRARIES(runcompilecommands CMakeLib)

+ 132 - 0
Tests/CMakeLib/run_compile_commands.cxx

@@ -0,0 +1,132 @@
+#include "cmSystemTools.h"
+
+class CompileCommandParser {
+public:
+  typedef std::map<std::string, std::string> CommandType;
+  typedef std::vector<CommandType> TranslationUnitsType;
+
+  CompileCommandParser(std::ifstream *input)
+  {
+    this->Input = input;
+  }
+
+  void Parse()
+  {
+    NextNonWhitespace();
+    ParseTranslationUnits();
+  }
+
+  const TranslationUnitsType& GetTranslationUnits()
+  {
+    return this->TranslationUnits;
+  }
+
+private:
+  void ParseTranslationUnits()
+  {
+    this->TranslationUnits = TranslationUnitsType();
+    ExpectOrDie('[', "at start of compile command file");
+    do
+      {
+      ParseTranslationUnit();
+      this->TranslationUnits.push_back(this->Command);
+      } while(Expect(','));
+    ExpectOrDie(']', "at end of array");
+  }
+
+  void ParseTranslationUnit()
+  {
+    this->Command = CommandType();
+    if(!Expect('{')) return;
+    if(Expect('}')) return;
+    do
+      {
+      ParseString();
+      std::string name = this->String;
+      ExpectOrDie(':', "between name and value");
+      ParseString();
+      std::string value = this->String;
+      this->Command[name] = value;
+      } while(Expect(','));
+    ExpectOrDie('}', "at end of object");
+  }
+
+  void ParseString()
+  {
+    this->String.clear();
+    if(!Expect('"')) return;
+    while (!Expect('"'))
+      {
+      Expect('\\');
+      this->String.push_back(C);
+      Next();
+      }
+  }
+
+  bool Expect(char c)
+  {
+    if(this->C == c)
+      {
+      NextNonWhitespace();
+      return true;
+      }
+    return false;
+  }
+
+  void ExpectOrDie(char c, const std::string & message)
+  {
+    if (!Expect(c))
+      ErrorExit(std::string("'") + c + "' expected " + message + ".");
+  }
+
+  void NextNonWhitespace()
+  {
+    do { Next(); } while (IsWhitespace());
+  }
+
+  void Next()
+  {
+    this->C = Input->get();
+    if (this->Input->bad()) ErrorExit("Unexpected end of file.");
+  }
+
+  void ErrorExit(const std::string &message) {
+    std::cout << "ERROR: " << message;
+    exit(1);
+  }
+
+  bool IsWhitespace()
+  {
+    return (this->C == ' ' || this->C == '\t' ||
+            this->C == '\n' || this->C == '\r');
+  }
+
+  char C;
+  TranslationUnitsType TranslationUnits;
+  CommandType Command;
+  std::string String;
+  std::ifstream *Input;
+};
+
+int main ()
+{
+  std::ifstream file("compile_commands.json");
+  CompileCommandParser parser(&file);
+  parser.Parse();
+  for(CompileCommandParser::TranslationUnitsType::const_iterator
+      it = parser.GetTranslationUnits().begin(),
+      end = parser.GetTranslationUnits().end(); it != end; ++it)
+    {
+    std::vector<std::string> std_command;
+    cmSystemTools::ParseUnixCommandLine(it->at("command").c_str(), std_command);
+    std::vector<cmStdString> command(std_command.begin(), std_command.end());
+    if (!cmSystemTools::RunSingleCommand(
+            command, 0, 0, it->at("directory").c_str()))
+      {
+      std::cout << "ERROR: Failed to run command \""
+                << command[0] << "\"" << std::endl;
+      exit(1);
+      }
+    }
+  return 0;
+}

+ 3 - 0
Tests/CMakeLists.txt

@@ -2031,6 +2031,9 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
     ENDIF()
     SET_TESTS_PROPERTIES(Contracts.${project} PROPERTIES TIMEOUT ${timeout})
   ENDFOREACH()
+
+  ADD_TEST_MACRO(CompileCommandOutput
+    "${CMake_BINARY_DIR}/Tests/CMakeLib/runcompilecommands")
 ENDIF(BUILD_TESTING)
 
 SUBDIRS(CMakeTests)

+ 11 - 0
Tests/CompileCommandOutput/CMakeLists.txt

@@ -0,0 +1,11 @@
+# a simple C only test case
+cmake_minimum_required (VERSION 2.6)
+project (CompileCommandOutput CXX)
+
+SET(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+set(CMAKE_DEBUG_POSTFIX "_test_debug_postfix")
+ADD_LIBRARY(test1 STATIC "file with spaces.cxx")
+ADD_LIBRARY(test2 SHARED "../CompileCommandOutput/relative.cxx")
+INCLUDE_DIRECTORIES(${CompileCommandOutput_SOURCE_DIR}/../../Source)
+ADD_EXECUTABLE(CompileCommandOutput compile_command_output.cxx)
+TARGET_LINK_LIBRARIES(CompileCommandOutput test1 test2)

+ 9 - 0
Tests/CompileCommandOutput/compile_command_output.cxx

@@ -0,0 +1,9 @@
+#include "file with spaces.h"
+#include "relative.h"
+
+int main (int argc, char** argv)
+{
+  file_with_spaces();
+  relative();
+  return 0;
+}

+ 3 - 0
Tests/CompileCommandOutput/file with spaces.cxx

@@ -0,0 +1,3 @@
+#include "file with spaces.h"
+
+void file_with_spaces() {}

+ 1 - 0
Tests/CompileCommandOutput/file with spaces.h

@@ -0,0 +1 @@
+void file_with_spaces();

+ 3 - 0
Tests/CompileCommandOutput/relative.cxx

@@ -0,0 +1,3 @@
+#include "relative.h"
+
+void relative() {}

+ 1 - 0
Tests/CompileCommandOutput/relative.h

@@ -0,0 +1 @@
+void relative();