Build Clang on x86_64 (ubuntu) with arm-linux-gnueabihf failed

Hello.

Similar question to what i asked few days ago but was not resolved.

I’ve followed guide (http://llvm.org/docs/HowToCrossCompileLLVM.html) step-by-step.
The only changes i’ve done is installed g++ package since i’ve received “no g++ found” on clear virtual machine (ubuntu 13.04_64).

First i’ve compiled for host (to use tblgens), then for ARM.
When cross-compiling for ARM (tried both ninja and autotools) i’m getting linker error:

Linking CXX executable …/…/bin/llvm-tblgen
…/…/lib/libLLVMSupport.a: could not read symbols: File format not recognized
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [bin/llvm-tblgen] Error 1
make[1]: *** [utils/TableGen/CMakeFiles/llvm-tblgen.dir/all] Error 2

Verbose output (make VERBOSE=1):

cd /home/asmirnov/llvm_arm_cmake_build/utils/TableGen && /usr/bin/cmake -E cmake_link_script CMakeFiles/llvm-tblgen.dir/link.txt --verbose=1
/usr/local/bin/clang++ -target armv7a-linux-gnueabihf -mcpu=cortex-a9 -I/usr/arm-linux-gnueabihf/include/c++/4.7.3/arm-linux-gnueabihf/ -I/usr/arm-linux-gnueabihf/include/ -mfloat-abi=hard -ccc-gcc-name arm-linux-gnueabihf-gcc -Wall -W -Wno-unused-parameter -Wwrite-strings -Wmissing-field-initializers -pedantic -Wno-long-long -Wcovered-switch-default -Wnon-virtual-dtor -fno-rtti -O3 -DNDEBUG CMakeFiles/llvm-tblgen.dir/AsmMatcherEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/AsmWriterEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/AsmWriterInst.cpp.o CMakeFiles/llvm-tblgen.dir/CallingConvEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/CodeEmitterGen.cpp.o CMakeFiles/llvm-tblgen.dir/CodeGenDAGPatterns.cpp.o CMakeFiles/llvm-tblgen.dir/CodeGenInstruction.cpp.o CMakeFiles/llvm-tblgen.dir/CodeGenMapTable.cpp.o CMakeFiles/llvm-tblgen.dir/CodeGenRegisters.cpp.o CMakeFiles/llvm-tblgen.dir/CodeGenSchedule.cpp.o CMakeFiles/llvm-tblgen.dir/CodeGenTarget.cpp.o CMakeFiles/llvm-tblgen.dir/DAGISelEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/DAGISelMatcherEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/DAGISelMatcherGen.cpp.o CMakeFiles/llvm-tblgen.dir/DAGISelMatcherOpt.cpp.o CMakeFiles/llvm-tblgen.dir/DAGISelMatcher.cpp.o CMakeFiles/llvm-tblgen.dir/DFAPacketizerEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/DisassemblerEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/FastISelEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/FixedLenDecoderEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/InstrInfoEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/IntrinsicEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/OptParserEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/PseudoLoweringEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/RegisterInfoEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/SetTheory.cpp.o CMakeFiles/llvm-tblgen.dir/SubtargetEmitter.cpp.o CMakeFiles/llvm-tblgen.dir/TGValueTypes.cpp.o CMakeFiles/llvm-tblgen.dir/TableGen.cpp.o CMakeFiles/llvm-tblgen.dir/X86DisassemblerTables.cpp.o CMakeFiles/llvm-tblgen.dir/X86ModRMFilters.cpp.o CMakeFiles/llvm-tblgen.dir/X86RecognizableInstr.cpp.o CMakeFiles/llvm-tblgen.dir/CTagsEmitter.cpp.o -o …/…/bin/llvm-tblgen -L/usr/lib/gcc/x86_64-linux-gnu/4.7 -L/lib64 …/…/lib/libLLVMTableGen.a …/…/lib/libLLVMSupport.a -lrt -ldl -lpthread -lpthread
…/…/lib/libLLVMSupport.a: could not read symbols: File format not recognized
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [bin/llvm-tblgen] Error 1
make[2]: Leaving directory /home/asmirnov/llvm_arm_cmake_build' make[1]: *** [utils/TableGen/CMakeFiles/llvm-tblgen.dir/all] Error 2 make[1]: Leaving directory /home/asmirnov/llvm_arm_cmake_build’
make: *** [all] Error 2

Can it be walked-around by invocation without -L/lib64 ?

Anton

As far as i understood, invocation line is saved in CMakeFiles/llvm-tblgen.dir/link.txt.
I’ve edited it to remove -L/lib64 and invoked the last command line manually but the problem remains.

What can i do in order to avoid adding -L/lib64 ?

Thanks,
Anton

I can confirm that after editing there is no -L/lib64 in invocation line,
but the problem remains. I think previously compiled files were compiled/linked with -L/lib64 and this
corrupts the build.

How can it be fixed/walked-around?

Hi Anton,

I’m very confused about your setup. The subject of these emails suggests you want to use arm-linux-gnueabihf, but the CMake verbose output you showed shows you’ve told it to use clang++ (/usr/local/bin/clang++ -target armv7a-linux-gnueabihf). The compiler flags also seem to be a frankenmix of x86 and ARM ( -L/usr/lib/gcc/x86_64-linux-gnu/4.7 is never gonna work!)

I managed a build without any problems using:

mkdir build; cd build; cmake … -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ -DCMAKE_SYSTEM_NAME=Linux

As the CMake cross-compilation wiki says, “CMAKE_SYSTEM_NAME” is very important as it tells CMake that it’s cross compiling.

I also went and looked at the wiki page you quoted, and went and tried it out. That page is written for someone who wants to cross compile with clang. You want to cross-compile with gcc, so there are some changes you need to make.

You must remove the “-target” parameter. You must also remove the “-ccc-gcc-name” parameter. You also still need the CMAKE_C_COMPILER and CMAKE_CXX_COMPILER arguments. So the line becomes:

cmake … -DCMAKE_C_COMPILER=/work/tools/linaro/gnueabi/2013.08-20130816/bin/arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=/work/tools/linaro/gnueabi/2013.08-20130816/bin/arm-linux-gnueabihf-g++ -DCMAKE_CROSSCOMPILING=True -DLLVM_TABLEGEN=/work/llvm/build7/…/build6/native/bin/llvm-tblgen -DLLVM_DEFAULT_TARGET_TRIPLE=arm-linux-gnueabihf -DLLVM_TARGET_ARCH=ARM -DLLVM_TARGETS_TO_BUILD=ARM -DCMAKE_CXX_FLAGS=’ -mcpu=cortex-a9 -I/usr/arm-linux-gnueabihf/include/c++/4.7.2/arm-linux-gnueabihf/ -I/usr/arm-linux-gnueabihf/include/ -mfloat-abi=hard’

Where ‘/work/llvm/build7/…/build6/native/bin’ is the location of a previously-built x86 llvm-tblgen.

Hopefully this has helped. My preference would be the first command line I pasted - using -DCMAKE_SYSTEM_NAME=Linux. That seems the simplest way to me, and it gets LLVM to auto-create its own native llvm-tblgen.

Cheers,

James

Thanks, James.

I will give it a try right now!

I’ve noticed you’ve used linaro toolchain instead of ubuntu’s gcc-4.7-arm-linux-gnueabihf (and other packages from http://llvm.org/docs/HowToCrossCompileLLVM.html).
Can you write what packages should be downloaded and installed from http://www.linaro.org/downloads/ ?

Thanks and regards,
Anton.

Anton,

The compiler I’m using is this one: https://launchpad.net/gcc-linaro/+milestone/4.8-2013.08 . This just happens to be the latest linaro compiler installed on the central package database at ARM. I’d assume the ubuntu one would work just as well.

Cheers,

James

Hi.

I’ve succeed to compile clang for ARM using ubuntu …gnueabihf… packages, but libclang.so can’t be stripped
using tool from ndk because of error:

/softdev/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/…/lib/gcc/arm-linux-androideabi/4.6/…/…/…/…/arm-linux-androideabi/bin/ld: error: /Users/asmirnov/Documents/dev/src/clang_jni/obj/local/armeabi/libclang.so uses VFP register arguments, output does not

Not sure what’s wrong now since i’ve passed cpu and float (hard) as parameters. Any suggestions?
BTW I’m going to use it on android devices which are ARM hard float.

I’m going to try to compile it with linaro toolchain tomorrow on 32bit vm as it does not work on 64bit (or i was not able just to find it for 64bit).

Thanks,
Anton.

Hi Anton,

Ensure -mfloat-abi=hard is in your CFLAGS and CXXFLAGS. Also ensure you target a recent-ish processor or -march=armv7.

I can’t really give support on the android linker, but it does look like your resulting binary is soft-float.

James

If you are using Android’s NDK, you should be aware that it targets soft-float for all ARM ABIs. Thus, if you are linking against any of the NDK components, they are not going to match a hard-float piece that you have built from scratch.

Steve

Hi, Steven.

That’s exactly what i’m having now!

I’ve tried to solve it by adding LOCAL_EXPORT_CPPFLAGS := -mfpu=vfp -mfloat-abi=hard in Android.mk and APP_ABI := armeabi-v7a in Application.mk but it did not help unfortunately.
I’m using android log (#include <android/log.h>, #include <stdio.h> and #include <string.h>) is this the reason of linking error?

Do you know how can it be solved?

PS. i’ve tried ndk-build v=1 to see actual command line and it seems that i can just use linker from arm-linux-gnueabihf toolchains… How do you think
will it help?

Sorry, Stephen*.

Right, I think that you can’t use hard-float for your compiler ABI. You will need to recompile things with soft-float. The NDK does not supply any hard-float libraries to link against, so by passing -mfloat-abi=hard, you are still picking up the soft-float versions (and hence getting link errors).

Steve

Can i do another way - use hard float files that are compiled soft float now (as it’s pretty difficult to compile libxxx.so soft float)?
May be i can just skip using ndk and compile/link it using cmake and native toolchain? What libs should be recompiled hard float, libc?

It would be best to look at the linker command line (the one that failed) to see what libraries/files were being pulled in. Then you might be able to recompile those for the ABI details that you want to support. If you are planning to run your resulting executable on Android, I again caution you that all of the on-device libraries are soft-float and will probably not work (i.e. you will end up just getting corrupt results when arguments get pulled from the wrong registers/stack at runtime). In that case, you will need to build a device image where libc.so, and other core libraries were constructed with the hard-float ABI. This is unfortunately not something that can be easily achieved with AOSP today, so I stick with my original suggestion to recompile your new components for soft-float.

Steve

Okay, you’re right and i agree with you.