編譯 FFmpeg 之 clang

使用 clang 編譯 FFmpeg

一、 準備工作

  • 下載 FFmpeg、 最新版 ndk(上篇文章已經提及)
  • 整理下文件(當然用你喜歡的就行, 只要配置的路徑對就沒問題)

二、 明確使用 target-os=android, 使用 clang 進行編譯

2.1 明確 clang 編譯環(huán)境的位置

# 在相應 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

我們可以在這里發(fā)現(xiàn)不同 Android 版本和架構的編譯工具。 通過查看里面的編譯工具我們發(fā)現(xiàn), 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 

發(fā)現(xiàn)問題了嗎, 前綴不一樣耶。 這個問題在配置 configure 時需要特別注意。(這里知道前綴不一樣就好了)

2.2 對比 configure 源碼明確問題所在

在查看 configure 時 發(fā)現(xiàn)如下代碼:

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}"

發(fā)現(xiàn)問題了嗎?

如果 target-os 設置的是 Android 的話, 那么 使用的 clang 去編譯呢。
我們先不管 ar_default、cc_default、cxx_default、....等等的默認值,我們先看最后幾行各個工具的拼接, 發(fā)現(xiàn)都是 cross_prefix 去拼接的。 cross_prefix 就是我們在設置 configure 里配置的 --cross-prefix 前綴。 發(fā)現(xiàn)問題沒, 發(fā)現(xiàn)問題沒, 發(fā)現(xiàn)問題沒, 我們在 2.1 中剛看到, 很明顯 clang、 clang++ 的前綴和 其他工具的不一樣。 所以這個地方很矛盾呀。 為了通用,我們可以定義一個參數(shù)在外部去單獨設置 clang 和 clang++ 的前綴(這里我隨便命名成--cross-prefix-clang)。跟設置 --cross-prefix 一樣。

現(xiàn)在看下 ar_default、 cc_default、 cxx_default、 nm_default、 pkg_config_default等還有其他工具的默認名字, 可以在configure中全局搜索這個名字看默認值, 發(fā)現(xiàn) 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]

先設置一個幫助信息呢, 規(guī)范嘛要

  • 在 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

你會發(fā)現(xiàn)直接編譯完,動態(tài)庫生成了!!!, 沒有發(fā)現(xiàn)中間有任何問題

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容