]> granicus.if.org Git - clang/commitdiff
[clang][Tooling] Infer target and mode from argv[0] when using JSONCompilationDatabase
authorKadir Cetinkaya <kadircet@google.com>
Wed, 26 Jun 2019 07:39:03 +0000 (07:39 +0000)
committerKadir Cetinkaya <kadircet@google.com>
Wed, 26 Jun 2019 07:39:03 +0000 (07:39 +0000)
Summary:
Wraps JSON compilation database with a target and mode adding database
wrapper. So that driver can correctly figure out which toolchain to use.

Note that clients that wants to make use of this target discovery mechanism
needs to link in TargetsInfos and initialize them at startup.

Reviewers: ilya-biryukov

Subscribers: mgorny, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D63755

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@364386 91177308-0d34-0410-b5e6-96231b3b80d8

bindings/python/tests/cindex/test_cdb.py
include/clang/Tooling/CompilationDatabase.h
lib/Tooling/CMakeLists.txt
lib/Tooling/GuessTargetAndModeCompilationDatabase.cpp [new file with mode: 0644]
lib/Tooling/JSONCompilationDatabase.cpp
unittests/Tooling/CompilationDatabaseTest.cpp

index e2a48f14cdeb9be238c72764a632a01fc2215dd8..99bc72143beffa3d24077bfb035b84b78d0db63f 100644 (file)
@@ -63,15 +63,16 @@ class TestCDB(unittest.TestCase):
         expected = [
             { 'wd': '/home/john.doe/MyProject',
               'file': '/home/john.doe/MyProject/project.cpp',
-              'line': ['clang++', '-o', 'project.o', '-c',
+              'line': ['clang++', '--driver-mode=g++', '-o', 'project.o', '-c',
                        '/home/john.doe/MyProject/project.cpp']},
             { 'wd': '/home/john.doe/MyProjectA',
               'file': '/home/john.doe/MyProject/project2.cpp',
-              'line': ['clang++', '-o', 'project2.o', '-c',
+              'line': ['clang++', '--driver-mode=g++', '-o', 'project2.o', '-c',
                        '/home/john.doe/MyProject/project2.cpp']},
             { 'wd': '/home/john.doe/MyProjectB',
               'file': '/home/john.doe/MyProject/project2.cpp',
-              'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c',
+              'line': ['clang++', '--driver-mode=g++', '-DFEATURE=1', '-o',
+                       'project2-feature.o', '-c',
                        '/home/john.doe/MyProject/project2.cpp']},
 
             ]
@@ -89,7 +90,7 @@ class TestCDB(unittest.TestCase):
         self.assertEqual(len(cmds), 1)
         self.assertEqual(cmds[0].directory, os.path.dirname(file))
         self.assertEqual(cmds[0].filename, file)
-        expected = [ 'clang++', '-o', 'project.o', '-c',
+        expected = [ 'clang++', '--driver-mode=g++', '-o', 'project.o', '-c',
                      '/home/john.doe/MyProject/project.cpp']
         for arg, exp in zip(cmds[0].arguments, expected):
             self.assertEqual(arg, exp)
@@ -101,10 +102,11 @@ class TestCDB(unittest.TestCase):
         self.assertEqual(len(cmds), 2)
         expected = [
             { 'wd': '/home/john.doe/MyProjectA',
-              'line': ['clang++', '-o', 'project2.o', '-c',
+              'line': ['clang++', '--driver-mode=g++', '-o', 'project2.o', '-c',
                        '/home/john.doe/MyProject/project2.cpp']},
             { 'wd': '/home/john.doe/MyProjectB',
-              'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c',
+              'line': ['clang++', '--driver-mode=g++', '-DFEATURE=1', '-o',
+                       'project2-feature.o', '-c',
                        '/home/john.doe/MyProject/project2.cpp']}
             ]
         for i in range(len(cmds)):
index 01f6e679a05965890d13af98c3e080b2efe47c34..dea046a2dc7c3a939331ef5660e729bbd5cb636d 100644 (file)
@@ -213,6 +213,12 @@ private:
 std::unique_ptr<CompilationDatabase>
     inferMissingCompileCommands(std::unique_ptr<CompilationDatabase>);
 
+/// Returns a wrapped CompilationDatabase that will add -target and -mode flags
+/// to commandline when they can be deduced from argv[0] of commandline returned
+/// by underlying database.
+std::unique_ptr<CompilationDatabase>
+inferTargetAndDriverMode(std::unique_ptr<CompilationDatabase> Base);
+
 } // namespace tooling
 } // namespace clang
 
index 6ed2f25acda6875103ba36185cd63aa6bd585a35..5a380fb8cce94abe27400dc14cd43abca186f695 100644 (file)
@@ -17,6 +17,7 @@ add_clang_library(clangTooling
   Execution.cpp
   FileMatchTrie.cpp
   FixIt.cpp
+  GuessTargetAndModeCompilationDatabase.cpp
   InterpolatingCompilationDatabase.cpp
   JSONCompilationDatabase.cpp
   Refactoring.cpp
diff --git a/lib/Tooling/GuessTargetAndModeCompilationDatabase.cpp b/lib/Tooling/GuessTargetAndModeCompilationDatabase.cpp
new file mode 100644 (file)
index 0000000..ac3faf1
--- /dev/null
@@ -0,0 +1,57 @@
+//===- GuessTargetAndModeCompilationDatabase.cpp --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Tooling.h"
+#include <memory>
+
+namespace clang {
+namespace tooling {
+
+namespace {
+class TargetAndModeAdderDatabase : public CompilationDatabase {
+public:
+  TargetAndModeAdderDatabase(std::unique_ptr<CompilationDatabase> Base)
+      : Base(std::move(Base)) {
+    assert(this->Base != nullptr);
+  }
+
+  std::vector<std::string> getAllFiles() const override {
+    return Base->getAllFiles();
+  }
+
+  std::vector<CompileCommand> getAllCompileCommands() const override {
+    return addTargetAndMode(Base->getAllCompileCommands());
+  }
+
+  std::vector<CompileCommand>
+  getCompileCommands(StringRef FilePath) const override {
+    return addTargetAndMode(Base->getCompileCommands(FilePath));
+  }
+
+private:
+  std::vector<CompileCommand>
+  addTargetAndMode(std::vector<CompileCommand> Cmds) const {
+    for (auto &Cmd : Cmds) {
+      if (Cmd.CommandLine.empty())
+        continue;
+      addTargetAndModeForProgramName(Cmd.CommandLine, Cmd.CommandLine.front());
+    }
+    return Cmds;
+  }
+  std::unique_ptr<CompilationDatabase> Base;
+};
+} // namespace
+
+std::unique_ptr<CompilationDatabase>
+inferTargetAndDriverMode(std::unique_ptr<CompilationDatabase> Base) {
+  return llvm::make_unique<TargetAndModeAdderDatabase>(std::move(Base));
+}
+
+} // namespace tooling
+} // namespace clang
index 0ee9d174b441d7a15dd5b195dfca74f1a5c4abb1..76a82b0fd9bd365c4fc07c6b39976f8370af25c5 100644 (file)
@@ -14,7 +14,9 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Tooling/CompilationDatabase.h"
 #include "clang/Tooling/CompilationDatabasePluginRegistry.h"
+#include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -165,7 +167,9 @@ class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin {
     llvm::sys::path::append(JSONDatabasePath, "compile_commands.json");
     auto Base = JSONCompilationDatabase::loadFromFile(
         JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect);
-    return Base ? inferMissingCompileCommands(std::move(Base)) : nullptr;
+    return Base ? inferTargetAndDriverMode(
+                      inferMissingCompileCommands(std::move(Base)))
+                : nullptr;
   }
 };
 
index 19b797a0a6408d87ef53eb946baa18c9acf4486b..d86c9bf79a2785f3a0adcb8ba84fcae323d25f95 100644 (file)
@@ -9,10 +9,12 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclGroup.h"
 #include "clang/Frontend/FrontendAction.h"
+#include "clang/Tooling/CompilationDatabase.h"
 #include "clang/Tooling/FileMatchTrie.h"
 #include "clang/Tooling/JSONCompilationDatabase.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/TargetSelect.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -632,7 +634,7 @@ struct MemCDB : public CompilationDatabase {
   }
 };
 
