来源于:https://github.com/jcsilva/docker-kaldi-android



Dockerfile:

FROM ubuntu:16.04

RUN mkdir -p /opt/android-sdk-linux && mkdir -p ~/.android && touch ~/.android/repositories.cfg

ENV WORKING_DIR /opt

ENV ANDROID_NDK_HOME ${WORKING_DIR}/android-ndk-linux
ENV ANDROID_TOOLCHAIN_PATH /tmp/my-android-toolchain
ENV PATH ${ANDROID_TOOLCHAIN_PATH}/bin:${PATH}

RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    ca-certificates \
    clang \
    file \
    gfortran \
    git \
    python \
    unzip \
    wget && \
    apt-get clean autoclean && \
    apt-get autoremove -y

##### Install Android toolchain
RUN cd ${WORKING_DIR} && \
    wget -q --output-document=android-ndk.zip https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip && \
    unzip android-ndk.zip && \
    rm -f android-ndk.zip && \
    mv android-ndk-r14b ${ANDROID_NDK_HOME}

RUN ${ANDROID_NDK_HOME}/build/tools/make_standalone_toolchain.py --arch arm --api 21 --stl=libc++ --install-dir ${ANDROID_TOOLCHAIN_PATH}

##### Download, compile and install OpenBlas
RUN cd ${WORKING_DIR} && \
    git clone https://github.com/xianyi/OpenBLAS && \
    cd OpenBLAS && \
    make TARGET=ARMV7 HOSTCC=gcc CC=arm-linux-androideabi-gcc NO_SHARED=1 NOFORTRAN=1 USE_THREAD=0 NUM_THREADS=32 libs && \
    make install NO_SHARED=1 PREFIX=`pwd`/install

