美文网首页
编译 FFmpeg 之 clang

编译 FFmpeg 之 clang

作者: zhuxiaoan | 来源:发表于2019-08-20 13:19 被阅读0次

    使用 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
    
    

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

    相关文章

      网友评论

          本文标题:编译 FFmpeg 之 clang

          本文链接:https://www.haomeiwen.com/subject/hmxpsctx.html