编译 FFmpeg 之 clang

使用 clang 编译 FFmpeg

一、 准备工作

  • 下载 FFmpeg、 最新版 ndk(上篇文章已经提及)
  • 整理下文件(当然用你喜欢的就行, 只要配置的路径对就没问题)

二、 明确使用 target-os=android, 使用 clang 进行编译

2.1 明确 clang 编译环境的位置

# 在相应 ndk 的这个目录下
ndk/toolchains/llvm/prebuilt/darwin-x86_64

让我们看看 clang 等编译工具的内容(bin目录)

aarch64-linux-android-addr2line     i686-linux-android-gprof
aarch64-linux-android-ar        i686-linux-android-ld
aarch64-linux-android-as        i686-linux-android-ld.bfd
aarch64-linux-android-c++filt       i686-linux-android-ld.gold
aarch64-linux-android-dwp       i686-linux-android-nm
aarch64-linux-android-elfedit       i686-linux-android-objcopy
aarch64-linux-android-gprof     i686-linux-android-objdump
aarch64-linux-android-ld        i686-linux-android-ranlib
aarch64-linux-android-ld.bfd        i686-linux-android-readelf
aarch64-linux-android-ld.gold       i686-linux-android-size
aarch64-linux-android-nm        i686-linux-android-strings
aarch64-linux-android-objcopy       i686-linux-android-strip
aarch64-linux-android-objdump       i686-linux-android16-clang
aarch64-linux-android-ranlib        i686-linux-android16-clang++
aarch64-linux-android-readelf       i686-linux-android17-clang
aarch64-linux-android-size      i686-linux-android17-clang++
aarch64-linux-android-strings       i686-linux-android18-clang
aarch64-linux-android-strip     i686-linux-android18-clang++
aarch64-linux-android21-clang       i686-linux-android19-clang
aarch64-linux-android21-clang++     i686-linux-android19-clang++
aarch64-linux-android22-clang       i686-linux-android21-clang
aarch64-linux-android22-clang++     i686-linux-android21-clang++
aarch64-linux-android23-clang       i686-linux-android22-clang
aarch64-linux-android23-clang++     i686-linux-android22-clang++
aarch64-linux-android24-clang       i686-linux-android23-clang
aarch64-linux-android24-clang++     i686-linux-android23-clang++
aarch64-linux-android26-clang       i686-linux-android24-clang
aarch64-linux-android26-clang++     i686-linux-android24-clang++
aarch64-linux-android27-clang       i686-linux-android26-clang
aarch64-linux-android27-clang++     i686-linux-android26-clang++
aarch64-linux-android28-clang       i686-linux-android27-clang
aarch64-linux-android28-clang++     i686-linux-android27-clang++
aarch64-linux-android29-clang       i686-linux-android28-clang
aarch64-linux-android29-clang++     i686-linux-android28-clang++
arm-linux-androideabi-addr2line     i686-linux-android29-clang
arm-linux-androideabi-ar        i686-linux-android29-clang++
arm-linux-androideabi-as        ld.lld
arm-linux-androideabi-c++filt       llvm-ar
arm-linux-androideabi-dwp       llvm-as
arm-linux-androideabi-elfedit       llvm-config
arm-linux-androideabi-gprof     llvm-cov
arm-linux-androideabi-ld        llvm-dis
arm-linux-androideabi-ld.bfd        llvm-link
arm-linux-androideabi-ld.gold       llvm-modextract
arm-linux-androideabi-nm        llvm-nm
arm-linux-androideabi-objcopy       llvm-objcopy
arm-linux-androideabi-objdump       llvm-profdata
arm-linux-androideabi-ranlib        llvm-readobj
arm-linux-androideabi-readelf       llvm-strip
arm-linux-androideabi-size      llvm-symbolizer
arm-linux-androideabi-strings       pkg-config
arm-linux-androideabi-strip     sancov
armv7a-linux-androideabi16-clang    sanstats
armv7a-linux-androideabi16-clang++  scan-build
armv7a-linux-androideabi17-clang    scan-view
armv7a-linux-androideabi17-clang++  x86_64-linux-android-addr2line
armv7a-linux-androideabi18-clang    x86_64-linux-android-ar
armv7a-linux-androideabi18-clang++  x86_64-linux-android-as
armv7a-linux-androideabi19-clang    x86_64-linux-android-c++filt
armv7a-linux-androideabi19-clang++  x86_64-linux-android-dwp
armv7a-linux-androideabi21-clang    x86_64-linux-android-elfedit
armv7a-linux-androideabi21-clang++  x86_64-linux-android-gprof
armv7a-linux-androideabi22-clang    x86_64-linux-android-ld
armv7a-linux-androideabi22-clang++  x86_64-linux-android-ld.bfd
armv7a-linux-androideabi23-clang    x86_64-linux-android-ld.gold
armv7a-linux-androideabi23-clang++  x86_64-linux-android-nm
armv7a-linux-androideabi24-clang    x86_64-linux-android-objcopy
armv7a-linux-androideabi24-clang++  x86_64-linux-android-objdump
armv7a-linux-androideabi26-clang    x86_64-linux-android-ranlib
armv7a-linux-androideabi26-clang++  x86_64-linux-android-readelf
armv7a-linux-androideabi27-clang    x86_64-linux-android-size
armv7a-linux-androideabi27-clang++  x86_64-linux-android-strings
armv7a-linux-androideabi28-clang    x86_64-linux-android-strip
armv7a-linux-androideabi28-clang++  x86_64-linux-android21-clang
armv7a-linux-androideabi29-clang    x86_64-linux-android21-clang++
armv7a-linux-androideabi29-clang++  x86_64-linux-android22-clang
bisect_driver.py            x86_64-linux-android22-clang++
clang                   x86_64-linux-android23-clang
clang++                 x86_64-linux-android23-clang++
clang-check             x86_64-linux-android24-clang
clang-format                x86_64-linux-android24-clang++
clang-tidy              x86_64-linux-android26-clang
clang-tidy.real             x86_64-linux-android26-clang++
git-clang-format            x86_64-linux-android27-clang
i686-linux-android-addr2line        x86_64-linux-android27-clang++
i686-linux-android-ar           x86_64-linux-android28-clang
i686-linux-android-as           x86_64-linux-android28-clang++
i686-linux-android-c++filt      x86_64-linux-android29-clang
i686-linux-android-dwp          x86_64-linux-android29-clang++
i686-linux-android-elfedit      yasm

