为何配置为armv7-a的官方ARM工具链可同时编译armv7与armv8代码?
问题
我从ARM官网下载了官方ARM Linux gnueabihf工具链的13.2版本,查看其配置命令行发现编译工具被配置为--with-arch=armv7-a。但当我分别用-march=armv7-a和-march=armv8-a参数编译测试二进制文件时,通过arm-linux-gnueabihf-readelf检查发现生成的so文件分别带有v7和v8的Tag_CPU_arch标签。而使用树莓派3+的工具链(配置为armv8-a)时,即使指定-march=armv7-a编译,生成的二进制文件仍显示v8标签。请问为何配置为armv7-a的官方ARM工具链能够生成两种架构的二进制文件?
相关配置与命令
官方ARM工具链配置
$ /opt/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-gcc -v Using built-in specs. COLLECT_GCC=/opt/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-gcc COLLECT_LTO_WRAPPER=/opt/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-linux-gnueabihf/bin/../libexec/gcc/arm-none-linux-gnueabihf/13.2.1/lto-wrapper Target: arm-none-linux-gnueabihf Configured with: /data/jenkins/workspace/GNU-toolchain/arm-13/src/gcc/configure --target=arm-none-linux-gnueabihf --prefix= --with-sysroot=/arm-none-linux-gnueabihf/libc --with-build-sysroot=/data/jenkins/workspace/GNU-toolchain/arm-13/build-arm-none-linux-gnueabihf/install//arm-none-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c,c++,fortran --with-gmp=/data/jenkins/workspace/GNU-toolchain/arm-13/build-arm-none-linux-gnueabihf/host-tools --with-mpfr=/data/jenkins/workspace/GNU-toolchain/arm-13/build-arm-none-linux-gnueabihf/host-tools --with-mpc=/data/jenkins/workspace/GNU-toolchain/arm-13/build-arm-none-linux-gnueabihf/host-tools --with-isl=/data/jenkins/workspace/GNU-toolchain/arm-13/build-arm-none-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-mode=thumb --with-arch=armv7-a --with-pkgversion='Arm GNU Toolchain 13.2.rel1 (Build arm-13.7)' Thread model: posix Supported LTO compression algorithms: zlib gcc version 13.2.1 20231009 (Arm GNU Toolchain 13.2.rel1 (Build arm-13.7))
编译与验证命令
$ arm-linux-gnueabihf-gcc -march=armv7-a -shared -fPIC -o arm_raw_v7.so test.c $ arm-linux-gnueabihf-gcc -march=armv8-a -shared -fPIC -o arm_raw_v8.so test.c $ arm-linux-gnueabihf-readelf -A arm_raw_v?.so | grep Tag_CPU_arch: Tag_CPU_arch: v7 Tag_CPU_arch: v8
树莓派工具链配置
/opt/cross-pi-gcc-10.2.0-2/bin/arm-linux-gnueabihf-gcc -v Using built-in specs. COLLECT_GCC=/opt/cross-pi-gcc-10.2.0-2/bin/arm-linux-gnueabihf-gcc COLLECT_LTO_WRAPPER=/opt/cross-pi-gcc-10.2.0-2/bin/../libexec/gcc/arm-linux-gnueabihf/10.2.0/lto-wrapper Target: arm-linux-gnueabihf Configured with: ../configure --prefix= --target=arm-linux-gnueabihf --enable-languages=c,c++,fortran --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/cross-pi-gcc-10.2.0-2/arm-linux-gnueabihf/libc --with-arch=armv8-a --with-fpu=neon-fp-armv8 --with-float=hard --disable-multilib Thread model: posix Supported LTO compression algorithms: zlib gcc version 10.2.0 (GCC)
解答
- 官方ARM工具链的
--with-arch=armv7-a只是默认架构设置,并非限制工具链只能生成该架构的代码。GCC工具链在编译时允许通过-march参数覆盖默认值,只要工具链本身支持目标架构的指令集。 - 官方ARM 13.2版本工具链编译时启用了对ARMv8-A架构的支持——ARM的官方工具链通常会向后兼容更高版本的架构,尤其是当基础架构是ARMv7-A时,只要工具链在编译时包含了ARMv8-A的指令集支持,就能通过
-march=armv8-a生成对应架构的代码。 - 树莓派工具链的差异在于它配置了
--disable-multilib,同时默认架构是ARMv8-A。当你指定-march=armv7-a时,虽然编译器会生成ARMv7-A的指令,但工具链的目标系统根目录(sysroot)中使用的是ARMv8-A的库,链接阶段会将二进制文件的架构标签统一为工具链默认的ARMv8-A。另外,旧版本GCC(比如树莓派用的10.2.0)在处理架构标签时,可能不会完全跟随-march参数修改,而是优先使用工具链配置时的目标架构。 - 总结来说,官方ARM工具链本身支持多架构编译,
-march参数能直接覆盖默认设置并修改输出二进制的架构标签;而树莓派工具链因编译配置(禁用multilib、默认架构为v8-A)和GCC版本原因,无法通过-march参数彻底更改输出的架构标签。
内容的提问来源于stack exchange,提问作者Richard W
相关产品推荐
相关产品推荐

