Skip to content
Advertisement

What’s the use of LLVM in Android NDK Toolchains?

What’s the use of LLVM in Android NDK Toolchains?


A little recap:

I was building my native project with Gradlew on Ubuntu, targeting arm and x86_64 architectures. Seems that LLVM were utilized to call C/C++ compiler of arm-linux-androideabi-4.9 as well as x86_64(?)

The following is extracted from armeabi-v7a/ndkBuild_build_output.log:

/home/mypc/Android/android-ndk-r17c/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ -MMD -MP -MF /home/mypc/git/android-project-1/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/objs-debug/module-5/stream_cpp.o.d -gcc-toolchain /home/mypc/Android/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 -fpic -ffunction-sections -funwind-tables -fstack-protector-strong -Wno-invalid-command-line-argument …

..and the following is extracted from x86_64/ndkBuild_build_output.log:

/home/mypc/Android/android-ndk-r17c/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ -MMD -MP -MF /home/mypc/git/android-project-1/build/intermediates/ndkBuild/debug/obj/local/x86_64/objs-debug/module-5/stream_cpp.o.d -gcc-toolchain /home/mypc/Android/android-ndk-r17c/toolchains/x86_64-4.9/prebuilt/linux-x86_64 -target x86_64-none-linux-android -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC -Wno-invalid-command-line-argument …

  • The “…” indicates that there’s a long tail of this single-line command I’ve trimmed off.
  • Names of personal folders & project were changed.

Let’s take a look what’s inside Android NDK’s toolchains folder:

myacc:~/.../android-ndk-r17c/toolchains$ tree -L 1
.
├── aarch64-linux-android-4.9
├── arm-linux-androideabi-4.9
├── llvm
├── mips64el-linux-android-4.9
├── mipsel-linux-android-4.9
├── NOTICE-MIPS
├── NOTICE-MIPS64
├── renderscript
├── x86-4.9
└── x86_64-4.9

It’s quite confusing to me. I thought llvm is a kind of toolchain since it’s placed here, next to other toolchains. Again, what’s actually the use of LLVM in Android NDK Toolchains?

Thanks for the help 🙂

Advertisement

Answer

LLVM is the compiler (backend). The compiler used is Clang, which resides within the llvm directory. (LLVM is the name of the component of Clang that does the actual code generation, aka backend.)

Previously, the NDK used GCC as compiler. With GCC, each target architecture (arm, aarch64, x86 etc) had a separate copy of GCC built with that individual target configured. Clang/LLVM on the other hand can target any configured architecture with one single compiler executable. So with Clang, you’ll save a bit of diskspace, avoiding to have many separate compiler executables. That’s why there’s only one copy of the llvm directory tree.

In NDK r17, you have both GCC and Clang compilers available; Clang is used by default but GCC is still available for projects that haven’t been able to migrate to using Clang yet. In newer NDK versions, the old GCC is removed.

In the newer NDK versions, even if GCC is removed, the architecture specific directories like aarch64-linux-android-4.9 are still kept around, as the GNU binutils (minor tools used by the build process) are still used, and those also come in one copy per architecture (even though they technically might work across architectures).

And as for why building for e.g. arm also mentions x86_64; when you are running Clang or GCC, you are running an executable for your build computer which runs x86_64, hence the prebuilt/linux-x86_64 part of the paths.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement