Ubuntu 18.04下用Clang+NDK20编译Android版FFmpeg遇错求助
我来帮你一步步分析和解决遇到的两个核心问题:
问题1:getenv宏定义冲突错误
错误原因
你的config.h里被自动生成了#define getenv(x) NULL宏,这和NDK sysroot中stdlib.h里的getenv函数声明直接冲突了。这个宏通常是FFmpeg的configure脚本在检测到目标环境不支持getenv函数时生成的,但在Android NDK环境下其实是支持getenv的,出现这个问题大概率是configure的参数设置导致检测逻辑出错。
解决方案
临时修复:手动修改config.h
打开生成的config.h文件,找到#define getenv(x) NULL这一行,直接删除或者注释掉。之后重新执行make,这个冲突就会消失。根源解决:调整configure参数
你当前的configure参数中加了--disable-pthreads,这可能导致configure误判环境缺少getenv相关依赖。如果你的FFmpeg功能不需要禁用pthreads,建议去掉--disable-pthreads参数;如果必须禁用,那么可以在--extra-cflags中添加-Ugetenv,强制取消这个宏定义:--extra-cflags="-target aarch64-none-linux-android -mfpu=neon -mfloat-abi=soft -I/home/sources/android-ndk-r20/sysroot/usr/include/aarch64-linux-android -O3 -fPIC -Ugetenv"
问题2:C编译器测试失败(链接器错误)
错误原因
从报错信息看,有两个关键点:
- 链接器报错
-f may not be used without -shared:这是因为configure传递了错误的链接参数,可能是-fsanitize=undefined这类参数被错误地加入,而交叉编译时没有配合正确的shared选项。 - 你的
--extra-ldflags里的路径存在错误:比如-L/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/lib/gcc/aarch64-linux-android/4.9.x是相对路径,应该补全为NDK的绝对路径;还有-L/platforms/android-/arch-arm64/usr/lib里的android-是无效的版本号,需要替换成具体的Android API级别(比如android-21)。
解决方案
调整configure的参数,修正路径并清理错误的编译/链接选项:
./configure \ --prefix=android/ \ --disable-asm \ --enable-cross-compile \ --disable-static \ --disable-programs \ --disable-doc \ --enable-shared \ --enable-protocol=file \ --enable-pic \ --enable-small \ # 如果不需要禁用pthreads就去掉下面这行 --disable-pthreads \ --ar=/home/sources/android-ndk-r20/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar \ --strip=/home/sources/android-ndk-r20/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip \ --ld=/home/sources/android-ndk-r20/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-ld \ --cc=/home/sources/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/clang \ --cxx=/home/sources/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ \ --as=/home/sources/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/clang \ --target-os=android \ --extra-cflags="-target aarch64-none-linux-android21 -mfpu=neon -mfloat-abi=softfp -I/home/sources/android-ndk-r20/sysroot/usr/include/aarch64-linux-android -O3 -fPIC -Ugetenv" \ --extra-ldflags="-L/home/sources/android-ndk-r20/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/lib/gcc/aarch64-linux-android/4.9.x -L/home/sources/android-ndk-r20/platforms/android-21/arch-arm64/usr/lib" \ --sysroot=/home/sources/android-ndk-r20/sysroot
这里做了几个关键调整:
- 在
-target参数中添加了Android API级别(aarch64-none-linux-android21),确保clang正确识别目标环境。 - 修正了
--extra-ldflags中的绝对路径,替换了无效的android-为具体的API版本android-21。 - 把
-mfloat-abi=soft改成了softfp,这是ARM64更常用的浮点ABI设置。 - 添加了
-Ugetenv来避免宏定义冲突。
替代编译方法
如果上面的参数调整还是有问题,你可以试试NDK的toolchain脚本生成独立工具链,这样编译参数会更简洁:
生成独立工具链:
/home/sources/android-ndk-r20/build/tools/make_standalone_toolchain.py \ --arch arm64 \ --api 21 \ --install-dir /home/sources/arm64-android-toolchain设置环境变量:
export PATH=/home/sources/arm64-android-toolchain/bin:$PATH export CC=aarch64-linux-android-clang export CXX=aarch64-linux-android-clang++ export AR=aarch64-linux-android-ar export LD=aarch64-linux-android-ld export STRIP=aarch64-linux-android-strip执行configure(参数更简洁):
./configure \ --prefix=android/ \ --disable-asm \ --enable-cross-compile \ --disable-static \ --disable-programs \ --disable-doc \ --enable-shared \ --enable-protocol=file \ --enable-pic \ --enable-small \ --disable-pthreads \ --target-os=android \ --arch=aarch64 \ --extra-cflags="-mfpu=neon -O3 -fPIC -Ugetenv" \ --sysroot=/home/sources/arm64-android-toolchain/sysroot
这种方式不需要手动指定各种工具的绝对路径,NDK已经帮你配置好了,出错概率更低。
内容的提问来源于stack exchange,提问作者Poperton

