Cross compiling compiler-rt to mips64el - wrong file name?

Apologies if this is the wrong category.
I am trying to cross compile compiler-rt to mips64el-unknown-linux-musl (to an empty sysroot, ie no existing cross libraries).
I have specified DCMAKE_{C,CXX,ASM}_COMPILER_TARGET as such, and my CMake source directory is /runtimes in the monorepo.
For some reason however, CMake names the libclang_rt library “libclang_rt.builtins-mips.a”, whereas clang looks for (and my expectation is) “libclang_rt.builtins-mips64el.a”. Running readelf -h on the generated file shows it is compiled correctly (i.e. elf 64 and little endian)

Can anyone give any guidance on what I/CMake could be doing wrong?

I dug into the code that produces these names for some Arm 32 bit work.

The function that builds that name is set_output_name in compiler-rt/cmake/Modules/AddCompilerRT.cmake. You’ll need to trace back where the arch parameter was generated.

I suggest using a few well placed message(STATUS ...) calls in the places that call that macro.

There are a few places where architecture names are normalised for various reasons, and it’s likely the process isn’t being reversed.

Also if you can’t find it that way, we’d need to see the exact cmake commands you’re using. Since the triple names can have a big effect on this stuff.

Thank you for your response, I will play around with placing messages in CMake. Out of curiousity, tried manually copying, but I got linker errors relating to missing 128bit symbols, likely because of this, where only 64bit mips targets have GENERIC_TF_SOURCES.

For reference, I am calling CMake like this:

cmake -GNinja -Ssrcs/llvm-project-llvmorg-16.0.1/runtimes -Bbuild/mips64el-unknown-linux-musl-compiler-rt-16.0.1 -DCMAKE_TOOLCHAIN_FILE=/tmp/tmp3vf0s7u0.cmake -DCMAKE_INSTALL_PREFIX=/usr -DCOMPILER_RT_INSTALL_PATH=/usr/lib/clang -DLLVM_BINARY_DIR=/usr/mips64el-unknown-linux-musl/usr/lib/llvm -DLLVM_ENABLE_RUNTIMES=compiler-rt -DCOMPILER_RT_BUILD_BUILTINS=ON -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_LIBCXX=ON -DCMAKE_C_COMPILER_WORKS=ON -DCMAKE_CXX_COMPILER_WORKS=ON -DCOMPILER_RT_BUILD_LIBFUZZER=OFF -DCOMPILER_RT_BUILD_MEMPROF=OFF -DCOMPILER_RT_BUILD_PROFILE=OFF -DCOMPILER_RT_BUILD_SANITIZERS=OFF -DCOMPILER_RT_BUILD_XRAY=OFF -DCOMPILER_RT_BUILD_ORC=OFF
Toolchain file
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR mips64el)

set(m_sysroot /usr/mips64el-unknown-linux-musl)
set(m_triple mips64el-unknown-linux-musl)

set(CMAKE_SYSROOT ${m_sysroot})

set(CMAKE_C_COMPILER /usr/lib/llvm/16/bin/clang)
set(CMAKE_CXX_COMPILER /usr/lib/llvm/16/bin/clang++)
set(CMAKE_AR /usr/lib/llvm/16/bin/llvm-ar)
set(CMAKE_NM /usr/lib/llvm/16/bin/llvm-nm)
set(CMAKE_RANLIB /usr/lib/llvm/16/bin/llvm-ranlib)

set(CMAKE_C_COMPILER_TARGET ${m_triple})
set(CMAKE_CXX_COMPILER_TARGET ${m_triple})
set(CMAKE_ASM_COMPILER_TARGET ${m_triple})


set(common_ldflags "--gcc-install-dir= -fuse-ld=lld -resource-dir /usr/mips64el-unknown-linux-musl/usr/lib/clang")



set(CMAKE_EXE_LINKER_FLAGS_INIT ${common_ldflags})
set(CMAKE_MODULE_LINKER_FLAGS_INIT ${common_ldflags})
set(CMAKE_SHARED_LINKER_FLAGS_INIT ${common_ldflags})
#CMAKE_STATIC_LINKER_FLAGS is passed to ar, not clang

(At this stage the sysroot only has linux and musl headers)

Okay I’ve figured it out.
to figure out what the compiler can support in cmake/base-config-ix.cmake it calls test_target_arch, which verifies a simple file can be successfully built.
The problem arises since my sysroot does not yet have any libraries (compiler-rt has to be built before anything).
I think ideally a warning should be issued if CMAKE_C_COMPILER_WORKS that the target detection might not work. I will experiment more to see what I can set in my case specifically

EDIT: It can’t be this, I have COMPILER_RT_DEFAULT_TARGET_ONLY set

EDIT 2: when COMPILER_RT_DEFAULT_TARGET_ONLY is set COMPILER_RT_DEFAULT_TARGET_ARCH, compiler-rt/CMakeLists.txt uses CHECK_SYMBOL_EXIST, which for some reason returns nothing for __mips64 and __MIPSEL__, even when they are shown with clang -target mips64el-unknown-linux-musl -dM -E -x c

EDIT 3: okay, look like I’ll have to get CHECK_SYMBOL_EXISTS (try_compile) in some way, either by probiding my own implementation, or using something along the lines of set(CACHE FORCE). Is there a reason for LLVM checking if the architecture begins with mips, and then setting 64 and/or el again (source)?

EDIT 4: I just ended up setting COMPILER_RT_MIPS_64 and COMPILER_RT_MIPS_EL manually on the command line and it worked.

One tip is to completely clean your build dir between all these experiments. I find that try compiles and whatnot often get cached.

Quite possible that it’s to do with the way mutlilibs are built. There is a mode where it can detect multiple configurations at once, though this is a legacy mode not part of (or at least not advisable) with the runtimes build.

1 Like

Because of MIPSr6: [CMake] Fix MIPSr6 build for compiler-rt · llvm/llvm-project@9221aa6 · GitHub

This does look like it interacts poorly with -DCMAKE_C_COMPILER_WORKS=ON etc though given it’ll try to link?

1 Like

I think I found a not hacky way to do this: set CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY. This way missing libraries will not be a problem.

It looks like this has been previously discussed.