I'm looking for a way to get a modern, fresh baremetal x86_64 C++ toolchain with libc and libcxx (both reduced to baremetal/no-standard functionality). The LLVM project offers a CMake-based libcxx that seems to be buildable with exactly the properties I need. However, I have the following questions:
- Is libcxx from llvm-project overall meant for baremetal usage outside of LLVM? Is this somewhere documented? I can't find anything except this ressource.
- Is libc from llvm-project meant to be the base for a baremetal libcxx? Or do I need to provide my own libc header files? (In any case: I'm aware of that symbols such as
printf()need to be provided by myself)
Actually, from the libc I only need some header files. I do not need exit(), write(), and printf(). I want to provide my own implementations if needed.
Here's the relevant excerpt from my CMakelists.txt so far:
set(LLVM_ENABLE_RUNTIMES "libcxxabi;libcxx")
set(LLVM_INCLUDE_TESTS "OFF")
set(LLVM_INCLUDE_DOCS "OFF")
set(LIBCXXABI_ENABLE_SHARED "OFF")
set(LIBCXXABI_ENABLE_STATIC "ON")
set(LIBCXXABI_BAREMETAL "ON")
set(LIBCXXABI_ENABLE_THREADS "OFF")
set(LIBCXX_ENABLE_SHARED "OFF")
set(LIBCXX_ENABLE_STATIC "ON")
set(LIBCXX_ENABLE_UNICODE "ON")
set(LIBCXX_ENABLE_WIDE_CHARACTERS "ON")
set(LIBCXX_INCLUDE_TESTS "OFF")
set(LIBCXX_INCLUDE_BENCHMARKS "OFF")
set(LIBCXX_ENABLE_EXCEPTIONS "OFF")
set(LIBCXX_ENABLE_FILESYSTEM "OFF")
set(LIBCXX_ENABLE_LOCALIZATION "OFF")
set(LIBCXX_ENABLE_MONOTONIC_CLOCK "OFF")
set(LIBCXX_ENABLE_RANDOM_DEVICE "OFF")
set(LIBCXX_ENABLE_RTTI "OFF")
set(LIBCXX_ENABLE_SHARED "OFF")
set(LIBCXX_ENABLE_THREADS "OFF")
set(LIBCXX_ENABLE_TIME_ZONE_DATABASE "OFF")
set(LIBCXX_INCLUDE_BENCHMARKS "OFF")
set(LIBCXX_INSTALL_HEADERS "ON")
set(LIBCXX_INSTALL_LIBRARY "OFF")
set(LIBCXX_INSTALL_SHARED_LIBRARY "OFF")
set(LIBCXX_INSTALL_STATIC_LIBRARY "OFF")
add_subdirectory($ENV{LLVM_PROJECT_SRC}/runtimes ./llvm-project)
add_executable(freestanding-linux-hello-world main.cpp)
target_compile_options(
freestanding-linux-hello-world
PRIVATE
-nodefaultlibs
-nostdinc
-nostdlib
-ffreestanding
"$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>"
"$<$<COMPILE_LANGUAGE:CXX>:-fno-threadsafe-statics>"
"$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>"
)
target_link_options(
freestanding-linux-hello-world
PRIVATE
-nodefaultlibs
-nostdinc
-nostdlib
-ffreestanding
"$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>"
"$<$<COMPILE_LANGUAGE:CXX>:-fno-threadsafe-statics>"
"$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>"
)
target_link_libraries(freestanding-linux-hello-world
PRIVATE
cxx_static)
Using <llvm-project>/runtimes seems to be the proper entry point, according to this guide.
However: At that point the build fails as features.h is missing. I tried to add missing header-files one-by-one, but this never ended and there were never ending compilation errors.
Instead of providing my own libc, I tried to build the libc from llvm-project with additionally:
# added "libc"
set(LLVM_ENABLE_RUNTIMES "libc;libcxxabi;libcxx")
set(LIBC_TARGET_OS "baremetal")
set(LIBC_TARGET_OS_IS_BAREMETAL "ON")
but this also didn't succeed. The first error that came there was
error: ‘char* __llvm_libc::strcpy(char*, const char*)’ aliased to external symbol ‘strcpy’
and I stopped for now to get some guidance first.
I think the llvm-project is missing a high-level description on what you have to do to get a baremetal CXX toolchain.
Update 1 I tried using musl as libc. With lots of digital ductape, I built musl and only use the generated header files. I'm one step further.
Now, I'm facing further build errors. Notably is that the CMake build for libcxx always seems to the x86_64-unknown-linux-gnu target triple. I tried
set(LLVM_BUILTIN_TARGETS "x86_64-unknown-none")
set(LLVM_RUNTIME_TARGETS "x86_64-unknown-none")
set(LLVM_HOST_TRIPLE "x86_64-unknown-none")
set(LLVM_TARGET_ARCH "x86_64-unknown-none")
set(LLVM_DEFAULT_TARGET_TRIPLE "x86_64-unknown-none")
but nothing changed.