Mac 下編譯 Kaldi Android (arm) .so 庫(kù)

話說(shuō)之前公司里面一直用到的是 PocketSphinx , 但是在新的項(xiàng)目中有一個(gè)應(yīng)用的場(chǎng)景汇歹,這時(shí)候發(fā)現(xiàn)噪聲影響以及識(shí)別的精確度方面都不是很理想刽射。于是在 Telegram Channel 里面咨詢了下苍鲜,@nshmyrev 回復(fù)建議可以利用 Kaldi DNN 模型,應(yīng)該會(huì)有顯著提升。于是考慮轉(zhuǎn)向研究 Kaldi蚁趁。

首先碰到的一個(gè)問(wèn)題是跨平臺(tái)編譯。網(wǎng)上搜索后發(fā)現(xiàn)泄鹏,被引用最多的一篇文章(下文簡(jiǎn)稱“編譯指南”)是 compile-kaldi-android郎任,但它是基于 Ubuntu 環(huán)境來(lái)編譯的,也看到了編譯 Kaldi 可用的 docker file备籽。但是在Mac環(huán)境下又可以怎樣成功編譯呢舶治?讓我們分解來(lái)看:

1. 配置Android NDK 以及 獨(dú)立的編譯 toolchain

這部分和編譯指南中的大體一致,對(duì)不同的平臺(tái)车猬,沒有NDK的需要相應(yīng)的下載霉猛,并且配置ANDROID_NDK 路徑。

安裝 toolchain :

$ANDROID_NDK/build/tools/make_standalone_toolchain.py --arch arm --api 21 --stl=libc++ --install-dir /tmp/my-android-toolchain

以上命令創(chuàng)建 /tmp/my-android-toolchain/ 文件目錄珠闰,并且已經(jīng)包含了 android-21/arch-arm sysroot韩脏,以及32位 ARM 架構(gòu)的工具鏈可執(zhí)行文件等。

將 toolchain 加入到系統(tǒng) PATH中:

export ANDROID_TOOLCHAIN_PATH=/tmp/my-android-toolchain
export PATH=${ANDROID_TOOLCHAIN_PATH}/bin:$PATH

2. 編譯 Android 版本的 OpenBLAS

注:考慮到 gfortran 已經(jīng)是GCC的一部分了铸磅,可以選擇性安裝 gfortran赡矢。

下載源碼:

git clone https://github.com/xianyi/OpenBLAS

選擇 ARMV7 進(jìn)行編譯:

make \
    TARGET=ARMV7 \
    ONLY_CBLAS=1 \
    CC=$ANDROID_TOOLCHAIN_PATH/bin/arm-linux-androideabi-clang \
    AR=$ANDROID_TOOLCHAIN_PATH/bin/arm-linux-androideabi-ar \
    HOSTCC=gcc \
    ARM_SOFTFP_ABI=1 \
    -j4

此處與編譯指南中有所不同,如果按它上面的操作阅仔,會(huì)報(bào)出 找不到"crtbegin_so"之類的錯(cuò)誤吹散。

安裝庫(kù)文件

make install NO_SHARED=1 PREFIX=`pwd`/install

3. 編譯 CLAPACK

git clone https://github.com/simonlynen/android_libs.git

cd android_libs/lapack

打開 jni/Android.mk, 注釋掉測(cè)試相關(guān)的編譯指令

# remove some compile instructions related to tests

# LOCAL_MODULE:= testlapack
# LOCAL_SRC_FILES:= testclapack.cpp
# LOCAL_STATIC_LIBRARIES := lapack
# include $(BUILD_SHARED_LIBRARY)

打開 jni/Application.mk

APP_STL := gnustl_static 替換為 APP_STL := c++_shared
APP_ABI := armeabi armeabi-v7a 替換為 APP_ABI := armeabi-v7a。armeabi 已經(jīng)不再支持了八酒。
文件最后增加 NDK_TOOLCHAIN_VERSION := clang

編譯

$ANDROID_NDK/ndk-build

編譯完成后會(huì)在 obj/local/armeabi-v7a/生成庫(kù)文件空民。將生成的庫(kù)文件拷貝到前面你安裝OpenBLAS庫(kù)文件的目錄下(e.g: OpenBlas/install/lib)。Kaldi 將會(huì)在這個(gè)目錄下查找相關(guān)的依賴項(xiàng)羞迷。

4. 編譯 Kaldi

下載源碼

git clone https://github.com/kaldi-asr/kaldi.git

