在为Android编译FFmpeg时,为什么会出现“错误:无效的指令助记符”的提示?

4
我正在尝试使用NDK (r18.1.5063045)中的clang编译Mac OS上的Android FFmpeg 4.0。以下是我的配置命令:
./configure \
--target-os=android \
--arch=armv7-a \
--enable-cross-compile \
--cc=${ANDROID_NDK}/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang \
--enable-shared \
--disable-static 

这个步骤已经成功完成。然后我运行make -j8,并得到以下错误:

In file included from libavfilter/vf_mestimate.c:22:
In file included from ./libavcodec/mathops.h:40:
./libavcodec/arm/mathops.h:90:26: error: invalid instruction mnemonic 'itt'
    "cmp   %1, %2  \n\t"
                     ^
<inline asm>:3:2: note: instantiated into assembly here
    itt   gt      
    ^~~

有什么想法导致这种情况发生?
1个回答

6
我怀疑Clang针对的是宿主操作系统而不是arm32。使用独立工具链可以解决这个问题。我注意到构建系统仍在使用我的宿主strip工具(无法处理arm二进制文件),所以我通过将--strip传递给ffmpeg的配置脚本来解决了这个问题。
${ANDROID_NDK}/build/tools/make_standalone_toolchain.py \
    --arch arm --api 16 --install-dir /tmp/standalone-toolchain

./configure \
--target-os=android \
--arch=armv7-a \
--enable-cross-compile \
--cc=/tmp/standalone-toolchain/bin/clang \
--strip=/tmp/standalone-toolchain/bin/arm-linux-androideabi-strip \
--enable-shared \
--disable-static 

make -j...

编译过程中出现错误,位于libavdevice/v4l2.c文件中:

CC  libavdevice/v4l2.o
libavdevice/v4l2.c:135:9: error: assigning to 'int (*)(int, unsigned long, ...)' from incompatible type
      '<overloaded function type>'
        SET_WRAPPERS();
        ^~~~~~~~~~~~~~
libavdevice/v4l2.c:121:17: note: expanded from macro 'SET_WRAPPERS'
    s->ioctl_f  = prefix ## ioctl;      \
                ^           ~~~~~
/tmp/standalone-toolchain/bin/../sysroot/usr/include/bits/ioctl.h:56:5: note: candidate function has type mismatch at 2nd
      parameter (expected 'unsigned long' but has 'unsigned int')
int ioctl(int __fd, unsigned __request, ...) __overloadable __enable_if(1, "") __RENAME(ioctl);
    ^
/tmp/standalone-toolchain/bin/../sysroot/usr/include/bits/ioctl.h:36:5: note: candidate function has type mismatch at 2nd
      parameter (expected 'unsigned long' but has 'int')
int ioctl(int __fd, int __request, ...);
    ^

关于ioctl的第二个参数类型存在争议。glibc使用unsigned long类型声明:

int ioctl(int fd, unsigned long request, ...);

POSIX 和Bionic(以及musl)使用 int 声明它:

int ioctl(int fildes, int request, ... /* arg */);

类似的问题也出现在PulseAudio和musl上,因此我对ffmpeg应用了相同类型的修复:

diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index 10a0ff0dd6..1b9c6e760b 100644
--- a/libavdevice/v4l2.c
+++ b/libavdevice/v4l2.c
@@ -95,7 +95,11 @@ struct video_data {
     int (*open_f)(const char *file, int oflag, ...);
     int (*close_f)(int fd);
     int (*dup_f)(int fd);
+#ifdef __GLIBC__
     int (*ioctl_f)(int fd, unsigned long int request, ...);
+#else
+    int (*ioctl_f)(int fd, int request, ...);
+#endif
     ssize_t (*read_f)(int fd, void *buffer, size_t n);
     void *(*mmap_f)(void *start, size_t length, int prot, int flags, int fd, int64_t offset);
     int (*munmap_f)(void *_start, size_t length);

之后,项目构建成功。
顺便说一下:使用这些更改,该项目也可以构建为arm64:
  • 独立工具链:--arch arm64
  • 独立工具链:--api 21
  • 配置:--arch=aarch64
  • 配置:--strip=/.../aarch64-linux-android-strip

很遗憾,我没有解决我的问题。我还收到了一个关于缺少pkgconfig的警告,有什么提示吗?尝试将--pkg-config设置为toolchain/lib/pkgconfig,但那只是一个文件夹。 - natario

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接