我们可以在这里发现不同 Android 版本和架构的编译工具。 通过查看里面的编译工具我们发现, clang、 clang++ 是不但分架构还分 Android 版本的, 而其他工具只分架构。 比如我选几个哈

armv7a-linux-androideabi16-clang 
armv7a-linux-androideabi16-clang++
armv7a-linux-androideabi29-clang 
armv7a-linux-androideabi29-clang++

arm-linux-androideabi-addr2line     
arm-linux-androideabi-ar        
arm-linux-androideabi-as        
arm-linux-androideabi-c++filt       
arm-linux-androideabi-dwp      
arm-linux-androideabi-elfedit     
arm-linux-androideabi-gprof     
arm-linux-androideabi-ld       
arm-linux-androideabi-ld.bfd   
arm-linux-androideabi-ld.gold     
arm-linux-androideabi-nm       
arm-linux-androideabi-objcopy     
arm-linux-androideabi-objdump      
arm-linux-androideabi-ranlib       
arm-linux-androideabi-readelf       
arm-linux-androideabi-size      
arm-linux-androideabi-strings    
arm-linux-androideabi-strip 

发现问题了吗, 前缀不一样耶。 这个问题在配置 configure 时需要特别注意。(这里知道前缀不一样就好了)

2.2 对比 configure 源码明确问题所在

在查看 configure 时 发现如下代码:

set_default target_os
if test "$target_os" = android; then
    cc_default="clang"
fi

ar_default="${cross_prefix}${ar_default}"
cc_default="${cross_prefix}${cc_default}"
cxx_default="${cross_prefix}${cxx_default}"
nm_default="${cross_prefix}${nm_default}"
pkg_config_default="${cross_prefix}${pkg_config_default}"

发现问题了吗?

