NDK r21d + x264 编写脚本文件 & 编译生成 Android 所需的库

本文最后更新于:1 年前

下载 x264 源码

1
git clone https://code.videolan.org/videolan/x264.git

编写脚本文件

查看文件目录

查看支持的命令

1
./configure --help

部分命令说明

Standard options描述
–prefix=PREFIX指定生成的文件存放的位置
–exec-prefix=EPREFIX
–bindir=DIR
–libdir=DIR[PREFIX/lib]
–includedir=DIR[PREFIX/include]
–extra-asflags=EASFLAGS
–extra-cflags=ECFLAGS本质是设置 CFLAGS 变量(默认 gcc、clang 会读取 CFLAGS 变量)
–extra-ldflags=ELDFLAGS
–extra-rcflags=ERCFLAGS
Configuration options描述
–disable-clicli: 命令行工具
–system-libx264
–enable-shared动态库,so 文件
–enable-static静态库,a 文件
–disable-bashcompletion
–enable-bashcompletion
–bashcompletionsdir=DIR
–disable-opencl
–disable-gpl
–disable-thread
–disable-win32thread
–disable-interlaced
–bit-depth=BIT_DEPTH
–chroma-format=FORMAT
Advanced options描述
–disable-asm
–enable-lto
–enable-debug本质是在 CFLAGS 添加 -g
–enable-gprof本质是在 CFLAGS 添加 -pg
–enable-strip本质是在 CFLAGS 添加 -s
–enable-pic*本质是在 CFLAGS 添加 -fPIC,Android 需要
Cross-compilation描述
–host=HOST*运行的平台
–cross-prefix=PREFIX*设置库文件的路径前缀
–sysroot=SYSROOT*指定库与头文件的搜索路径的根目录(默认会使用 Linux 的文件,Android 需要改为使用 NDK 中的文件)
External library support描述
–disable-avs
–disable-swscale
–disable-lavf
–disable-ffms
–disable-gpac
–disable-lsmash

编写脚本文件

1、创建文件

1
gedit build.sh
  • CC: 指定编译 C 的编译器,需要以环境变量使用
  • CXX: 指定编译 C++ 的编译器,需要以环境变量使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/bin/bash

function my_build
{
./configure \
--prefix=$MY_PREFIX \
--extra-cflags=$MY_EXTRA_CFLAGS \
--disable-cli \
--enable-shared \
--enable-pic \
--host=$MY_HOST \
--cross-prefix=$MY_CROSS_PREFIX \
--sysroot=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/sysroot \

make clean
make -j8
make install
}

#arm64-v8a
export CC=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang
export CXX=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++
MY_PREFIX=./Android/arm64-v8a
MY_EXTRA_CFLAGS="-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O2 -DNDEBUG -fPIC --target=aarch64-none-linux-android21 --gcc-toolchain=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64"
MY_HOST=aarch64-linux-android
MY_CROSS_PREFIX=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-
my_build

#armeabi-v7a
export CC=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang
export CXX=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang++
MY_PREFIX=./Android/armeabi-v7a
MY_EXTRA_CFLAGS="-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -Oz -DNDEBUG -fPIC --gcc-toolchain=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64"
MY_HOST=armv7a-linux-android
MY_CROSS_PREFIX=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-
my_build

#x86_64
export CC=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang
export CXX=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang++
MY_PREFIX=./Android/x86_64
MY_EXTRA_CFLAGS="-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O2 -DNDEBUG -fPIC --target=x86_64-none-linux-android21 --gcc-toolchain=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64"
MY_HOST=x86_64-linux-android
MY_CROSS_PREFIX=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android-
my_build

#x86
export CC=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang
export CXX=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang++
MY_PREFIX=./Android/x86
MY_EXTRA_CFLAGS="-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -mstackrealign -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O2 -DNDEBUG -fPIC --target=i686-none-linux-android21 --gcc-toolchain=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64"
MY_HOST=i686-linux-android
MY_CROSS_PREFIX=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android-
my_build

添加 Android 项目需要的 CFLAGS 的技巧

