Ubuntu 19.04编译armeabi-v7a类型Android JNI共享库报错求助
我看了你遇到的问题——在Ubuntu 19.04上编译针对armeabi-v7a的Android JNI共享库时,链接阶段总是出现输入/输出错误,但arm64-v8a、mips等其他架构却能正常编译,换了r9d、r10e、r16b、r21这些NDK版本都没改善。结合你给出的日志、配置和代码,我判断问题大概率不在NDK本身,而是编译环境或文件系统的限制导致的,下面是几个可以尝试的排查和修复步骤:
1. 优先排查共享文件夹的问题
你的编译目录/mnt/hgfs/facedlib/Dlib4Android看起来是VirtualBox的共享文件夹,这类共享目录经常会有文件系统特性限制(比如不支持某些POSIX权限、文件锁或者链接器需要的文件操作),导致链接器无法正常生成输出文件。
- 把代码复制到本地磁盘编译:先把整个项目复制到Ubuntu本地目录,比如
~/facedlib/Dlib4Android,然后再执行ndk-build -B V=1,看看是否能绕过这个问题。 - 调整共享文件夹挂载参数:如果必须用共享目录,尝试重新挂载并添加
metadata参数(VirtualBox默认可能没开启,这个参数会改善文件权限和属性的支持):sudo umount /mnt/hgfs sudo mount -t vboxsf -o uid=$UID,gid=$GID,metadata your_share_name /mnt/hgfs
2. 彻底清理编译缓存后重新构建
有时候旧的编译产物可能损坏,导致后续链接时出错。可以完全清理掉旧的输出文件再重新编译:
ndk-build clean rm -rf obj/ libs/ ndk-build -B V=1
3. 指定链接器的临时文件目录
链接器在工作时会生成临时文件,如果系统默认的临时目录(比如/tmp)在共享磁盘上或者空间不足,也可能触发I/O错误。可以手动指定一个本地磁盘的临时目录:
export TMPDIR=/tmp/ndk_build_temp mkdir -p $TMPDIR ndk-build -B V=1
4. 简化Android.mk配置排查冲突
你的Android.mk里包含了include $(SUB_MK_FILES),如果子目录的Makefile有针对armeabi-v7a的特殊配置,可能导致链接时的冲突。可以先注释掉这一行,只编译当前的native_try.cpp:
# include $(SUB_MK_FILES)
如果这样能成功编译,再逐个排查子目录的Makefile配置,找出冲突点。
5. 验证armeabi-v7a工具链本身是否正常
可以手动用NDK的armeabi-v7a工具链编译一个极简的测试程序,确认工具链没有问题:
// test.cpp #include <iostream> int main() { return 0; }
执行以下命令编译:
/home/vmuser/android/android-ndk-r16b/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=armv7-none-linux-androideabi16 --sysroot=/home/vmuser/android/android-ndk-r16b/platforms/android-16/arch-arm test.cpp -o test.so -shared
如果这个命令能成功生成test.so,说明工具链本身是正常的,问题还是出在项目配置或文件系统上。
6. 检查系统磁盘空间和inode使用
磁盘空间不足或者inode耗尽也会导致I/O错误,执行以下命令检查:
df -h # 检查磁盘空间 df -i # 检查inode数量
如果空间不足,清理一些无用文件;如果inode不够,删除大量小文件释放inode。
按照上面的步骤逐一排查,应该能找到问题的根源。我最怀疑的是共享文件夹的限制,建议先尝试把代码复制到本地目录编译,这是最容易验证的方案。
内容的提问来源于stack exchange,提问作者ghphone

