【问题标题】:Build FFMPEG 4.2 with Android NDK r20使用 Android NDK r20 构建 FFMPEG 4.2
【发布时间】:2019-08-27 19:47:27
【问题描述】:

我正在尝试使用 Android NDK r20 构建 FFMPEG 4.2,但我遇到了 configure 的问题。

我关注了 Ilia Kosynkin 的博客文章 (https://medium.com/@ilja.kosynkin/building-ffmpeg-4-0-for-android-with-clang-642e4911c31e),并对 build.sh 进行了一些小改动,我成功地在 Ubuntu 16 VM 上使用 Android NDK r17c 为 API 级别 14 构建了 FFMPEG 4.0.2。

我将 FFMPEG 更新到 4.2,将 Android NDK 更新到 r20,但出现了这些和其他编译器错误。

~/android-ndk/sysroot/usr/include/stdlib.h:61:7: error: expected identifier or '('
char* getenv(const char* __name);
      ^
./config.h:17:19: note: expanded from macro 'getenv'
#define getenv(x) NULL
                  ^
~/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/8.0.7/include/stddef.h:105:18: note: expanded from macro 'NULL'
#  define NULL ((void*)0)

还有很多这样的:

./libavutil/libm.h:54:32: error: static declaration of 'cbrt' follows non-static declaration
static av_always_inline double cbrt(double x)
                               ^
~/android-ndk/sysroot/usr/include/math.h:191:8: note: previous declaration is here
double cbrt(double __x);
       ^

除了cbrt 之外,还重新定义了大约十几个其他与数学相关的函数(例如 lrint、round、trunc、inet_aton)。我打开了生成的config.h,注释掉了#define getenv(x) NULL,并将#define HAVE_CBRT 0 之类的定义更改为#define HAVE_CBRT 1。我运行了make 和make install,构建成功。

所以我的问题是,是否有可以传递给configure 的 ffmpeg 选项,这些选项将生成一个无需修改即可成功构建的 config.h?

编辑:来自 config.log 的其他信息。

似乎configure 中的check_mathfunc 对NDK r20 失败,但我不知道为什么。这是一个链接命令在检查truncf 时失败的示例。这个错误对我没有任何意义。

~/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ld
    -L~/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x
    -L~/android-ndk/platforms/android-29/arch-arm/usr/lib
    --fix-cortex-a8 -lc --sysroot=~/android-ndk/sysroot -fPIE -pie
    -o /tmp/ffconf.1OTX8pa8/test /tmp/ffconf.1OTX8pa8/test.o -lgcc

~/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ld:
    fatal error: -f/--auxiliary may not be used without -shared

编辑 2:错误似乎是由 -pie 选项(创建与位置无关的可执行文件)引起的。以前版本的 FFMPEG 在 android 的 configure 脚本中没有这两行:

add_cflags -fPIE
add_ldexeflags -fPIE, -pie

如果我将 -shared 添加到 add_ldexeflags,我会收到错误“-shared 和 -pie 不兼容”。如果我将 -pie 替换为 -shared,check_mathfunc 会成功,但我不知道这样做是否正确。 -fPIE 需要 -shared 但 -pie 不能与它一起使用,这似乎很奇怪。

用 -shared 替换 -pie 似乎可以修复 config.h 文件,但现在我在构建 libavutil 期间得到了 'sys/sysctl.h' file not found。 NDK r20 有 2 个 sysctl.h 实例,NDK r17c 有 1 个实例,但它们都不在名为 sys 的目录中。

编辑 3:我将把它归结为 FFMPEG configure 脚本中的一个错误。 configure 通过生成一个使用该函数的小源文件然后编译和链接生成的文件来检查函数是否存在。如果出现任何故障,该功能将不可用。对于 NDK r17c,check_func sysctl 失败并且构建排除了sysctl 功能。由于某种原因,NDK r20 的测试成功,因为check_func 不验证sys/sysctl.h 是否存在,它只是原型sysctl() 并调用它。我通过向configure 添加一个名为check_sysfunc 的函数来解决这个问题,该函数试图包含sys/sysctl.h。我现在克服了这个错误,并有了一个关于隐式声明无效的新错误。我不得不假设这也是configure 的一个缺陷,希望不会有太多这样的情况。

【问题讨论】:

    标签: ffmpeg android-ndk


    【解决方案1】:

    我目前正在尝试和你做同样的事情。显然,这个人(不是我)设法用 NDK r20 编译 ffmpeg4.2。到目前为止,它似乎与 ARCH=armv7a 一起工作

    [Youtube]https://www.youtube.com/watch?v=RP8SEAhcq5M [Github]https://github.com/binglingziyu/ffmpeg-android-build

    [附注我没有足够的声誉发表评论...所以是的...]

    【讨论】:

      【解决方案2】:

      直接将-fPIE 传递给ld 是错误的。那是一个编译器标志。链接器标志拼写为-pie。 -fPIE 是 -f PIE,这是一个完全不同的论点:

      https://linux.die.net/man/1/ld

      -f 名称 --auxiliary=name 创建 ELF 共享对象时,将内部 DT_AUXILIARY 字段设置为指定名称。这告诉了动态 共享对象的符号表应该用作链接器 共享对象名称的符号表上的辅助过滤器。如果你 稍后将程序链接到此过滤器对象,然后,当您运行 程序中,动态链接器将看到 DT_AUXILIARY 字段。如果 动态链接器解析过滤器对象中的任何符号,它 会先检查共享对象中是否有定义 姓名。如果有,将使用它来代替中的定义 过滤器对象。共享对象名称不必存在。就这样 共享对象名称可用于提供替代 某些功能的实现,可能用于调试或 机器特定性能。

      可以多次指定此选项。 DT_AUXILIARY 条目 将按照它们在命令行中出现的顺序创建。

      至于其他问题:

      NDK r20 有 2 个 sysctl.h 实例,NDK r17c 有 1 个,但它们都不在名为 sys 的目录中。

      我刚刚提交了https://github.com/android-ndk/ndk/issues/1068,但我不确定我们是否会修复那个问题。显然,强烈建议不要使用它。修复源不使用这可能是更好的调用。

      【讨论】:

        猜你喜欢
        • 2019-11-08
        • 1970-01-01
        • 2012-06-09
        • 2021-10-22
        • 2017-11-22
        • 2015-05-01
        • 2018-06-25
        • 2014-10-27
        • 2017-01-05
        相关资源
        最近更新 更多