聊聊
這邊文章主要是個記錄,用於記錄本人在 Windows 中編譯 ffmpeg 的 Android so 的過程中踩到的坑以及詳細過程,方便后續回味。能搜到這里來的同學,想必都知道 ffmpeg 是啥了。我就不多介紹了。不懂的可以百度。
開干。
為啥不用 Windows 直接編譯 so
Windows 直接編譯 so 是個大坑,盡量別用 Windows 直接編譯 ffmpeg。請記住這句話。下面來講幾點原因:
- Windows 原生編譯 so 的文章相比於 Linux 編譯來說,着實不算多。本人也在百度上查閱了各種資料。都沒能找到一篇讓人滿意的參考文章(可能是個人能力有限吧)。
- ffmpeg 是在 Linux 上用純 C 編寫的,證據之一就是 ffmpeg 源碼中的 configure 文件,這是 Linux 小開發們常用的編譯配置方式。這就導致了在 Windows 上編譯 ffmpeg,注定會碰一鼻子灰。尤其是 4.X 以上。比如我遇到的無法解決的一個問題:ffmpeg 4.X.X 以上的軟鏈接問題,其會導致的一個錯誤如下:
ln: failed to create symbolic link 'libavutil.so': No such file or directory
make: *** [ffbuild/library.mak:102: libavutil/libavutil.so] Error 1
clang: error: no such file or directory: 'liba'
make: *** [ffbuild/library.mak:103: libavformat/libavformat.so.58] Error 1
LD libavformat/libavformat.so.58
clang: error: no such file or directory: 'liba'
make: *** [ffbuild/library.mak:103: libavformat/libavformat.so.58] Error 1
如果想要用 Windows 原生編譯 so,可以看看下面兩個東西:
- 一個大佬:https://blog.csdn.net/luo0xue/article/details/90369426。
- Windows 中的編譯安裝過程:
- 安裝 Linux 的開發環境:cygwin。請不要使用 MinGW,更不要使用 Git Bash,二者缺少了一些 ffmpeg 編譯所需要的文件。
- 在 Linux 開發環境中安裝 NDK
- 下載 ffmpeg 源碼
- 配置編譯腳本,進行編譯
Windows10 WSL 編譯 Android so
從上面我踩過的坑中,我發現了在 Windows10 中,使用 Windows10 提供的 WSL 來編譯是最方便的。因為無論是第一個大佬講的東西,還是我第二個總結的東西,都繞不開一個問題:在 Windows 環境下編譯 ffmpeg 的 Android so,必須搭建 Linux 的開發環境。就是基於這一點,我確定了,在 Windows10 下編譯 ffmpeg 的 Android so,使用 Windows10 WSL 是最方便的。下面來詳細講下在 Windows10 WSL 中,如何編譯 Android so
開啟 WSL
按照以下步驟打開 Windows10 的 WSL。
打開控制面板操作如下:
鼠標右鍵 ---> 個性化 ---> 主題 ---> 桌面圖標設置 ---> 勾中控制面板
至此,控制面板圖標便出現在了桌面上:
接着就可以打開 WSL 功能了:控制面板 ---> 點擊程序和功能 ---> 啟用或關閉 Windows 功能 ---> 適用於 Linux 的 Windows 子系統:
然后,就可以去 Microsoft Store 搜索 Ubuntu 了。可以下載 Ubuntu 20.04 LTS 版本:
安裝之后,在開始菜單中點擊打開,初始化 OK 之后,就可以做下面的操作了。
WSL 安裝 NDK
創建目錄:
mkdir -p /home/wenchen/android/ndk
進入目錄:
cd /home/wenchen/android/ndk
使用 wget 命令下載 NDK:
wget https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip
下載完成后解壓到 ndk-r21e 目錄:
unzip android-ndk-r21e-linux-x86_64.zip -d ndk-r21e
解壓好之后配置環境變量:
sudo vim /etc/profile
按 i 鍵編輯,在配置文件末尾增加以下內容:
#android NDK
export ANDROID_NDK="/home/wenchen/android/ndk/ndk-r21e/android-ndk-r21e"
export PATH="$ANDROID_NDK:$PATH"
按 esc 鍵退出編輯模式,輸入 :wq 保存退出。接着更新環境變量:
source /etc/profile
NDK 就配置好了,接着我們可以看下是否 OK。輸入 ndk-build 命令,如果出現以下提示,就 OK 了:
wenchen@DESKTOP-RKNC9R1:~$ ndk-build
Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
/home/wenchen/android/ndk/ndk-r21e/android-ndk-r21e/build/core/build-local.mk:151: *** Android NDK: Aborting . Stop.
搭建 Git 開發環境
下載的 Ubuntu 已經為我們裝好了 Git,我們只需要配置一下就可以了。
輸入下面的命令,配置名稱:
git config --global user.name "xxx"
輸入下面的命令,配置郵件:
git config --global user.email "xxx@yyy.com"
生成 ssh key pair 密鑰對:
啟用 ssh-agent:
eval `ssh-agent`
輸入以下命令,生成 rsa 密鑰。一路回車,不要輸入任何東西,直到生成 OK:
ssh-keygen -t rsa -C "注釋內容(可以是郵箱地址)"
把私鑰添加到 ssh-agent 的高速緩存中:
ssh-add ~/.ssh/id_rsa
打印 rsa 的公鑰信息:
cat ~/.ssh/id_rsa.pub
公鑰信息如下:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDT+zQtc3Hh/zGKtC7Onx1f256g6JMhdXRBTC4uF7MEzd0zzmic71knFxSKln0xWBmwECUzoQ0FI6dvNGOo8qZfnILjm6WpQDU23wSjGHcEw6CANi3TqRKrFpHU/cY7RzwjVtxMeT5RYaBJ3FsifIYY94s47iYBnEMIu5pdDV9sM0J9sg0TUiZhvwi9y51CL+Vu38kQAQQLlbu27MqJJjHSj6nRis71+b8q0HScp8jlXCuQT/34NMoyXC2pNKHvXOsPGgeU+yoT1K+n2zMvhcSn8F22kDMLpe9kdsBCbwZ0rSylh9wZrTZyGJmCwFm4OP5e0fasofM14EMqK2DtKWTXqyjCSHRilUmuiGFG7SHULeU72Rhu1MutozBfuCDYVI1YlanWrX/ifHtkaI1tlhMXXOISgpbSVP3n5AnGhZ6W1tfp+kNeVGbtYRC/DtmVanUS+T3rr2kWVyGEhEetFZNX1n2ZPRA1+YfICbh2rU9EeumhV1P3BPEF+JWGd8IJszBSvBN/eosys/7KCVyAbOGkeTsWdizJoQN7ArKlnyWSGlIVHaLmyupe/otrfVsFbUd7lF4aPYmLJi4YztSGTBlW1scydnaevi3j5mqgFImALJg6X5KAVnSFVHnYVfIpSdgc5KgcG1wLcTz0lg83ieyhSwFBYykAklRCSjicBOwNrQ== xxx@yyy.com
將公鑰信息添加到 Gitee
打開 Gitee 后,選擇設置項:
選擇 SSH公鑰 設置項,粘貼剛才打印的公鑰信息,並點擊確定,公鑰就保存成功了。
下載 ffmpeg 源碼
進入目錄:
cd /home/wenchen/android
創建源碼目錄:
mkdir src
創建 so 目錄:
mkdir so
進入源碼目錄:
cd src
下載 ffmpeg 源碼:
git clone https://gitee.com/mirrors/ffmpeg.git
下載 OK 后,進入 ffmpeg 源碼目錄:
cd ffmpeg
修改 configure 文件權限:
chmod 777 configure
在 configure 文件中修改編譯腳本設置,新增編譯工具拼接選項(ndk 中交叉編譯工具名稱不同,默認規則拼接后,會出現找不到的情況,解釋如圖):
打開 Vim:
sudo vim configure
輸入 /CMDLINE_SET,按下回車鍵來匹配設置項。找到 cross_prefix,按 i 鍵編輯,新增一行內容:
CMDLINE_SET="
$PATHS_LIST
ar
arch
as
assert_level
build_suffix
cc
objcc
cpu
cross_prefix
# 下面一行內容為新增命令行參數,原文件中沒有
cross_prefix_clang
custom_allocator
cxx
dep_cc
# 省略其他.....
"
按 esc 鍵退出編輯模式,輸入 /ar_default="${cross_prefix}${ar_default}",按下回車鍵來匹配設置項。按 i 鍵鍵入編輯:
# 原內容
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}"
將中間兩行修改為:
# 修改后的內容
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}"
按 esc 鍵退出編輯,輸入 :wq 保存退出。
注釋:Vim 中,按 n(小寫 n) 可以匹配下一個內容,按 shift+n 可以匹配上一個內容。輸入 set nohlsearch(簡寫為:set-noh)來取消文本的高亮。
新增編譯腳本文件:
touch build_android_clang.sh
修改腳本權限:
chmod 777 build_android_clang.sh
編輯腳本:
sudo vim build_android_clang.sh
按 i 鍵編輯,腳本文件內容如下:
#!/bin/bash
set -x # 執行指令后,先顯示該指令及所下的參數。
# 目標Android版本
API=21
CPU=armv7-a
#so庫輸出目錄
OUTPUT=/home/wenchen/android/so/$CPU
# NDK的路徑,根據自己的NDK位置進行設置
NDK=/home/wenchen/android/ndk/ndk-r21e/android-ndk-r21e
# 編譯工具鏈路徑
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
# 編譯環境
SYSROOT=$TOOLCHAIN/sysroot
function build
{
./configure \
--prefix=$OUTPUT \
--target-os=android \
--arch=arm \
--cpu=$CPU \
--enable-asm \
--enable-neon \
--enable-cross-compile \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffplay \
--disable-ffprobe \
--disable-symver \
--disable-ffmpeg \
--sysroot=$SYSROOT \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--cross-prefix-clang=$TOOLCHAIN/bin/armv7a-linux-androideabi$API- \
--extra-cflags="-fPIC"
make clean all
# 這里是定義用幾個CPU編譯
make -j8
make install
}
build
按 esc 鍵退出編輯,輸入 :wq 保存退出。
寫好編譯腳本后,安裝 make 命令:
sudo apt-get install make
執行編譯腳本:
./build_android_clang.sh
關於編譯腳本中的一些說明,可以看看這篇文章。腳本基本上都參考自它。
一路通暢,再也沒有什么報錯。在 so 目錄下,可以找到 include、lib、share 三個目錄,ffmpeg so 就在 lib 目錄下,頭文件在 include 目錄下。
至於編譯多種 CPU 架構的 so,其實搜下 shell 編程 for 循環就會了。