[clang][Tooling] Infer target and mode from argv[0] when using JSONCompilationDatabase

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
This commit is contained in:
Kadir Cetinkaya
2019-06-26 07:39:03 +00:00
parent 8d068d6ad4
commit 617f68365c
6 changed files with 110 additions and 10 deletions
+8 -6
View 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)):
@@ -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
+1
View File
@@ -17,6 +17,7 @@ add_clang_library(clangTooling
Execution.cpp
FileMatchTrie.cpp
FixIt.cpp
GuessTargetAndModeCompilationDatabase.cpp
InterpolatingCompilationDatabase.cpp
JSONCompilationDatabase.cpp
Refactoring.cpp
@@ -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
+5 -1
View 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;
}
};
+33 -3
View 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