如果 target-os 设置的是 Android 的话, 那么 使用的 clang 去编译呢。
我们先不管 ar_default、cc_default、cxx_default、....等等的默认值,我们先看最后几行各个工具的拼接, 发现都是 cross_prefix 去拼接的。 cross_prefix 就是我们在设置 configure 里配置的 --cross-prefix 前缀。 发现问题没, 发现问题没, 发现问题没, 我们在 2.1 中刚看到, 很明显 clang、 clang++ 的前缀和 其他工具的不一样。 所以这个地方很矛盾呀。 为了通用,我们可以定义一个参数在外部去单独设置 clang 和 clang++ 的前缀(这里我随便命名成--cross-prefix-clang)。跟设置 --cross-prefix 一样。

现在看下 ar_default、 cc_default、 cxx_default、 nm_default、 pkg_config_default等还有其他工具的默认名字, 可以在configure中全局搜索这个名字看默认值, 发现 ar_default 默认值是ar, 如果拼上前缀的话(--cross-prefix + ar),在编译工具中是存在这个工具的, 其他的也一样。 但是 clang 和 clang++ 也不行, 不存在的, 我们看到在上面已经把 cc_default="clang"了, 但是 clang++ 还没有, 所以在上面需要手动添加一个 cxx_default="clang++", 这样的话(--cross-prefix-clang + clang 或者 + clang++) 才存在哦!

2.3 明确所需要的头文件和库

使用了 clang 编译就需要指定 clang 的头文件和库

使用该目录下的头文件和库, 在编写脚本时, 引入即可
/ndk/toolchains/llvm/prebuilt/darwin-x86_64/sysroot

三、 修改 configure

  • 最新版已经支持 target-os 设置成 android, 所以不用再像以前那样去修改那四个值了。

  • 通过二中我们知道要增加一个变量 --cross-prefix-clang(随便命名)

 --cross-prefix=PREFIX    use PREFIX for compilation tools [$cross_prefix]
 # 这里添加
 --cross-prefix-clang=PREFIX use PREFIX for compilation clang tools [$cross_prefix]

先设置一个帮助信息呢, 规范嘛要

  • 在 CMDLINE_SET 中把新增的变量加入
CMDLINE_SET="
   $PATHS_LIST
   ar
   arch
   as
   assert_level
   build_suffix
   cc
   objcc
   cpu
   cross_prefix
   # 这里添加
   cross_prefix_clang
   custom_allocator
   cxx
  • 修改 clang++ 编译的默认值
set_default target_os
if test "$target_os" = android; then
   cc_default="clang"
   # 这里修改 默认值
   cxx_default="clang++"
fi
ar_default="${cross_prefix}${ar_default}"
# 这里修改成我们新定义的前缀
cc_default="${cross_prefix_clang}${cc_default}"
# 这里修改成我们新定义的前缀
cxx_default="${cross_prefix_clang}${cxx_default}"
nm_default="${cross_prefix}${nm_default}"
pkg_config_default="${cross_prefix}${pkg_config_default}"

  • 修改完后重新 ./configure

四、 编写脚本

#!/bin/bash
export TMPDIR=../temp
# 定义变量(可以不定义, 直接在下面写死也行, 这样不是更加清晰复用和简易嘛)
SYSROOT=/Users/liushuai/ffmpeg_2/ndk/toolchains/llvm/prebuilt/darwin-x86_64/sysroot
# 定义变量(可以不定义, 直接在下面写死也行, 这样不是更加清晰复用和简易嘛)
PLATFORM=/Users/liushuai/ffmpeg_2/ndk/toolchains/llvm/prebuilt/darwin-x86_64
function build
{
   ./configure \
       --prefix=$PREFIX \
       --target-os=android \
       --arch=$CPU \
       --enable-shared \
       --disable-static \
       --disable-doc \
       --disable-ffmpeg \
       --disable-ffplay \
       --disable-ffprobe \
       --disable-avdevice \
       --disable-symver \
       --enable-cross-compile \
       --sysroot=$SYSROOT \
       --cross-prefix=$PLATFORM/bin/arm-linux-androideabi- \
       --cross-prefix-clang=$PLATFORM/bin/armv7a-linux-androideabi16- \
       --extra-cflags="-I$SYSROOT/usr/include" \
       --extra-ldflags="-L$SYSROOT/usr/lib"
       $ADDITIONAL_CONFIGURE_FLAG
       make clean
       make -j4
       make install
}
CPU=armv7-a
PREFIX=../os
build

你会发现直接编译完,动态库生成了!!!, 没有发现中间有任何问题

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容