Building the AST Visitor Example

There is an example in the docs for how to write a recursive AST visitor. It ends by suggesting the following cmake:

set(LLVM_LINK_COMPONENTS
  Support
  )

add_clang_executable(find-class-decls FindClassDecls.cpp)

target_link_libraries(find-class-decls
  PRIVATE
  clangAST
  clangBasic
  clangFrontend
  clangSerialization
  clangTooling
  )

But this isnt actually complete. find_package(Clang) doesnt provide add_clang_executable, and none of these things provide the include path that you need for any of this to compile.

What’s the intended, complete cmake necessary to get this example to build?

1 Like

Hmm, the CMake example seems to assume you’ll be building inside the LLVM tree, where lots of stuff is implicitly included. I don’t know if that’s a good assumption or not, but here’s a standalone CMake example (assuming your CMAKE_PREFIX_PATH or other search path variable is correctly set up to find the LLVM and Clang packages):

cmake_minimum_required(VERSION 3.13.4)
project(FindClassDecls)

find_package(Clang)
list(APPEND
  CMAKE_MODULE_PATH
  ${LLVM_CMAKE_DIR}
  ${CLANG_CMAKE_DIR}
  )
include(AddLLVM)
include(AddClang)

set(LLVM_LINK_COMPONENTS
  Support
  )

add_clang_executable(find-class-decls FindClassDecls.cpp)

target_include_directories(find-class-decls
  PRIVATE
  ${LLVM_INCLUDE_DIR}
  ${CLANG_INCLUDE_DIR}
  )
target_link_libraries(find-class-decls
  PRIVATE
  clangAST
  clangBasic
  clangFrontend
  clangSerialization
  clangTooling
  )

It’d be much nicer if the CMake modules automatically set up the CMake search path, if AddClang were self-contained and didn’t require a separate AddLLVM include (though that might be tricky to make work with the way the in-tree build is set up), and if the libraries carried the include path information. @beanz or @petrhosek, do you happen to know why it isn’t set up that way?

1 Like

If you’re building LLVM and Clang yourself, another alternative to consider would be to use LLVM_EXTERNAL_PROJECTS and LLVM_EXTERNAL_<PROJECT>_SOURCE_DIR to have your project be included as a part of the LLVM build graph, which will also get you the CMake functions you need automatically. See swift/SwiftSharedCMakeConfig.cmake at c95e11c011e5e6ee19f9c21332ff04df29dd49db · apple/swift · GitHub for how Swift does it.

Thanks @smeenai! That worked for me.

I agree it’d be nicer if there was less typing in cmake necessary to do this.

But more so, I think it’d be nicer if the clang documentation made it clear how to build tools externally - since I really would like for this to be external. The examples are either all explicitly internal (like this tutorial) or ambiguous (like the example I cited earlier).

That’s good feedback, and I can try to add some standalone CMake examples to the docs. Since you’ve been looking at the docs recently, do you know a good place to put that in? I’d ideally like some central place to say something like “the CMake examples in all the following docs assume an in-tree build, but if you’re building standalone add the following preamble to your CMakeLists.txt”, and then be able to reference that from other docs as needed.

I always refer to this. IDK, whether you can make it work with Clang as well.

1 Like