diff options
author | Manuel Klimek <klimek@google.com> | 2011-04-27 16:39:14 +0000 |
---|---|---|
committer | Manuel Klimek <klimek@google.com> | 2011-04-27 16:39:14 +0000 |
commit | 9a05fa97df4d5e64f740848a7759ecae5e1ed162 (patch) | |
tree | 70f5f56fcbe1bd6d3ff66ee1af96fa793fc01923 /examples | |
parent | 4d8d803b06804defe25346871c7beb6096540c4a (diff) |
This is the next step in building the standalone tools infrastructure:
This patch simplifies writing of standalone Clang tools. As an
example, we add clang-check, a tool that runs a syntax only frontend
action over a .cc file. When you integrate this into your favorite
editor, you get much faster feedback on your compilation errors, thus
reducing your feedback cycle especially when writing new code.
The tool depends on integration of an outstanding patch to CMake to
work which allows you to always have a current compile command
database in your cmake output directory when you set
CMAKE_EXPORT_COMPILE_COMMANDS.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130306 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'examples')
-rw-r--r-- | examples/CMakeLists.txt | 2 | ||||
-rw-r--r-- | examples/Tooling/CMakeLists.txt | 6 | ||||
-rw-r--r-- | examples/Tooling/ClangCheck.cpp | 108 |
3 files changed, 115 insertions, 1 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 9a32ee4065..8e16ef1c6c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,3 +1,3 @@ add_subdirectory(clang-interpreter) add_subdirectory(PrintFunctionNames) - +add_subdirectory(Tooling) diff --git a/examples/Tooling/CMakeLists.txt b/examples/Tooling/CMakeLists.txt new file mode 100644 index 0000000000..257d3ea8ea --- /dev/null +++ b/examples/Tooling/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_USED_LIBS clangTooling clangBasic) + +add_clang_executable(clang-check + ClangCheck.cpp + ) + diff --git a/examples/Tooling/ClangCheck.cpp b/examples/Tooling/ClangCheck.cpp new file mode 100644 index 0000000000..9f0b1dde70 --- /dev/null +++ b/examples/Tooling/ClangCheck.cpp @@ -0,0 +1,108 @@ +//===- examples/Tooling/ClangCheck.cpp - Clang check tool -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a clang-check tool that runs the +// clang::SyntaxOnlyAction over a number of translation units. +// +// Usage: +// clang-check <cmake-output-dir> <file1> <file2> ... +// +// Where <cmake-output-dir> is a CMake build directory in which a file named +// compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in +// CMake to get this output). +// +// <file1> ... specify the paths of files in the CMake source tree. This path +// is looked up in the compile command database. If the path of a file is +// absolute, it needs to point into CMake's source tree. If the path is +// relative, the current working directory needs to be in the CMake source +// tree and the file must be in a subdirectory of the current working +// directory. "./" prefixes in the relative files will be automatically +// removed, but the rest of a relative path must be a suffix of a path in +// the compile command line database. +// +// For example, to use clang-check on all files in a subtree of the source +// tree, use: +// /path/to/cmake/sources $ find . -name '*.cpp' \ +// |xargs clang-check /path/to/cmake/build +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/FrontendActions.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" + +/// \brief Returns the absolute path of 'File', by prepending it with +/// 'BaseDirectory' if 'File' is not absolute. Otherwise returns 'File'. +/// If 'File' starts with "./", the returned path will not contain the "./". +/// Otherwise, the returned path will contain the literal path-concatenation of +/// 'BaseDirectory' and 'File'. +/// +/// \param File Either an absolute or relative path. +/// \param BaseDirectory An absolute path. +/// +/// FIXME: Put this somewhere where it is more generally available. +static std::string GetAbsolutePath( + llvm::StringRef File, llvm::StringRef BaseDirectory) { + assert(llvm::sys::path::is_absolute(BaseDirectory)); + if (llvm::sys::path::is_absolute(File)) { + return File; + } + llvm::StringRef RelativePath(File); + if (RelativePath.startswith("./")) { + RelativePath = RelativePath.substr(strlen("./")); + } + llvm::SmallString<1024> AbsolutePath(BaseDirectory); + llvm::sys::path::append(AbsolutePath, RelativePath); + return AbsolutePath.str(); +} + +int main(int argc, char **argv) { + if (argc < 3) { + llvm::outs() << "Usage: " << argv[0] << " <cmake-output-dir> " + << "<file1> <file2> ...\n"; + return 1; + } + // FIXME: We should pull how to find the database into the Tooling package. + llvm::OwningPtr<llvm::MemoryBuffer> JsonDatabase; + llvm::SmallString<1024> JsonDatabasePath(argv[1]); + llvm::sys::path::append(JsonDatabasePath, "compile_commands.json"); + llvm::error_code Result = + llvm::MemoryBuffer::getFile(JsonDatabasePath, JsonDatabase); + if (Result != 0) { + llvm::outs() << "Error while opening JSON database: " << Result.message() + << "\n"; + return 1; + } + llvm::StringRef BaseDirectory(::getenv("PWD")); + for (int I = 2; I < argc; ++I) { + llvm::SmallString<1024> File(GetAbsolutePath(argv[I], BaseDirectory)); + llvm::outs() << "Processing " << File << ".\n"; + std::string ErrorMessage; + clang::tooling::CompileCommand LookupResult = + clang::tooling::FindCompileArgsInJsonDatabase( + File.str(), JsonDatabase->getBuffer(), ErrorMessage); + if (!LookupResult.CommandLine.empty()) { + if (!clang::tooling::RunToolWithFlags( + new clang::SyntaxOnlyAction, + LookupResult.CommandLine.size(), + clang::tooling::CommandLineToArgv( + &LookupResult.CommandLine).data())) { + llvm::outs() << "Error while processing " << File << ".\n"; + } + } else { + llvm::outs() << "Skipping " << File << ". Command line not found.\n"; + } + } + return 0; +} |