本文档涉及到的目标硬件为海思3516D,但是对其他Arm芯片也有一定的借鉴意义,只需要更换交叉编译链即可。因为Caffe的编译需要使用开启C++11,所以GCC版本需要大于等于4.8才可以正常进行编译
参考文档
开发环境介绍
主机操作系统:Ubuntu14.04 64位
目标板硬件:海思3516D
交叉编译器:arm-hisiv400-linux,海思提供的定制GCC 4.8.3交叉编译工具
编译注意事项
为了使Caffe部署时的体积最小化,需要如下几个注意事项
- Caffe的ARM编译只涉及到最后的推理部署,所以建议关闭lmdb、leveldb、snappy和opencv的编译
- Caffe及其依赖库都编译成静态库的版本,编译静态库时都要添加-ffunction-sections -fdata-sections的编译选项
- 在测试工程链接Caffe及其依赖库的时候,添加链接选项-Wl,--gc-sections(用于扔掉没有用到的静态库函数)
- 裁剪最后生成的可执行文件,通过arm-hisiv400-linux-gnueabi-strip命令
设置交叉编译链
# 在/etc/bash.bashrc的最后增加如下指令
# HISI Hi3516D V400 cross compiler
export ARCH=arm
export PATH=/opt/arm-hisiv400-linux/bin/:$PATH
export CROSS_COMPILE=arm-hisiv400-linux-gnueabi-
export CC=/opt/arm-hisiv400-linux/bin/arm-hisiv400-linux-gnueabi-gcc
export CXX=/opt/arm-hisiv400-linux/bin/arm-hisiv400-linux-gnueabi-g++
export LD=/opt/arm-hisiv400-linux/bin/arm-hisiv400-linux-gnueabi-ld
export AR=/opt/arm-hisiv400-linux/bin/arm-hisiv400-linux-gnueabi-ar
export AS=/opt/arm-hisiv400-linux/bin/arm-hisiv400-linux-gnueabi-as
export RANLIB=/opt/arm-hisiv400-linux/bin/arm-hisiv400-linux-gnueabi-ranlib
# 修改完成之后需要重启命令行才能生效
# 你可以通过如下指令来确认交叉编译链是否已经设置好
echo $CC
# 当显示/arm-hisiv400-linux/bin/arm-hisiv400-linux-gnueabi-gcc时表示交叉编译链已经设置好
# 当需要更换为本机编译时屏蔽上面的指令即可
下载依赖库
依赖库 | 版本 | 下载地址 |
---|---|---|
glog | 0.3.5 | https://github.com/google/glog |
gflags | 2.2.1 | https://github.com/gflags/gflags |
opencv | 3.2.0 | https://github.com/opencv/opencv |
protobuf | 3.2.0 | https://github.com/google/protobuf |
openblas | 0.2.20 | https://github.com/xianyi/OpenBLAS |
hdf5 | 5.1.8.20 | https://support.hdfgroup.org/downloads/index.html |
boost | 1.59.0 | http://www.boost.org/ |
在这里提供了所有依赖库的源代码打包下载地址:https://pan.baidu.com/s/1bp2OgNl
编译Opencv
修改CMakeLists.txt
# 强制打开NEON开关
# OCV_OPTION(ENABLE_NEON "Enable NEON instructions" "${NEON}" IF CMAKE_COMPILER_IS_GNUCXX AND (ARM OR AARCH64 OR IOS) )
OCV_OPTION(ENABLE_NEON "Enable NEON instructions" ON )
修改cmake/OpenCVCompilerOptions.cmake
# 将ENABLE_NEON开启之后的gcc参数修改为海思3516D推荐的参数"-mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=softfp"
if(ENABLE_NEON)
add_extra_compiler_option("-mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=softfp")
新建cmake Build目录
cd opencv-3.2.0
mkdir _install
使用cmake-gui进行配置
选择Specify options for cross-compiling,进入交叉编译链设置界面
# 设置交叉编译相关参数
# 本文使用的是海思3516D SDK 提供的 V400 工具链,存放位置为/opt/arm-hisiv400-linux/(更改为你正在使用的目录)
# 设置Operating System 为 arm-linux
# 设置C编译器为 /opt/arm-hisiv400-linux/bin/arm-hisiv400-linux-gnueabi-gcc
# 设置C++编译器为 /opt/arm-hisiv400-linux/bin/arm-hisiv400-linux-gnueabi-g++
# 设置System Root 为 /opt/arm-hisiv400-linux/target
点击Configure生成配置选项,并且打开Advancd选项
修改设置选项:
# 去掉勾选为FLASE 勾选为TRUE
BUILD_SHARED_LIBS # FLASE为编译静态库 TRUE为编译动态库
CMAKE_BUILD_TYPE # Release
CMAKE_CXX_FLAGS # -fPIC
CMAKE_C_FLAGS # -fPIC
CMAKE_EXE_LINKER_FLAGS # -lrt -lpthread
CMAKE_INSTALL_PREFIX # 自定义安装目录
WITH_CUDA # FLASE 禁用CUDA
WITH_CUFFT # FLASE 禁用CUFFT
WITH_EIGEN # FLASE 禁用EIGEN
WITH_FFMPEG # FLASE 禁用FFMPEG
WITH_OPENCL # FLASE 禁用OPENCL
WITH_OPENCLAMDBLAS # FLASE 禁用OPENCLAMDBLAS
WITH_OPENCLAMDFFT # FLASE 禁用OPENCLAMDFFT
WITH_OPENCL_SVM # FLASE 禁用OPENCL_SVM
# 可选配置(根据需要进行配置)
WITH_TIFF
WITH_1394
WITH_GSTREAMER
WITH_JASPER
WITH_LAPACK
WITH_MATLAB
WITH_WEBP
修改第三库CMakeLists.txt
# 如果你在上述的Cmake GUI界面开启了PNG的编译并且没有强制开启ENABLE_NEON选项,即
EWITH_PNG # TRUE 开启PNG
编译Opencv时将会出现如下链接错误(可能是Opencv3.2版本专有的Bug):
libopencv_imgcodecs.so: undefined reference to `png_init_filter_functions_neon'
解决方法如下:
进入到3rdparty/libpng,在CMakeLists.txt最顶端增加:
set(ENABLE_NEON ON)
点击Generate生成Makefile
进入_install目录&编译
cd _install
make -j8
make install
编译Glog
cd glog-0.3.5
./configure --host=arm-linux CFLAGS="-ffunction-sections -fdata-sections -O2 -fPIC" \
CXXFLAGS="-ffunction-sections -fdata-sections -O2 -fPIC" \
--prefix=/usr/local/HI3516D/v400/glog-0.3.5
make -j8
make install
编译gflags
新建cmake Build目录
cd gflags-2.2.1
mkdir _install
使用cmake-gui进行配置
参考编译opencv时的cmake交叉工具链配置
# 修改Cmake设置选项
CMAKE_INSTALL_PREFIX # 自定义安装目录
CMAKE_C_FLAGS -fPIC
CMAKE_CXX_FLAGS -fPIC
点击Generate生成Makefile
编译&安装
cd _install
make -j8
make install
编译Protobuf
安装软件
sudo apt-get install curl libtool
生成PC版本protoc可执行文件,供编译ARM版本库时使用
# 修改/etc/bash.bashrc 设置为CC/CXX/LD为普通gcc编译器
cd protobuf-3.2.0
./autoconf.sh
./configure --prefix=/usr/local/PC/protobuf-3.2.0
编译ARM版本
# 修改/etc/bash.bashrc 设置为CC/CXX/LD为交叉编译器
cd protobuf-3.2.0
./autoconf.sh
./configure --build=i686-pc-linux --host=arm-linux \
--with-protoc=/usr/local/PC/protobuf-3.2.0/bin/protoc \
--prefix=/usr/local/HI3516D/v400/protobuf-3.2.0 CFLAGS="-fPIC" CXXFLAGS="-fPIC -DNDEBUG"
编译&安装
make -j8
make install
编译OpenBLAS
修改Makefile.arm
# 根据你的ARM处理器版本和操作系统修改对应的CCOMMON_OPT和FCOMMON_OPT
# 本文档针对的是HI3516D,属于armv7架构
ifeq ($(CORE), $(filter $(CORE),ARMV7 CORTEXA9 CORTEXA15))
ifeq ($(OSNAME), Android)
CCOMMON_OPT += -mfpu=neon -march=armv7-a
FCOMMON_OPT += -mfpu=neon -march=armv7-a
else
# CCOMMON_OPT += -mfpu=neon -march=armv7-a
# FCOMMON_OPT += -mfpu=neon -march=armv7-a
CCOMMON_OPT += -ffunction-sections -fdata-sections -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=softfp
FCOMMON_OPT += -ffunction-sections -fdata-sections -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=softfp
endif
endif
编译
cd OpenBLAS-0.2.20
# 编译单独的静态库版本
make TARGET=ARMV7 HOSTCC=gcc CROSS=1 CROSS_SUFFIX=arm-hisiv400-linux-gnueabi- BINARY=32 NOFORTRAN=1 libs -j8
# 编译动态库版本
make TARGET=ARMV7 HOSTCC=gcc CROSS=1 CROSS_SUFFIX=arm-hisiv400-linux-gnueabi- BINARY=32 NOFORTRAN=1 libs shared
# 另附上ARMV8芯片的编译命令以供参考
make TARGET=ARMV8 HOSTCC=gcc CROSS=1 CROSS_SUFFIX=aarch64-linux-gnu- BINARY=64 NOFORTRAN=1 libs -j8
make TARGET=ARMV8 HOSTCC=gcc CROSS=1 CROSS_SUFFIX=aarch64-linux-gnu- BINARY=64 NOFORTRAN=1 libs shared -j8
安装
# PREFIX使用您自己的自定义安装目录
make PREFIX=/usr/local/HI3516D/v400/openBLAS-0.2.20 install
编译HDF5
生成H5detect和H5make_libsettings
生成H5Tinit.c和H5lib_settings.c
修改configure文件
# 屏蔽掉所有和交叉编译验证相关的步骤
# 搜索cannot run test program while cross compiling获得具体校验代码位置(共四处)
if test "$cross_compiling" = yes; then :
# { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
# $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
# as_fn_error $? "cannot run test program while cross compiling
# See \`config.log' for more details" "$LINENO" 5; }
else
# 执行配置
./configure --host=arm-linux --prefix=/usr/local/HI3516D/v400/hdf5-1.8.20 CFLAGS="-ffunction-sections -fdata-sections -O2" CXXFLAGS="-ffunction-sections -fdata-sections -O2"
修改Makefile
# 屏蔽掉和H5Tinit.c、H5lib_settings.c生成相关的Makefile代码
H5Tinit.c: H5detect$(EXEEXT)
# LD_LIBRARY_PATH="$$LD_LIBRARY_PATH`echo $(LDFLAGS) | \
sed -e 's/-L/:/g' -e 's/ //g'`" \
$(RUNSERIAL) ./H5detect$(EXEEXT) > $@ || \
(test $$HDF5_Make_Ignore && echo "*** Error ignored") || \
($(RM) $@ ; exit 1)
H5lib_settings.c: H5make_libsettings$(EXEEXT) libhdf5.settings
# LD_LIBRARY_PATH="$$LD_LIBRARY_PATH`echo $(LDFLAGS) | \
sed -e 's/-L/:/g' -e 's/ //g'`" \
$(RUNSERIAL) ./H5make_libsettings$(EXEEXT) > $@ || \
(test $$HDF5_Make_Ignore && echo "*** Error ignored") || \
($(RM) $@ ; exit 1)
编译&安装
make
make install
编译Boost
生成编译脚本
cd boost_1_59_0
./bootstrap.sh --prefix=/usr/local/HI3516D/v400/boost-1.59.0
修改编译脚本project-config.jam
if ! gcc in [ feature.values <toolset> ]
{
using gcc : arm : arm-hisiv400-linux-gnueabi-gcc ; # 注意中间的多处空格
}
编译&生成
./bjam install toolset=gcc-arm --layout=togged --build-type=complete --prefix=/usr/local/HI3516D/v400/boost-1.59.0
编译Caffe
修改Makefile和Makefile.config
#
编译&生成
#
make all
#
make all -j8
make install