-class InterpolateTest : public ::testing::Test {
+class MemDBTest : public ::testing::Test {
 protected:
   // Adds an entry to the underlying compilation database.
   // A flag is injected: -D <File>, so the command used can be identified.
@@ -658,6 +660,11 @@ protected:
     return Result.str();
   }
 
+  MemCDB::EntryMap Entries;
+};
+
+class InterpolateTest : public MemDBTest {
+protected:
   // Look up the command from a relative path, and return it in string form.
   // The input file is not included in the returned command.
   std::string getCommand(llvm::StringRef F) {
@@ -693,8 +700,6 @@ protected:
     llvm::sys::path::native(Result, llvm::sys::path::Style::posix);
     return Result.str();
   }
-
-  MemCDB::EntryMap Entries;
 };
 
 TEST_F(InterpolateTest, Nearby) {
@@ -804,5 +809,30 @@ TEST(CompileCommandTest, EqualityOperator) {
   EXPECT_TRUE(CCRef != CCTest);
 }
 
+class TargetAndModeTest : public MemDBTest {
+public:
+  TargetAndModeTest() { llvm::InitializeAllTargetInfos(); }
+
+protected:
+  // Look up the command from a relative path, and return it in string form.
+  std::string getCommand(llvm::StringRef F) {
+    auto Results = inferTargetAndDriverMode(llvm::make_unique<MemCDB>(Entries))
+                       ->getCompileCommands(path(F));
+    if (Results.empty())
+      return "none";
+    return llvm::join(Results[0].CommandLine, " ");
+  }
+};
+
+TEST_F(TargetAndModeTest, TargetAndMode) {
+  add("foo.cpp", "clang-cl", "");
+  add("bar.cpp", "x86_64-linux-clang", "");
+
+  EXPECT_EQ(getCommand("foo.cpp"),
+            "clang-cl --driver-mode=cl foo.cpp -D foo.cpp");
+  EXPECT_EQ(getCommand("bar.cpp"),
+            "x86_64-linux-clang -target x86_64-linux bar.cpp -D bar.cpp");
+}
+
 } // end namespace tooling
 } // end namespace clang