Dogfood part2: breaking the dependency

Many organisation have chosen to break the

  • libc++ <-> compiler-rt

dependency within the libunwind library as it does not seem to depend on the other libraries, however (as it is a stack unwinder) it seems makes a call into up into the ‘Standard C++ Library’. Instead I have chosen to break the dependency by building just a small part of compiler-rt which does not require any ‘Standard C++ Library’.

linker_flags = '-nodefaultlibs -rtlib=compiler-rt -lc -fuse-ld=lld'
subprocess.run (
    [
        'cmake',
        '-G',
        'Ninja',
        '-S',
        'runtimes',
        '-B',
        build,
        '--trace-expand',
        '--trace-redirect=' + build +'/cmake.log',
        '-DCMAKE_BUILD_TYPE=Release',
        '-DCMAKE_C_COMPILER=' + STAGING + '/bin/clang',
        '-DCMAKE_CXX_COMPILER=' + STAGING + '/bin/clang++',
        '-DCMAKE_EXE_LINKER_FLAGS_INIT=' + linker_flags,
        '-DCMAKE_INSTALL_PREFIX=' + STAGING,
        '-DCMAKE_MODULE_LINKER_FLAGS_INIT=' + linker_flags,
        '-DCMAKE_SHARED_LINKER_FLAGS_INIT=' + linker_flags,
        '-DCOMPILER_RT_BUILD_SANITIZERS=OFF',
        '-DCOMPILER_RT_BUILD_MEMPROF=OFF',
        '-DCOMPILER_RT_BUILD_XRAY=OFF',
        '-DCOMPILER_RT_BUILD_LIBFUZZER=OFF',
        '-DCOMPILER_RT_BUILD_ORC=OFF',
        '-DCOMPILER_RT_INCLUDE_TESTS=OFF',
        '-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON',
        '-DLLVM_ENABLE_RUNTIMES=compiler-rt',
        '-DLLVM_TARGETS_TO_BUILD=Native'
    ],
    check=True
)
start = time.perf_counter()
subprocess.run (
    [
        'ninja',
        '-C',
        build,
        'compiler-rt'
    ],
    check=True
)
subprocess.run (
    [
        'ninja',
        '-C',
        build,
        'install-compiler-rt'
    ],
    check=True
)

Where

  • linker_flags are needed to ensure that CMAKE can compile some basic code. You can see that this line is used to initialise each of cmake’s linker flags. The line itself is unusual in that it asks for no default libraries but also asks for the compiler-rt that we have not built yet. This is because in the <arch>-<vendor>-linux-gnu environment libgcc will be used if rtlib is not specified. I think it is a bug in the clang code that then pulls in libgcc in error, I would like to use one of:
 linker_flags = '-nodefaultlibs -lc -fuse-ld=lld'
 linker_flags = '-nodefaultlibs -no-rtlib -lc -fuse-ld=lld'
 linker_flags = '-nodefaultlibs -rtlib=none -lc -fuse-ld=lld'
  • This is a ‘runtime only’ build or ‘default build’ (depending on what you read)
  • The build variable is set to ‘build-functional-rt’
  • The STAGING constant is still set to ‘/staging’ and we are using the functional llvm-tools, clang and lld that we built and installed in part 1
  • COMPILER_RT_… I have turned off nearly all the functionality of compiler-rt that we are building
  • LLVM_ENABLE_PER_TARGET_RUNTIME_DIR allows libraries to be created for multiple environments. I am building for only my host environment,but I use it to clearly define where the libraries will be found.

This code, unfortunately does not work without patches. I do not understand enough about the rest of the code to submit these, and I don’t have the rights anyway.

In …/clang/lib/Driver/Gnu.cpp (around line:516) Even though we have specified -nodefaultlibs the code tries to add crtbegin and crtend. It confuses the cases of compiler-rt, libgcc for gnu and libgcc for android. Furthermore, I have specified compiler-rt which does no even need crtbegin or crtend.
So I changed the code to ignore crtbegin and crtend if compiler-rt was specified

In …/compiler-rt/cmake/base-config-ix.cmake (around line:35) The code cannot access the compiler version so fails to put the compiler-rt files in the correct place.The code in …/clang/lib/Driver/ToolChain.cpp (around line 511) tells clang to look for them in one of two places relative to clang. I swapped the PACKAGE_VERSION flag it was using for the more general CMAKE_C_COMPILER_VERSION flag to fix it

As I have no rights to push the code, who do I speak to to:

  1. Discuss whether these are bugs or features?
  2. Fix them?

Building the “builtins” library shouldn’t need to link anything. We have a few places that mess with CMAKE_TRY_COMPILE_TARGET_TYPE to tell CMake not to link anything, but maybe that’s not complete.

compiler-rt/lib/crt has implementations of crtbegin/crtend. Not sure how you’re concluding they aren’t necessary…

If you have some idea of what you think the CMake code should look like, probably the easiest way to start a discussion is to post a patch, even if you’re not confident it’s the right patch. See Contributing to LLVM — LLVM 16.0.0git documentation

Thanks efriedma-quic,
Actually, the linker flags are used by cmake to determine whether clang++ can compile a program, and here I am trying to tell cmake not to pull in any libraries and to do just enough to pass the ‘does it compile’ test.
As I said in the article, I would prefer ‘-rtlib=none’ too

I discovered by accident that libunwind, libc++abi and libc++ would build with libclang_rt.builtins.a and without clang_rt.crtbegin.o or clang_rt.crtend.o
So, I don’t know whether their functionality was built into libclang_rt.builtins.a.

I have posted the three patches in ‘Dogfood summary’ is this enough or do I need to do more?

CMAKE_TRY_COMPILE_TARGET_TYPE is supposed to prevent that.

You might be able to build those specific libraries, sure. (crtbegin/crtend specifically provide functionality related to global constructors/destructors.)

If you don’t go through the normal review process (Contributing to LLVM — LLVM 16.0.0git documentation), I would guess nobody else is going to pick up the patches…