在Android NDK工具链中使用LLVM有什么用?
一点回顾:
我在Ubuntu上使用Gradlew构建我的本机项目,目标是arm和x86_64架构。似乎LLVM被用来调用arm-linux-androideabi-4.9的c / C ++编译器以及x86_64(?)
以下内容摘自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.od-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 ...
..以下是从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.od-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 ...
让我们来看看Android NDK的工具链文件夹中的内容:
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
这让我很困惑。我认为llvm是一种工具链,因为它放在这里,旁边是其他工具链。再次,在Android NDK工具链中实际使用LLVM是什么?
谢谢您的帮助 :)
LLVM是编译器(后端)。使用的编译器是Clang,它位于llvm目录中。 (LLVM是Clang组件的名称,用于执行实际的代码生成,即后端。)
以前,NDK使用GCC作为编译器。使用GCC,每个目标体系结构(arm,aarch64,x86等)都有一个单独的GCC副本,该副本是使用配置的单个目标构建的。另一方面,Clang / LLVM可以使用单个编译器可执行文件来定位任何已配置的体系结构。因此,使用Clang,您将节省一些磁盘空间,避免使用许多单独的编译器可执行文件。这就是为什么llvm目录树只有一个副本。
在NDK r17中,您可以使用GCC和Clang编译器;默认情况下使用Clang,但GCC仍可用于尚未能使用Clang迁移的项目。在较新的NDK版本中,旧的GCC被删除。
在较新的NDK版本中,即使删除了GCC,仍然会保留像aarch64-linux-android-4.9
这样的体系结构特定目录,因为仍然使用GNU binutils(构建过程使用的小工具),并且每个体系结构也有一个副本(即使它们在技术上可能跨架构工作)。
至于为何建造例如手臂也提到了x86_64;当您运行Clang或GCC时,您正在为运行x86_64的构建计算机运行可执行文件,因此prebuilt/linux-x86_64
是路径的一部分。
LLVM现在是一个umbrela项目,它包含多个模块化和可重用的编译器和工具链技术。您可以在The LLVM Compiler Infrastructure查看更多详情。
对于Android NDK,llvm成为默认工具链,因为r13b和gcc自r18b后被删除。
根据工具链目录toolchains/llvm/prebuilt/darwin-x86_64
,llvm支持所有ABI,即x86,x86_64,arm,arm64。
可能在将来的NDK版本中,llvm
目录下只有一个toolchains
目录,当所有gcc相关工具,头文件和库完全移植到llvm时。
可能有所帮助的参考文献:Android NDK path variable for "strip" command in CMake build tool chain
刚刚对不同的NDK版本进行了快速测试,以检查用于交叉编译的--gcc-toolchain
和--sysroot
的配置。
--target=armv7-none-linux-androideabi
--gcc-toolchain=~/ndks/android-ndk-r16b/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
--sysroot=~/ndks/android-ndk-r16b/sysroot
--target=armv7-none-linux-androideabi
--gcc-toolchain=~/ndks/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
--sysroot=~/ndks/android-ndk-r17c/sysroot
--target=armv7-none-linux-androideabi19
--gcc-toolchain=~/ndks/android-ndk-r18b/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
--sysroot=~/ndks/android-ndk-r18b/sysroot
--target=armv7-none-linux-androideabi19
--gcc-toolchain=~/ndks/android-ndk-r19b/toolchains/llvm/prebuilt/darwin-x86_64
--sysroot=~/ndks/android-ndk-r19b/toolchains/llvm/prebuilt/darwin-x86_64/sysroot
如上所示,在NDK r19b之前,NDK使用clang编译器,但--gcc-toolchain
和--sysroot
被配置为构建工具,头文件和库的旧路径。
但是,由于NDK r19b,--gcc-toolchain
和--sysroot
被配置为新的工具链llvm,即toolchains/llvm/prebuilt/darwin-x86_64
,并且将使用工具(例如,ranlib,ar,strip等)头文件和“llvm版本”的库。
此外,请注意toolchains/llvm/prebuilt/darwin-x86_64
包含对所有Android ABI的支持,即arm64-v8a的aarch64-linux-android
,armeabi-v7a的arm-linux-androideabi
,x86的i686-linux-android
,x86_64的x86_64-linux-android
。
因此,如果您想纯粹使用llvm工具链,可以试用NDK r19b。