Consult how to cross compile clang for arm on x86 linux ubuntu box

May I ask how to build clang for arm on x86 linux ubuntu box? And how to use sysroot to cross compile clang libc++ for arm on x86 linux? Appreciate any guidance.

Thanks,
Andy

I can get llvm source code and the information “cross-compiling from x86_64 to ARM” from https://llvm.org/docs/HowToCrossCompileLLVM.html. However, I still fail to build clang for ARM. It is strange, I have already set a target with " -target arm-linux-gnueabihf " . I am describing the failure progress as below. Expecting any idea.

The build steps:

cd llvm-project

mkdir build
cd build
cmake -DLLVM_ENABLE_PROJECTS=clang -G “Unix Makefiles”
make
// After I built host llvm-tblgen and clang-tblgen, I begin to return to build arm target clang as below steps:
cd …
mkdir build_arm_onx86
cd build_arm_onx86
mkdir stall_prefix
cmake -G “Unix Makefiles” -DCMAKE_CROSSCOMPILING=True -DCMAKE_INSTALL_PREFIX=./stall_prefix -DLLVM_TABLEGEN=/home_2t/workspace/llvm_clang/llvm-project/build/bin/llvm-tblgen -DCLANG_TABLEGEN=/home_2t/workspace/llvm_clang/llvm-project/build/bin/clang-tblgen -DLLVM_TARGET_ARCH=ARM -DLLVM_TARGETS_TO_BUILD=ARM -target arm-linux-gnueabihf -DLLVM_ENABLE_PROJECTS=“clang;libcxx;libcxxabi” …/llvm 2>&1 | tee out_cofiguration.txt
make 2>&1 | tee out_make.txt

The result:

build_arm_onx86$ file bin/clang-12
bin/clang-12: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=3b669c10e300bb5d9bb96cfb77f927ce95728ca6, not stripped

build_arm_onx86$ bin/clang --version
clang version 12.0.0 (https://github.com/llvm/llvm-project.git 3948341fa5fab2695b0df95edc248fe959e40664)
Target: x86_64-unknown-linux-gnu

Thread model: posix
InstalledDir: /home_2t/workspace/llvm_clang/llvm-project/build_arm_onx86/bin

Seems it failed from the configuration as attached cmake output log.

– LLVM host triple: x86_64-unknown-linux-gnu

– LLVM default target triple: x86_64-unknown-linux-gnu

Thanks in advance

Best Regards,
Andy

Hi Andy,

Assuming you are compiling with clang, I think -target and --sysroot
need to be added to CMAKE_CXX_FLAGS instead of being cmake arguments
themselves.

"However, if you’re using Clang, the driver might not be up-to-date
with your specific Linux distribution, version or GCC layout, so
you’ll need to fudge.

In addition to the ones above, you’ll also need:"

Means you'll need extra CMAKE_CXX_FLAGS. (I also made the same mistake
on first reading) So try:
-DCMAKE_CXX_FLAGS="-target arm-linux-gnueabihf
--sysroot=/usr/arm-linux-gnueabihf"

Also I think (not tried your exact config) you need to tell cmake you
want to use clang by doing:
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++

If you're using GCC, skip the target and sysroot CFLAGS. Also I found
that I had to explicitly give cmake the gcc name (similar to above):
-DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc
-DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++-5
I have a feeling CMake should find this on its own but I don't know
enough to say.

If the default triple is still x86 by that point you can set that
with: -DLLVM_DEFAULT_TARGET_TRIPLE=arm-linux-gnueabihf
(probably won't be an issue)

Thanks,
David Spickett.

Hi

You’ll want an arm64 Linux sysroot and an arm64 libcxx. I have a docker setup on docker hub for building a cross build toolchain for arm64 that you can look at: https://hub.docker.com/r/plotfi/llvm-pi

My quick steps here https://github.com/plotfi/llvm-pi/blob/master/Quick-Steps.md are for building the llvm-test-suite for arm64 but they can be repurposed for building clang for arm64 too.

Hope this helps

-Puyan

Also if you want to see how I setup my sysroot you can take a look at: https://github.com/plotfi/llvm-pi/blob/master/Dockerfile

-Puyan

Dear David,

I appreciate your experience. I also successfully built the clang for target ARM platform on x86 Linux by directly modifying “./llvm/CMakeLists.txt” as below in green color. It is ugly workaround. I prefer your approach and will try later.

Override the default target with an environment variable named by LLVM_TARGET_TRIPLE_ENV.

#set(LLVM_TARGET_TRIPLE_ENV CACHE STRING “The name of environment variable to override default target. Disabled by blank.”)
set(LLVM_TARGET_TRIPLE_ENV “armv7-linux-gnueabihf”)
set(LLVM_TARGET_TRIPLE_ENV “armv7-linux-gnueabihf” CACHE STRING “ydd override default target to armv7-linux-gnueabihf.”)
mark_as_advanced(LLVM_TARGET_TRIPLE_ENV)

By default, we target the host, but this can be overridden at CMake

invocation time.

set(LLVM_DEFAULT_TARGET_TRIPLE “${LLVM_HOST_TRIPLE}” CACHE STRING
“Default target for which LLVM will generate code.” )
set(TARGET_TRIPLE “${LLVM_DEFAULT_TARGET_TRIPLE}”)
message(STATUS “LLVM host triple: ${LLVM_HOST_TRIPLE}”)
message(STATUS “LLVM default target triple: ${LLVM_DEFAULT_TARGET_TRIPLE}”)
set(LLVM_TARGET_TRIPLE_ENV “armv7-linux-gnueabihf”)

message(STATUS “ydd LLVM_TARGET_TRIPLE_ENV: ${LLVM_TARGET_TRIPLE_ENV}”)
message(STATUS “ydd LLVM_TARGETS_TO_BUILD: ${LLVM_TARGETS_TO_BUILD}”)

Many Thanks,
Andy

Appreciate Puyan for your important information. I am going to study it soon.

Many thanks,
Andy