libclang-static-build: a standalone, static libclang distro that works.

art yerkes
2 min readApr 19, 2020

--

Hot take: https://twitter.com/deech/ has made https://github.com/deech/libclang-static-build ← a simple static build of libclang that allows you to bust your libtooling and other clang related code out of llvm build tree jail and api version hell.

One of my previous lives involved writing a lot of C++ and I became very opinionated on some practices in C++. For larger programs, I tended toward a java style that put an abstract base (ISomeObject) when appropriate in front of objects conferring nontrivial functionality (network protocol clients, db adapters, even coupling to the filesystem) and so wrote a tool that helped enforce these kinds of rules. I was pretty happy with the result but less so the workflow to build it; the official libtooling documentation basically tells you to build tooling programs in the llvm tree. When I’ve had the chance to recommend libtooling to someone to solve a problem (or to be like me and use my rules), I really can’t recommend it as a common workflow because of the lack of documentation for a normal dev workflow and the rate of change in the clang api… It’s a mess for anyone whose 9–5 isn’t packaging up clang for google or apple.

Enter https://github.com/deech/libclang-static-build .

It’s very self contained and you can incorporate it easily into cmake projects (and you’re probably building clang related stuff with cmake anyway).

While I’m not a cmake maven, using it went pretty simply

cmake_minimum_required(VERSION 3.13)
include(${CMAKE_ROOT}/Modules/ExternalProject.cmake)

set(LIBCLANG_INSTALL "libclang-copied")
ExternalProject_Add(libclang-static-build
DOWNLOAD_DIR "libclang-static-build"
INSTALL_DIR "${LIBCLANG_INSTALL}"
GIT_REPOSITORY "https://github.com/deech/libclang-static-build"
GIT_TAG "0cae8e85ef1ad951e1bb560e1eadcd64b2f0828e"
CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${LIBCLANG_INSTALL}"
)

project(noglob)
add_compile_options("-fno-rtti")

add_executable(noglob
DisallowGlobals.cpp
DisallowNewDelete.cpp
DisallowNonAbstract.cpp
DisallowCoupling.cpp
tool.cpp
)

ExternalProject_Get_Property(libclang-static-build binary_dir)

include_directories(
${binary_dir}/_deps/clang_sources-src/include
${binary_dir}/_deps/libclang_prebuilt-src/include
)

add_dependencies(noglob libclang-static-build)
target_link_libraries(noglob "-L${binary_dir}" "-lclang_static_bundled" -lpthread)

Just a bit of hooking into libclang-static-build and you can ignore that your distro somehow manages to ship both with a libclang that’s newer than what you built with last time (with breaking api changes) but not new enough to take advantage of features you’ve recently read about in the docs.

--

--