編譯 OpenFST
查看當(dāng)前的kaldi tools/Makefile 后發(fā)現(xiàn)使用的版本是OpenFST-1.6.7界轩。

cd kaldi/tools
wget -T 10 -t 1 http://www.openfst.org/twiki/pub/FST/FstDownload/openfst-1.6.7.tar.gz
tar -zxvf openfst-1.6.7.tar.gz

cd openfst-1.6.7/

CXX=clang++ ./configure --prefix=`pwd` --enable-static --enable-shared --enable-far --enable-ngram-fsts --host=arm-linux-androideabi LIBS="-ldl"

make -j 4

make install

cd ..

ln -s openfst-1.6.5 openfst

編譯源碼

cd ../src

打開 matrix/Makefile 文件,將其中的測(cè)試文件注釋掉(似乎與Clang8.0有關(guān)的bug)衔瓮。

#TESTFILES = matrix-lib-test sparse-matrix-test #matrix-lib-speed-tes
CXX=clang++ ./configure --static --android-incdir=/tmp/my-android-toolchain/sysroot/usr/include/ --host=arm-linux-androideabi --openblas-root=/path/to/OpenBLAS/install

make clean -j

make depend -j

make -j 4

按上述配置已經(jīng)可以生成所有的靜態(tài)鏈接庫(kù) .a 文件了浊猾,它們分別位于 src 下的各個(gè)子目錄中:

.//tree/kaldi-tree.a
.//gmm/kaldi-gmm.a
.//online2/kaldi-online2.a
.//util/kaldi-util.a
.//feat/kaldi-feat.a
.//lm/kaldi-lm.a
.//sgmm2/kaldi-sgmm2.a
.//rnnlm/kaldi-rnnlm.a
.//nnet/kaldi-nnet.a
.//decoder/kaldi-decoder.a
.//nnet2/kaldi-nnet2.a
.//chain/kaldi-chain.a
.//nnet3/kaldi-nnet3.a
.//cudamatrix/kaldi-cudamatrix.a
.//ivector/kaldi-ivector.a
.//kws/kaldi-kws.a
.//hmm/kaldi-hmm.a
.//lat/kaldi-lat.a
.//fstext/kaldi-fstext.a
.//transform/kaldi-transform.a
.//matrix/kaldi-matrix.a
.//base/kaldi-base.a

等等,說(shuō)好的.so文件在哪呢 热鞍?

P.S.

  • 打開 kaldi/src/configure 文件葫慎,將
--android-incdir=*)
    android=true;
    threaded_math=false;
    static_math=true;
    static_fst=true;
    dynamic_kaldi=false;
    MATHLIB='OPENBLAS';

其中的 dynamic_kaldi=false 改為 dynamic_kaldi=true

  • 更新 configure薇宠,指明庫(kù)類型為 --shared:
CXX=clang++ ./configure --shared --android-incdir=/tmp/my-android-toolchain/sysroot/usr/include/ --host=arm-linux-androideabi --openblas-root=/path/to/OpenBLAS/install
  • 編譯kaldi過(guò)程中除去 debugging symbols, 打開 src/kaldi.mk 修改其中的CXXFLAGS 為:
CXXFLAGS = -std=c++11 -I.. -I$(OPENFSTINC) -O1 $(EXTRA_CXXFLAGS) \
           -Wall -Wno-sign-compare -Wno-unused-local-typedefs \
           -Wno-deprecated-declarations -Winit-self -Wno-mismatched-tags \
           -DKALDI_DOUBLEPRECISION=$(DOUBLE_PRECISION) \
           -DHAVE_CXXABI_H -DHAVE_OPENBLAS -DANDROID_BUILD \
           -I$(OPENBLASINC) -I$(ANDROIDINC) -ftree-vectorize -mfloat-abi=softfp \
           -mfpu=neon -pthread \
           -O3 -DNDEBUG
        #    -g # -O0 -DKALDI_PARANOID
  • (已提交PR偷办,最新源碼已修復(fù)) 打開 src/makefiles/default_rules.mk,將第4行起按平臺(tái)類型進(jìn)行配置的部分替換為:
ifeq ($(KALDI_FLAVOR), dynamic)
  ifdef LIBNAME
      LIBFILE = lib$(LIBNAME).so
  endif
  LDFLAGS += -Wl,-rpath -Wl,$(KALDILIBDIR)
  EXTRA_LDLIBS += $(foreach dep,$(ADDLIBS), $(dir $(dep))$(notdir $(basename $(dep))).a)

  XDEPENDS =
