blob: e62a6f73afb276041fe54417857845d77c02ec9b [file] [log] [blame]
Manuel Klimekcb971c62012-04-04 12:07:46 +00001//===--- CompilationDatabase.cpp - ----------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Daniel Jasper7fd90b02012-08-24 05:50:27 +000010// This file contains implementations of the CompilationDatabase base class
11// and the FixedCompilationDatabase.
Manuel Klimekcb971c62012-04-04 12:07:46 +000012//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Tooling/CompilationDatabase.h"
Daniel Jasper7fd90b02012-08-24 05:50:27 +000016#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
Manuel Klimek8fa2fb82012-07-10 13:10:51 +000017#include "clang/Tooling/Tooling.h"
Manuel Klimekcb971c62012-04-04 12:07:46 +000018#include "llvm/ADT/SmallString.h"
Manuel Klimekcb971c62012-04-04 12:07:46 +000019#include "llvm/Support/Path.h"
20#include "llvm/Support/system_error.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000021#include <sstream>
Manuel Klimekcb971c62012-04-04 12:07:46 +000022
23namespace clang {
24namespace tooling {
25
Manuel Klimekcb971c62012-04-04 12:07:46 +000026CompilationDatabase::~CompilationDatabase() {}
27
28CompilationDatabase *
29CompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
30 std::string &ErrorMessage) {
Daniel Jasper7fd90b02012-08-24 05:50:27 +000031 std::stringstream ErrorStream;
32 for (CompilationDatabasePluginRegistry::iterator
33 It = CompilationDatabasePluginRegistry::begin(),
34 Ie = CompilationDatabasePluginRegistry::end();
35 It != Ie; ++It) {
36 std::string DatabaseErrorMessage;
37 OwningPtr<CompilationDatabasePlugin> Plugin(It->instantiate());
38 if (CompilationDatabase *DB =
39 Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage))
40 return DB;
41 else
42 ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n";
Manuel Klimekcb971c62012-04-04 12:07:46 +000043 }
Daniel Jasper7fd90b02012-08-24 05:50:27 +000044 ErrorMessage = ErrorStream.str();
45 return NULL;
Manuel Klimekcb971c62012-04-04 12:07:46 +000046}
47
Arnaud A. de Grandmaison4187df52012-07-10 16:56:35 +000048static CompilationDatabase *
Daniel Jasper7fd90b02012-08-24 05:50:27 +000049findCompilationDatabaseFromDirectory(StringRef Directory,
50 std::string &ErrorMessage) {
51 std::stringstream ErrorStream;
Daniel Jasper3d210782012-10-15 13:12:24 +000052 bool HasErrorMessage = false;
Arnaud A. de Grandmaison4187df52012-07-10 16:56:35 +000053 while (!Directory.empty()) {
54 std::string LoadErrorMessage;
55
56 if (CompilationDatabase *DB =
57 CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage))
58 return DB;
Daniel Jasper3d210782012-10-15 13:12:24 +000059
60 if (!HasErrorMessage) {
61 ErrorStream << "No compilation database found in " << Directory.str()
62 << " or any parent directory\n" << LoadErrorMessage;
63 HasErrorMessage = true;
64 }
Arnaud A. de Grandmaison4187df52012-07-10 16:56:35 +000065
66 Directory = llvm::sys::path::parent_path(Directory);
67 }
Daniel Jasper7fd90b02012-08-24 05:50:27 +000068 ErrorMessage = ErrorStream.str();
Arnaud A. de Grandmaison4187df52012-07-10 16:56:35 +000069 return NULL;
70}
71
Manuel Klimek8fa2fb82012-07-10 13:10:51 +000072CompilationDatabase *
73CompilationDatabase::autoDetectFromSource(StringRef SourceFile,
74 std::string &ErrorMessage) {
75 llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile));
76 StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
Arnaud A. de Grandmaison4187df52012-07-10 16:56:35 +000077
Daniel Jasper7fd90b02012-08-24 05:50:27 +000078 CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory,
79 ErrorMessage);
Arnaud A. de Grandmaison4187df52012-07-10 16:56:35 +000080
81 if (!DB)
82 ErrorMessage = ("Could not auto-detect compilation database for file \"" +
Daniel Jasper7fd90b02012-08-24 05:50:27 +000083 SourceFile + "\"\n" + ErrorMessage).str();
Arnaud A. de Grandmaison4187df52012-07-10 16:56:35 +000084 return DB;
85}
86
87CompilationDatabase *
88CompilationDatabase::autoDetectFromDirectory(StringRef SourceDir,
89 std::string &ErrorMessage) {
90 llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir));
91
Daniel Jasper7fd90b02012-08-24 05:50:27 +000092 CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath,
93 ErrorMessage);
Arnaud A. de Grandmaison4187df52012-07-10 16:56:35 +000094
95 if (!DB)
96 ErrorMessage = ("Could not auto-detect compilation database from directory \"" +
Daniel Jasper7fd90b02012-08-24 05:50:27 +000097 SourceDir + "\"\n" + ErrorMessage).str();
Arnaud A. de Grandmaison4187df52012-07-10 16:56:35 +000098 return DB;
Manuel Klimek8fa2fb82012-07-10 13:10:51 +000099}
100
Daniel Jasper7fd90b02012-08-24 05:50:27 +0000101CompilationDatabasePlugin::~CompilationDatabasePlugin() {}
102
Manuel Klimek30318e62012-04-18 07:41:50 +0000103FixedCompilationDatabase *
104FixedCompilationDatabase::loadFromCommandLine(int &Argc,
105 const char **Argv,
106 Twine Directory) {
107 const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
108 if (DoubleDash == Argv + Argc)
109 return NULL;
110 std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc);
111 Argc = DoubleDash - Argv;
112 return new FixedCompilationDatabase(Directory, CommandLine);
113}
114
115FixedCompilationDatabase::
116FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
117 std::vector<std::string> ToolCommandLine(1, "clang-tool");
118 ToolCommandLine.insert(ToolCommandLine.end(),
119 CommandLine.begin(), CommandLine.end());
120 CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine));
121}
122
123std::vector<CompileCommand>
124FixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
125 std::vector<CompileCommand> Result(CompileCommands);
126 Result[0].CommandLine.push_back(FilePath);
127 return Result;
128}
129
Manuel Klimeka3c70962012-07-13 12:31:45 +0000130std::vector<std::string>
131FixedCompilationDatabase::getAllFiles() const {
132 return std::vector<std::string>();
133}
134
Argyrios Kyrtzidis7e96bfb2012-12-04 07:26:44 +0000135std::vector<CompileCommand>
136FixedCompilationDatabase::getAllCompileCommands() const {
137 return std::vector<CompileCommand>();
138}
139
Daniel Jasper7fd90b02012-08-24 05:50:27 +0000140// This anchor is used to force the linker to link in the generated object file
141// and thus register the JSONCompilationDatabasePlugin.
142extern volatile int JSONAnchorSource;
143static int JSONAnchorDest = JSONAnchorSource;
Manuel Klimekcb971c62012-04-04 12:07:46 +0000144
145} // end namespace tooling
146} // end namespace clang