##### Download, compile and install CLAPACK
RUN cd ${WORKING_DIR} && \
    git clone https://github.com/simonlynen/android_libs && \
    cd android_libs/lapack && \
    sed -i 's/-mfloat-abi=softfp/-mfloat-abi=hard/g' jni/Application.mk && \
    sed -i 's/LOCAL_MODULE:= testlapack/#LOCAL_MODULE:= testlapack/g' jni/Android.mk && \
    sed -i 's/LOCAL_SRC_FILES:= testclapack.cpp/#LOCAL_SRC_FILES:= testclapack.cpp/g' jni/Android.mk && \
    sed -i 's/LOCAL_STATIC_LIBRARIES := lapack/#LOCAL_STATIC_LIBRARIES := lapack/g' jni/Android.mk && \
    sed -i 's/include $(BUILD_SHARED_LIBRARY)/#include $(BUILD_SHARED_LIBRARY)/g' jni/Android.mk && \
    ${ANDROID_NDK_HOME}/ndk-build && \
    cp obj/local/armeabi-v7a/*.a ${WORKING_DIR}/OpenBLAS/install/lib

##### Compile kaldi
# Using "/opt" because of a bug in Docker:
# https://github.com/docker/docker/issues/25925
COPY ./compile-kaldi.sh /opt

RUN chmod +x /opt/compile-kaldi.sh

ENTRYPOINT ["./opt/compile-kaldi.sh"]

compile-kaldi.sh:

#!/bin/bash

cd ${WORKING_DIR}/kaldi/tools

# tools directory --> we'll only compile OpenFST
OPENFST_VERSION=$(grep -oP "OPENFST_VERSION *= *\K(.*)$" ${WORKING_DIR}/kaldi/tools/Makefile)
wget -T 10 -t 1 http://openfst.cs.nyu.edu/twiki/pub/FST/FstDownload/openfst-${OPENFST_VERSION}.tar.gz
tar -zxvf openfst-${OPENFST_VERSION}.tar.gz
cd openfst-${OPENFST_VERSION}/
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

# source directory
cd ..
ln -s openfst-${OPENFST_VERSION} openfst
cd ../src
CXX=clang++ ./configure --static --android-incdir=${ANDROID_TOOLCHAIN_PATH}/sysroot/usr/include/ --host=arm-linux-androideabi --openblas-root=${WORKING_DIR}/OpenBLAS/install
make clean -j
make depend -j
make -j4




关于生成SO库的说明:

CXX=clang++ ./configure --shared --android-incdir=/home/houwenbin/android-ndk-r14b/sysroot/usr/include/ --host=arm-linux-androideabi --openblas-root=/home/houwenbin/OpenBLAS/install

以为这样就可以了?非也,还是生成了静态库?原因就在于--android-incdir设置项又把动态选项给摁回去了。。。。

  --android-incdir=*)
    android=true;
    threaded_math=false;
    static_math=true;
    static_fst=true;
    dynamic_kaldi=true;//这里需要手动修改为true
    MATHLIB='OPENBLAS';
    ANDROIDINC=`read_dirname $1`;
    shift;;

这样才会生成动态库,创建lib文件夹,以及连接符号:

if $dynamic_kaldi ; then
  KALDILIBDIR=`pwd`/lib
  echo "KALDI_FLAVOR := dynamic" >> kaldi.mk
  echo "KALDILIBDIR := $KALDILIBDIR" >> kaldi.mk
fi

生成的mk文件和Makefile文件:

# This file was generated using the following command:
# ./configure --shared --android-incdir=/home/houwenbin/android-ndk-r14b/sysroot/usr/include/ --host=arm-linux-androideabi --openblas-root=/home/houwenbin/OpenBLAS/install

CONFIGURE_VERSION := 6

# Toolchain configuration

CXX = arm-linux-androideabi-clang++
AR = arm-linux-androideabi-ar
AS = arm-linux-androideabi-as
RANLIB = arm-linux-androideabi-ranlib

# Base configuration

DOUBLE_PRECISION = 0
OPENFSTINC = /home/houwenbin/kaldi-master/tools/openfst/include
OPENFSTLIBS = /home/houwenbin/kaldi-master/tools/openfst/lib/libfst.a
OPENFSTLDFLAGS = 

OPENBLASINC = /home/houwenbin/OpenBLAS/install/include
OPENBLASLIBS = /home/houwenbin/OpenBLAS/install/lib/libopenblas.a /home/houwenbin/OpenBLAS/install/lib/libclapack.a /home/houwenbin/OpenBLAS/install/lib/liblapack.a /home/houwenbin/OpenBLAS/install/lib/libblas.a /home/houwenbin/OpenBLAS/install/lib/libf2c.a
ANDROIDINC = /home/houwenbin/android-ndk-r14b/sysroot/usr/include
# OpenBLAS specific Android configuration

ifndef DOUBLE_PRECISION
$(error DOUBLE_PRECISION not defined.)
endif
ifndef OPENFSTINC
$(error OPENFSTINC not defined.)
endif
ifndef OPENFSTLIBS
$(error OPENFSTLIBS not defined.)
endif
ifndef OPENBLASINC
$(error OPENBLASINC not defined.)
endif
ifndef OPENBLASLIBS
$(error OPENBLASLIBS not defined.)
endif
ifndef ANDROIDINC
$(error ANDROIDINC not defined.)
endif

COMPILER = $(shell $(CXX) -v 2>&1)
ifneq ($(findstring clang,$(COMPILER)),clang)
$(error Android build does not support compiling with $(CXX).
        Supported compilers: clang++)
endif

CXXFLAGS = -std=c++11 -I.. -I$(OPENFSTINC) $(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=hard \
           -mfpu=neon -mhard-float -D_NDK_MATH_NO_SOFTFP=1 -pthread \
           -g # -O0 -DKALDI_PARANOID

ifeq ($(KALDI_FLAVOR), dynamic)
CXXFLAGS += -fPIC
endif

LDFLAGS = $(EXTRA_LDFLAGS) $(OPENFSTLDFLAGS) -Wl,--no-warn-mismatch -pie
LDLIBS = $(EXTRA_LDLIBS) $(OPENFSTLIBS) $(OPENBLASLIBS) -lm_hard -ldl

# Environment configuration

# This is the top-level Makefile for Kaldi.
# Also see kaldi.mk which supplies options and some rules
# used by the Makefiles in the subdirectories.

SHELL := /bin/bash


SUBDIRS = base matrix util feat tree gmm transform \
          fstext hmm lm decoder lat kws cudamatrix nnet \
          bin fstbin gmmbin fgmmbin featbin \
          nnetbin latbin sgmm2 sgmm2bin nnet2 nnet3 chain nnet3bin nnet2bin kwsbin \
          ivector ivectorbin online2 online2bin lmbin chainbin

MEMTESTDIRS = base matrix util feat tree gmm transform \
          fstext hmm lm decoder lat nnet kws chain \
          bin fstbin gmmbin fgmmbin featbin \
          nnetbin latbin sgmm2 nnet2 nnet3 nnet2bin nnet3bin sgmm2bin kwsbin \
          ivector ivectorbin online2 online2bin lmbin

CUDAMEMTESTDIR = cudamatrix

SUBDIRS_LIB = $(filter-out %bin, $(SUBDIRS))

KALDI_SONAME ?= libkaldi.so

# Optional subdirectories
EXT_SUBDIRS = online onlinebin  # python-kaldi-decoding
EXT_SUBDIRS_LIB = $(filter-out %bin, $(EXT_SUBDIRS))

include kaldi.mk

# Reset the default goal, so that the all target will become default
.DEFAULT_GOAL :=
all:
	$(MAKE) checkversion
	$(MAKE) kaldi.mk
	$(MAKE) mklibdir
	$(MAKE) subdirs
	-echo Done

subdirs: $(SUBDIRS)

mklibdir:
	@echo $(KALDILIBDIR)
	test -d $(KALDILIBDIR) || mkdir $(KALDILIBDIR)

#I don't want to call rm -rf
rmlibdir:
ifneq ($(KALDILIBDIR), )
	-rm $(KALDILIBDIR)/*{.so,.a,.o}
	-rmdir $(KALDILIBDIR)
else
	@true
endif

.PHONY: checkversion
checkversion:
ifeq ($(shell ./configure --version),$(CONFIGURE_VERSION))
	@echo "The version of configure script matches kaldi.mk version. Good."
else
	@echo ""
	@echo "The kaldi.mk file was generated using a different version of configure script. Please rerun the configure again"
	@test -f ./kaldi.mk && echo  "Hint: Previous configure command line: " && head -n 2 ./kaldi.mk | grep configure | sed 's/^# *//g'
	@echo ""
	@false