else
  ifdef LIBNAME
    LIBFILE = $(LIBNAME).a
  endif
  XDEPENDS = $(ADDLIBS)
endif

具體原因在于澄港,src下各個(gè)部分編譯動(dòng)態(tài)鏈接庫(kù)時(shí)需要區(qū)分不同的平臺(tái)類型椒涯,而 Makefile 中直接根據(jù) shell 環(huán)境下 uname 返回的值來(lái)判定的。而這在跨平臺(tái)編譯時(shí)是不夠充分的回梧,此時(shí)的 host=arm-linux-androideabi废岂,不能以Mac下的動(dòng)態(tài)鏈接庫(kù)的條件直接判定铡溪,否則會(huì)出現(xiàn)動(dòng)態(tài)鏈接庫(kù)不匹配的問(wèn)題 :

clang80++: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [libkaldi-matrix.dylib] Error 1
  • 重新編譯即可,生成的so文件可在 src/lib/下找到泪喊。
make -j clean depend; make -j 4

5. 后記

這次解決跨平臺(tái)的編譯問(wèn)題將近花了4天的時(shí)間棕硫,故記錄整個(gè)過(guò)程,希望對(duì)后來(lái)嘗試編譯的人有所啟示袒啼。在這期間非常感謝 compile-kaldi-android的指引, @funcwj 在微信上的交流哈扮, google group kaldi-help論壇上面大家的熱心回復(fù)。

6. 引用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蚓再,一起剝皮案震驚了整個(gè)濱河市滑肉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌摘仅,老刑警劉巖靶庙,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異娃属,居然都是意外死亡六荒,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門矾端,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)掏击,“玉大人,你說(shuō)我怎么就攤上這事秩铆⊙馔ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵殴玛,是天一觀的道長(zhǎng)捅膘。 經(jīng)常有香客問(wèn)我,道長(zhǎng)滚粟,這世上最難降的妖魔是什么寻仗? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮坦刀,結(jié)果婚禮上愧沟,老公的妹妹穿的比我還像新娘。我一直安慰自己鲤遥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布林艘。 她就那樣靜靜地躺著盖奈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狐援。 梳的紋絲不亂的頭發(fā)上钢坦,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天究孕,我揣著相機(jī)與錄音,去河邊找鬼爹凹。 笑死厨诸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的禾酱。 我是一名探鬼主播微酬,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼颤陶!你這毒婦竟也來(lái)了颗管?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤滓走,失蹤者是張志新(化名)和其女友劉穎垦江,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體搅方,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡比吭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了姨涡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梗逮。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绣溜,靈堂內(nèi)的尸體忽然破棺而出慷彤,到底是詐尸還是另有隱情,我是刑警寧澤怖喻,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布底哗,位于F島的核電站,受9級(jí)特大地震影響锚沸,放射性物質(zhì)發(fā)生泄漏跋选。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一哗蜈、第九天 我趴在偏房一處隱蔽的房頂上張望前标。 院中可真熱鬧,春花似錦距潘、人聲如沸炼列。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)俭尖。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間稽犁,已是汗流浹背焰望。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留已亥,地道東北人熊赖。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像虑椎,于是被迫代替她去往敵國(guó)和親震鹉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 說(shuō)明 這只是筆記绣檬。足陨。。娇未。墨缘。。零抬。镊讼。 從0開始搭建測(cè)試環(huán)境 下載android ndk ,然后配置ndk環(huán)境變量,使n...
    吉兇以情遷閱讀 5,117評(píng)論 0 3
  • Android游戲開發(fā)實(shí)踐(1)之NDK與JNI開發(fā)02 承接上篇Android游戲開發(fā)實(shí)踐(1)之NDK與JNI...
    AlphaGL閱讀 3,754評(píng)論 0 24
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 2,696評(píng)論 0 3
  • 今天突然想聽民謠平夜,于是把高曉松2012年的全國(guó)巡回演唱會(huì)找出來(lái)看蝶棋。 老狼,葉蓓忽妒,小柯玩裙,鄭鈞… 白衣飄飄的年代… 睡...
    四姐和悅女王閱讀 575評(píng)論 0 2
  • 視覺筆記,是我上個(gè)月才知道的一種記錄方式段直,它可以用來(lái)做會(huì)議記錄吃溅、讀書筆記、生活瑣事等鸯檬,從知道的那一刻就喜歡上了它决侈,...
    婉珊1219閱讀 92評(píng)論 0 0