当 configure 不支持某个参数时,需要主动在 CFLAGS 中添加。

1、新建 Android 的 C++ 项目

2、build release 版本,生成 build.ninja、rules.ninja

3、使用 build.ninja 中的 FLAGS

1
-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security   -Oz -DNDEBUG  -fPIC

4、使用 rules.ninja 中的参数

1
--target=armv7-none-linux-androideabi21 --gcc-toolchain=/home/weichao/android-sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/weichao/android-sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/linux-x86_64/sysroot

调整路径,修改参数,去掉重复的参数:

1
--target=armv7-none-linux-androideabi21 --gcc-toolchain=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64

对脚本中的变量进行抽取,方便修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/bin/bash

NDK_ROOT=/home/weichao/android-ndk-r21d
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64
API=21
API_2=24 #x86在24以下会报错,所以单独指定

function my_build
{
./configure \
--prefix=$MY_PREFIX \
--extra-cflags=$MY_EXTRA_CFLAGS \
--disable-cli \
--enable-shared \
--enable-pic \
--host=$MY_HOST \
--cross-prefix=$MY_CROSS_PREFIX \
--sysroot=$TOOLCHAIN/sysroot \

make clean
make -j8
make install
}

#arm64-v8a
export CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
export CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
MY_PREFIX=./Android/arm64-v8a
MY_EXTRA_CFLAGS="-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O2 -DNDEBUG -fPIC --target=aarch64-none-linux-android21 --gcc-toolchain=$TOOLCHAIN"
MY_HOST=aarch64-linux-android
MY_CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
my_build

#armeabi-v7a
export CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
export CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
MY_PREFIX=./Android/armeabi-v7a
MY_EXTRA_CFLAGS="-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -Oz -DNDEBUG -fPIC --gcc-toolchain=$TOOLCHAIN"
MY_HOST=armv7a-linux-android
MY_CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
my_build

#x86_64
export CC=$TOOLCHAIN/bin/x86_64-linux-android$API-clang
export CXX=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++
MY_PREFIX=./Android/x86_64
MY_EXTRA_CFLAGS="-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O2 -DNDEBUG -fPIC --target=x86_64-none-linux-android21 --gcc-toolchain=$TOOLCHAIN"
MY_HOST=x86_64-linux-android
MY_CROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android-
my_build

#x86
export CC=$TOOLCHAIN/bin/i686-linux-android$API_2-clang
export CXX=$TOOLCHAIN/bin/i686-linux-android$API_2-clang++
MY_PREFIX=./Android/x86
MY_EXTRA_CFLAGS="-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -mstackrealign -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O2 -DNDEBUG -fPIC --target=i686-none-linux-android21 --gcc-toolchain=$TOOLCHAIN"
MY_HOST=i686-linux-android
MY_CROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android-
my_build

编译生成 Android 所需的库

给脚本文件设置权限

1
chmod +x build.sh

执行脚本文件

1
. build.sh

编译可能会遇到缺少 NASM 库的情况,下载安装比较新的版本就可以了。

可以看到 CFLAGS 中的不识别的参数会被忽略:

然后展示基本信息:

然后是详细过程,最后生成文件:

编译完成后生成文件

编译结果查看 log

/x264/config.log

编译 x86 版本时报错:clang: error: unknown argument: ‘-mpreferred-stack-boundary=6’

原因貌似是当 clang 遇到不识别的参数时会报 error,是 clang 的处理机制问题。参见Issue 475183: clang: does not support -mpreferred-stack-boundary=2

解决办法有 2 个:
1、去掉不识别的参数。
2、使用更高版本的修复了这个问题的 clang。

由于我没找到这个参数是在哪加的,且不清楚去掉后会有什么影响,所以我采用第 2 种方法解决这个问题,最终在 i686-linux-android24-clang 版本解决了问题。

1
2
export CC=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang
export CXX=/home/weichao/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang++


NDK r21d + x264 编写脚本文件 & 编译生成 Android 所需的库
https://weichao.io/01bc0b7a05c2/
作者
魏超
发布于
2020年9月18日
更新于
2022年12月4日
许可协议