CompilationDatabase.cpp revision 252723
1219820Sjeff//===--- CompilationDatabase.cpp - ----------------------------------------===// 2219820Sjeff// 3219820Sjeff// The LLVM Compiler Infrastructure 4219820Sjeff// 5219820Sjeff// This file is distributed under the University of Illinois Open Source 6219820Sjeff// License. See LICENSE.TXT for details. 7219820Sjeff// 8219820Sjeff//===----------------------------------------------------------------------===// 9219820Sjeff// 10219820Sjeff// This file contains implementations of the CompilationDatabase base class 11219820Sjeff// and the FixedCompilationDatabase. 12219820Sjeff// 13219820Sjeff//===----------------------------------------------------------------------===// 14219820Sjeff 15219820Sjeff#include "clang/Tooling/CompilationDatabase.h" 16219820Sjeff#include "clang/Tooling/CompilationDatabasePluginRegistry.h" 17219820Sjeff#include "clang/Tooling/Tooling.h" 18219820Sjeff#include "llvm/ADT/SmallString.h" 19219820Sjeff#include "llvm/Support/Path.h" 20219820Sjeff#include "llvm/Support/system_error.h" 21219820Sjeff#include <sstream> 22219820Sjeff 23219820Sjeffnamespace clang { 24219820Sjeffnamespace tooling { 25219820Sjeff 26219820SjeffCompilationDatabase::~CompilationDatabase() {} 27219820Sjeff 28219820SjeffCompilationDatabase * 29219820SjeffCompilationDatabase::loadFromDirectory(StringRef BuildDirectory, 30219820Sjeff std::string &ErrorMessage) { 31219820Sjeff std::stringstream ErrorStream; 32219820Sjeff for (CompilationDatabasePluginRegistry::iterator 33219820Sjeff It = CompilationDatabasePluginRegistry::begin(), 34219820Sjeff Ie = CompilationDatabasePluginRegistry::end(); 35219820Sjeff It != Ie; ++It) { 36219820Sjeff std::string DatabaseErrorMessage; 37219820Sjeff OwningPtr<CompilationDatabasePlugin> Plugin(It->instantiate()); 38219820Sjeff if (CompilationDatabase *DB = 39219820Sjeff Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage)) 40219820Sjeff return DB; 41219820Sjeff else 42219820Sjeff ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n"; 43219820Sjeff } 44219820Sjeff ErrorMessage = ErrorStream.str(); 45219820Sjeff return NULL; 46219820Sjeff} 47219820Sjeff 48219820Sjeffstatic CompilationDatabase * 49219820SjefffindCompilationDatabaseFromDirectory(StringRef Directory, 50219820Sjeff std::string &ErrorMessage) { 51219820Sjeff std::stringstream ErrorStream; 52219820Sjeff bool HasErrorMessage = false; 53219820Sjeff while (!Directory.empty()) { 54219820Sjeff std::string LoadErrorMessage; 55219820Sjeff 56219820Sjeff if (CompilationDatabase *DB = 57219820Sjeff CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage)) 58219820Sjeff return DB; 59219820Sjeff 60219820Sjeff if (!HasErrorMessage) { 61219820Sjeff ErrorStream << "No compilation database found in " << Directory.str() 62219820Sjeff << " or any parent directory\n" << LoadErrorMessage; 63219820Sjeff HasErrorMessage = true; 64219820Sjeff } 65219820Sjeff 66219820Sjeff Directory = llvm::sys::path::parent_path(Directory); 67219820Sjeff } 68219820Sjeff ErrorMessage = ErrorStream.str(); 69219820Sjeff return NULL; 70219820Sjeff} 71219820Sjeff 72219820SjeffCompilationDatabase * 73219820SjeffCompilationDatabase::autoDetectFromSource(StringRef SourceFile, 74219820Sjeff std::string &ErrorMessage) { 75255932Salfred SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile)); 76255932Salfred StringRef Directory = llvm::sys::path::parent_path(AbsolutePath); 77255932Salfred 78219820Sjeff CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory, 79242933Sdim ErrorMessage); 80242933Sdim 81242933Sdim if (!DB) 82242933Sdim ErrorMessage = ("Could not auto-detect compilation database for file \"" + 83242933Sdim SourceFile + "\"\n" + ErrorMessage).str(); 84242933Sdim return DB; 85219820Sjeff} 86219820Sjeff 87219820SjeffCompilationDatabase * 88219820SjeffCompilationDatabase::autoDetectFromDirectory(StringRef SourceDir, 89219820Sjeff std::string &ErrorMessage) { 90240680Sgavin SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir)); 91240680Sgavin 92219820Sjeff CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath, 93219820Sjeff ErrorMessage); 94219820Sjeff 95219820Sjeff if (!DB) 96219820Sjeff ErrorMessage = ("Could not auto-detect compilation database from directory \"" + 97219820Sjeff SourceDir + "\"\n" + ErrorMessage).str(); 98219820Sjeff return DB; 99255932Salfred} 100219820Sjeff 101219820SjeffCompilationDatabasePlugin::~CompilationDatabasePlugin() {} 102219820Sjeff 103219820SjeffFixedCompilationDatabase * 104219820SjeffFixedCompilationDatabase::loadFromCommandLine(int &Argc, 105219820Sjeff const char **Argv, 106255932Salfred Twine Directory) { 107255932Salfred const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--")); 108219820Sjeff if (DoubleDash == Argv + Argc) 109219820Sjeff return NULL; 110255932Salfred std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc); 111219820Sjeff Argc = DoubleDash - Argv; 112219820Sjeff return new FixedCompilationDatabase(Directory, CommandLine); 113219820Sjeff} 114219820Sjeff 115219820SjeffFixedCompilationDatabase:: 116219820SjeffFixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) { 117219820Sjeff std::vector<std::string> ToolCommandLine(1, "clang-tool"); 118219820Sjeff ToolCommandLine.insert(ToolCommandLine.end(), 119219820Sjeff CommandLine.begin(), CommandLine.end()); 120219820Sjeff CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine)); 121219820Sjeff} 122219820Sjeff 123219820Sjeffstd::vector<CompileCommand> 124219820SjeffFixedCompilationDatabase::getCompileCommands(StringRef FilePath) const { 125219820Sjeff std::vector<CompileCommand> Result(CompileCommands); 126219820Sjeff Result[0].CommandLine.push_back(FilePath); 127255932Salfred return Result; 128255932Salfred} 129255932Salfred 130219820Sjeffstd::vector<std::string> 131219820SjeffFixedCompilationDatabase::getAllFiles() const { 132219820Sjeff return std::vector<std::string>(); 133219820Sjeff} 134219820Sjeff 135219820Sjeffstd::vector<CompileCommand> 136219820SjeffFixedCompilationDatabase::getAllCompileCommands() const { 137219820Sjeff return std::vector<CompileCommand>(); 138219820Sjeff} 139219820Sjeff 140219820Sjeff// This anchor is used to force the linker to link in the generated object file 141219820Sjeff// and thus register the JSONCompilationDatabasePlugin. 142219820Sjeffextern volatile int JSONAnchorSource; 143219820Sjeffstatic int JSONAnchorDest = JSONAnchorSource; 144219820Sjeff 145219820Sjeff} // end namespace tooling 146219820Sjeff} // end namespace clang 147219820Sjeff