Why do I get "error: invalid instruction mnemonic" when compiling FFmpeg for Android?
Why do I get "error: invalid instruction mnemonic" when compiling FFmpeg for Android?
我正在尝试使用 NDK (r18.1.5063045) 中的 clang
为 Android 编译 FFmpeg 4.0。我的主机架构是 Mac OS。
这是我的配置命令:
./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
^~~
知道是什么原因造成的吗?
我怀疑 Clang 的目标是主机 OS 而不是 arm32。使用 standalone toolchain 可以解决该问题。我注意到构建系统仍在使用我的主机 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 and 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);
之后,项目构建成功。
FWIW:该项目还使用这些更改为 arm64 构建:
- 独立工具链:
--arch arm64
- 独立工具链:
--api 21
- 配置:
--arch=aarch64
- 配置:
--strip=/.../aarch64-linux-android-strip
我正在尝试使用 NDK (r18.1.5063045) 中的 clang
为 Android 编译 FFmpeg 4.0。我的主机架构是 Mac OS。
这是我的配置命令:
./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
^~~
知道是什么原因造成的吗?
我怀疑 Clang 的目标是主机 OS 而不是 arm32。使用 standalone toolchain 可以解决该问题。我注意到构建系统仍在使用我的主机 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 and 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);
之后,项目构建成功。
FWIW:该项目还使用这些更改为 arm64 构建:
- 独立工具链:
--arch arm64
- 独立工具链:
--api 21
- 配置:
--arch=aarch64
- 配置:
--strip=/.../aarch64-linux-android-strip