Understanding CMake build targets

My end goal is to distribute a BOLT-optimzed, PGOed Clang with full LTO, plus static-only libc++. I don’t want any other component, runtime library, or tool, such as compiler-rt, libc++abi, libunwind, llvm-config, and so on, unless any of them are strict dependencies of either Clang or libc++ (I don’t know where to find this information).

I’m basing myself off this Dockerfile from the monorepo:

Except I’m setting -DLLVM_ENABLE_PROJECTS="bolt;clang" (I want to use mold instead of LLD), -DLLVM_DISTRIBUTION_COMPONENTS="" (I just want Clang), and -DLLVM_RUNTIME_DISTRIBUTION_COMPONENTS="libcxx" (and -DPGO_INSTRUMENT_LTO=Full, of course).

cmake --build build -t stage2-clang-bolt stage2-install-distribution runs fine (the only issue is that it always installs clang-format and clang-tidy for some reason, even though I never asked for them), but cmake --build build -t install-distribution errors out with:

gmake[4]: *** No rule to make target 'install-libcxx'.  Stop.
CMake Error at /home/user/tmp/bs/cache/llvm-project/llvm/cmake/modules/FileLock.cmake:9 (execute_process):
  execute_process failed command indexes:

    1: "Child return code: 2"



gmake[3]: *** [runtimes/CMakeFiles/install-libcxx.dir/build.make:70: runtimes/CMakeFiles/install-libcxx] Error 1
gmake[2]: *** [CMakeFiles/Makefile2:159558: runtimes/CMakeFiles/install-libcxx.dir/all] Error 2
gmake[2]: *** Waiting for unfinished jobs....
gmake[4]: *** No rule to make target 'install-libcxxabi'.  Stop.
CMake Error at /home/user/tmp/bs/cache/llvm-project/llvm/cmake/modules/FileLock.cmake:9 (execute_process):
  execute_process failed command indexes:

    1: "Child return code: 2"



gmake[3]: *** [runtimes/CMakeFiles/install-libcxxabi.dir/build.make:70: runtimes/CMakeFiles/install-libcxxabi] Error 1
gmake[2]: *** [CMakeFiles/Makefile2:159494: runtimes/CMakeFiles/install-libcxxabi.dir/all] Error 2
gmake[1]: *** [CMakeFiles/Makefile2:16263: CMakeFiles/install-distribution.dir/rule] Error 2
gmake: *** [Makefile:332: install-distribution] Error 2

I don’t really know enough about LLVM’s CMake build targets to actually know what I’m doing; I simply tried making the same targets as the Dockerfile.

I want to do what Building a Distribution of LLVM describes: Set both LLVM_DISTRIBUTION_COMPONENTS and LLVM_RUNTIME_DISTRIBUTION_COMPONENTS, and make the correct *-distribution and *-install-distribution targets, since it sounds like this way CMake’ll build only what I strictly request and no extra runtimes or tools, reducing my build times. Quoting the documentation (emphasis mine):

When building with LLVM_DISTRIBUTION_COMPONENTS the build system also generates a distribution target which builds all the components specified in the list. This is a convenience build target to allow building just the distributed pieces without needing to build all configured targets.

I guess my questions are:

  1. Where are LLVM’s CMake build targets documented? How do I know what targets such as stage2-clang-bolt, stage2-install-distribution, and so on, actually do and the differences between them?
  2. Which “*-distribution” and “*-install-distribution” targets should I use to build and install my distribution, respectively? Considering I want BOLT + LTO + PGO via the CMake cache.
  3. Which components depend on which? (E.g., does libc++ depend on libc++abi?)

After fiddling with the configuration options for a few days, I ended up leaving LLVM_ENABLE_PROJECTS and LLVM_ENABLE_RUNTIMES alone at whichever values the caches set them to and setting -DLLVM_DISTRIBUTION_COMPONENTS='clang;cxx'. I then ran cmake --build build -j 8 -t stage2-clang-bolt install-distribution. The first target builds the BOLT-optimized, PGOed Clang and the second one (I think) builds libc++ and installs everything to CMAKE_INSTALL_PREFIX according to what I specified in LLVM_DISTRIBUTION_COMPONENTS.

What I don’t know is if libc++ is built using the final Clang built in stage2-clang-bolt, which would be ideal for distribution, but I don’t know how I would even check this.

I think that my mistake was trying to use LLVM_RUNTIME_DISTRIBUTION_COMPONENTS when I’m rooting my CMake invocation at the <monorepo>/llvm directory; I think it only makes sense to use this variable when rooting the invocation at <monorepo>/runtimes, but I could be mistaken! So I’ll leave this question open.

Why would it matter which which clang libc++ gets built with? The artifacts will be the same, assuming there are not determinism/UB issues within clang. The compilation might be slightly slower, but libc++ compiles fast enough that’s probably not a concern if you’re doing a three stage clang build.

From libc++’s vendor documentation:

It is possible to build Clang and then build the runtimes using that just-built compiler in a single CMake invocation. This is usually the correct way to build the runtimes when putting together a toolchain, […]

I don’t know why this would be the “correct way” to build the runtimes, but that’s what libc++’s documentation told me so I just believed it.

That’s what you’re already doing. You’re using the stage1 compiler instead of the stage2 optimized compiler.