交叉编译FFmpeg至armv6架构时ARM指令不兼容错误求助
我需要为32位旧ARMv6架构(arm1176jzf-s)交叉编译FFmpeg应用,已使用ct-ng构建交叉工具链,配置如下:
CT_CONFIG_VERSION="4" CT_PARALLEL_JOBS=8 CT_PATCH_BUNDLED_LOCAL=y CT_LOCAL_PATCH_DIR="${CT_TOP_DIR}/patches" CT_ARCH="arm" CT_ARCH_CHOICE_KSYM="ARM" CT_ARCH_ARM=y CT_ARCH_CPU="arm1176jzf-s" CT_ARCH_FPU="vfp" CT_ARCH_FLOAT_HW=y CT_TOOLCHAIN_PKGVERSION="Sample" CT_TARGET_VENDOR="unknown" CT_KERNEL_LINUX=y CT_LINUX_V_6_12=y CT_BINUTILS_V_2_43=y CT_BINUTILS_LINKER_LD_GOLD=y CT_BINUTILS_GOLD_THREADS=y CT_BINUTILS_LD_WRAPPER=y CT_BINUTILS_PLUGINS=y CT_GLIBC_V_2_24=y CT_GLIBC_EXTRA_CFLAGS="" CT_CC_GCC_EXTRA_CONFIG_ARRAY="--enable-multiarch --enable-libstdcxx-backtrace=yes" CT_CC_GCC_LTO_ZSTD=y CT_CC_GCC_DISABLE_PCH=y CT_CC_GCC_ENABLE_DEFAULT_PIE=y CT_CC_GCC_LIBGOMP=y CT_CC_GCC_LIBQUADMATH=y CT_CC_GCC_LIBSANITIZER=y CT_CC_GCC_BUILD_ID=y CT_CC_LANG_CXX=y CT_CC_LANG_FORTRAN=y CT_GDB_NATIVE_BUILD_IPA_LIB=y CT_GDB_NATIVE_STATIC_LIBSTDCXX=y CT_GCC_V_9=y
编译得到的arm-unknown-linux-gnueabihf-gcc版本为9.5.0,可正常编译helloworld程序,但编译FFmpeg时,链接阶段出现错误:
tmp/ccdQb5lt.s:103: Error: selected processor does not support `movw r8,#0xFFFF' in ARM mode tmp/ccdQb5lt.s:162: Error: selected processor does not support `movw r8,#0xFFFF' in ARM mode tmp/ccdQb5lt.s:222: Error: selected processor does not support `movw r5,#0xFFFF' in ARM mode tmp/ccdQb5lt.s:281: Error: selected processor does not support `movw r9,#0xFFFF' in ARM mode tmp/ccdQb5lt.s:339: Error: selected processor does not support `movw ip,#0xFFFF' in ARM mode tmp/ccdQb5lt.s:398: Error: selected processor does not support `movw r9,#0xFFFF' in ARM mode tmp/ccdQb5lt.s:456: Error: selected processor does not support `movw r9,#0xFFFF' in ARM mode tmp/ccdQb5lt.s:1914: Error: selected processor does not support `movw r4,#0xFFFF' in ARM mode tmp/ccdQb5lt.s:26915: Error: selected processor does not support `movw r4,#0xFFFF' in ARM mode tmp/ccdQb5lt.s:29031: Error: selected processor does not support `movw r9,#0xFFFF' in ARM mode tmp/ccdQb5lt.s:32384: Error: selected processor does not support `movw ip,#0xFFFF' in ARM mode lto-wrapper: fatal error: arm-unknown-linux-gnueabihf-gcc returned 1 exit status
我理解错误含义,但不解为何编译器会生成目标处理器不支持的指令,如何让编译器避免使用这类指令?
解决方案
错误原因
movw是ARMv7及以上架构才支持的指令,问题核心是链接时优化(LTO)阶段丢失了架构约束:你的工具链开启了CT_CC_GCC_LTO_ZSTD=y,FFmpeg默认也可能启用LTO,在全局优化过程中,编译器没有严格遵循ARMv6的指令集限制,生成了ARMv7专属指令。helloworld代码简单,不会触发这类跨架构优化,因此能正常编译。
解决步骤
禁用LTO
在FFmpeg的configure命令中添加--disable-lto,关闭链接时优化,避免优化阶段突破架构限制:./configure --disable-lto ... # 其他功能配置选项强制指定ARMv6架构编译参数
在configure前明确传递针对arm1176jzf-s的编译参数,确保所有编译单元严格生成ARMv6兼容指令:CFLAGS="-march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard" \ CXXFLAGS="-march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard" \ ./configure \ --target-os=linux \ --arch=arm \ --cross-prefix=arm-unknown-linux-gnueabihf- \ --disable-lto \ # 添加你的FFmpeg功能配置,比如--enable-gpl、--disable-debug等注:
-march=armv6zk是arm1176jzf-s对应的准确架构标识,包含该CPU支持的Thumb2和DSP扩展。验证工具链默认参数
运行以下命令检查交叉编译器的默认架构参数,确认工具链是否真的默认适配ARMv6:arm-unknown-linux-gnueabihf-gcc -v如果输出中
-march不是armv6相关值,必须通过上述CFLAGS/CXXFLAGS强制覆盖。排查FFmpeg自动优化
如果上述步骤无效,可临时禁用FFmpeg的汇编优化(代价是性能下降,仅用于排查问题):./configure --disable-asm ...
内容的提问来源于stack exchange,提问作者Daniel