endif

biglib: $(SUBDIRS_LIB)
ifeq ($(KALDI_FLAVOR), dynamic)
ifeq ($(shell uname), Darwin)
	$(CXX) -dynamiclib -o $(KALDILIBDIR)/libkaldi.dylib -install_name @rpath/libkaldi.dylib -framework Accelerate $(LDFLAGS) $(SUBDIRS_LIB:=/*.dylib)
else
ifeq ($(shell uname), Linux)
	#$(warning the following command will probably fail, in that case add -fPIC to your CXXFLAGS and remake all)
	$(CXX) -shared -o $(KALDILIBDIR)/$(KALDI_SONAME) -Wl,-soname=$(KALDI_SONAME),--whole-archive  $(SUBDIRS_LIB:=/kaldi-*.a) $(LDLIBS) -Wl,--no-whole-archive
else
	$(error Dynamic libraries not supported on this platform. Run configure with --static flag. )
endif
endif
endif

biglibext: $(EXT_SUBDIRS_LIB)
ifeq ($(KALDI_FLAVOR), dynamic)
ifeq ($(shell uname), Darwin)
	$(CXX) -dynamiclib -o $(KALDILIBDIR)/libkaldi_ext.dylib -install_name @rpath/libkaldi_ext.dylib -framework Accelerate $(LDFLAGS) $(EXT_SUBDIRS_LIB:=/*.dylib)
else
ifeq ($(shell uname), Linux)
	#$(warning The following command will probably fail, in that case add -fPIC to your CXXFLAGS and remake all.)
	$(CXX) -shared -o $(KALDILIBDIR)/libkaldi_ext.so -Wl,-soname=libkaldi_ext.so,--whole-archive  $(EXT_SUBDIRS_LIB:=/kaldi-*.a) -Wl,--no-whole-archive
else
	$(error Dynamic libraries not supported on this platform. Run configure with --static flag. )
endif
endif
endif

kaldi.mk:
	@[ -f kaldi.mk ] || { echo "kaldi.mk does not exist; you have to run ./configure"; exit 1; }

# Compile optional stuff
ext: ext_depend $(SUBDIRS) $(EXT_SUBDIRS)
	-echo Done

check_portaudio:
	@[ -d ../tools/portaudio ] || ( cd ../tools;  ./install_portaudio.sh )

clean: rmlibdir
	-for x in $(SUBDIRS) $(EXT_SUBDIRS); do $(MAKE) -C $$x clean; done

distclean: clean
	-for x in $(SUBDIRS) $(EXT_SUBDIRS); do $(MAKE) -C $$x distclean; done

test: $(addsuffix /test, $(SUBDIRS_LIB))

ext_test: $(addsuffix /test, $(EXT_SUBDIRS_LIB))

# Define an implicit rule, expands to e.g.:
#  base/test: base
#     $(MAKE) -C base test
%/test: % mklibdir
	$(MAKE) -C $< test

cudavalgrind:
	-for x in $(CUDAMEMTESTDIR); do $(MAKE) -C $$x valgrind || { echo "valgrind on $$x failed"; exit 1; }; done

valgrind:
	-for x in $(MEMTESTDIRS); do $(MAKE) -C $$x valgrind || { echo "valgrind on $$x failed"; exit 1; }; done

base/.depend.mk:
	$(MAKE) depend

depend: $(addsuffix /depend, $(SUBDIRS))

%/depend:
	$(MAKE) -C $(dir $@) depend


ext_depend: check_portaudio
	-for x in $(EXT_SUBDIRS); do $(MAKE) -C $$x depend; done


.PHONY: $(SUBDIRS)
$(SUBDIRS) : mklibdir
	$(MAKE) -C $@

.PHONY: $(EXT_SUBDIRS)
$(EXT_SUBDIRS) : mklibdir ext_depend
	$(MAKE) -C $@


### Dependency list ###
# this is necessary for correct parallel compilation
#1)The tools depend on all the libraries
bin fstbin gmmbin fgmmbin sgmm2bin featbin nnetbin nnet2bin nnet3bin chainbin latbin ivectorbin lmbin kwsbin online2bin: \
 base matrix util feat tree gmm transform sgmm2 fstext hmm \
 lm decoder lat cudamatrix nnet nnet2 nnet3 ivector chain kws online2

#2)The libraries have inter-dependencies
base: base/.depend.mk
matrix: base
util: base matrix
feat: base matrix util gmm transform tree
tree: base util matrix
gmm: base util matrix tree
transform: base util matrix gmm tree
sgmm2: base util matrix gmm tree transform hmm
fstext: base util matrix tree
hmm: base tree matrix util
lm: base util matrix fstext
decoder: base util matrix gmm hmm tree transform lat
lat: base util hmm tree matrix
cudamatrix: base util matrix
nnet: base util hmm tree matrix cudamatrix
nnet2: base util matrix lat gmm hmm tree transform cudamatrix
nnet3: base util matrix lat gmm hmm tree transform cudamatrix chain fstext
chain: lat hmm tree fstext matrix cudamatrix util base
ivector: base util matrix transform tree gmm
#3)Dependencies for optional parts of Kaldi
onlinebin: base matrix util feat tree gmm transform sgmm2 fstext hmm lm decoder lat cudamatrix nnet nnet2 online
# python-kaldi-decoding: base matrix util feat tree gmm transform sgmm2 fstext hmm decoder lat online
online: decoder gmm transform feat matrix util base lat hmm tree
online2: decoder gmm transform feat matrix util base lat hmm tree ivector cudamatrix nnet2 nnet3 chain
kws: base util hmm tree matrix lat

Logo

更多推荐