移植opencv3.1.0到hi3516a

移植opencv3.1.0到hi3516a

参考文章:

http://stackoverflow.com/questions/14810135/erro-while-cross-compile-opencv-program-for-arm

http://blog.csdn.net/pangdegui/article/details/42716829

http://www.cnblogs.com/rickyk/p/3875334.html

https://cmake.org/cmake-tutorial/

https://cmake.org/Wiki/CMake_Cross_Compiling

一、交叉编译opencv3.1.0

1、修改cmake文件
在源码的platforms下已经有对各平台的交叉编译支持,我们只需要做一些简单的修改。

[zzz@localhost platforms]$ pwd
/home/zzz/software/opencv-3.1.0/platforms
[zzz@localhost platforms]$ ll
total 28
drwxr-xr-x. 4 zzz zzz 4096 Dec 18 23:02 android
drwxr-xr-x. 3 zzz zzz 4096 Dec 18 23:02 ios
drwxr-xr-x. 4 zzz zzz 4096 Jan 22 17:24 linux
drwxr-xr-x. 2 zzz zzz 4096 Dec 18 23:02 osx
-rw-r--r--. 1 zzz zzz  323 Dec 18 23:02 readme.txt
drwxr-xr-x. 2 zzz zzz 4096 Dec 18 23:02 scripts
drwxr-xr-x. 2 zzz zzz 4096 Dec 18 23:02 winrt

我们的目标是交叉编译到arm上,那么就进入到linux下:

[zzz@localhost linux]$ pwd
/home/zzz/software/opencv-3.1.0/platforms/linux
[zzz@localhost linux]$ ll
total 20
-rw-r--r--.  1 zzz zzz 4196 Jan 22 16:35 arm-gnueabi.toolchain.cmake
...

arm-gnueabi.toolchain.cmake指明了交叉编译的一些路径等设置,我们根据实际情况对其进行适当修改:

set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_VERSION 1) set(CMAKE_SYSTEM_PROCESSOR arm-hisiv300-linux-gnueabi) set(GCC_COMPILER_VERSION "4.6" CACHE STRING "GCC Compiler version") set(FLOAT_ABI_SUFFIX "") if (NOT SOFTFP) set(FLOAT_ABI_SUFFIX "hf") endif() #CROSS COMPILE SETTING set(TOOLCHAIN_DIR "/opt/hisi-linux/x86-arm/arm-hisiv300-linux/") set(CMAKE_C_COMPILER "/opt/hisi-linux/x86-arm/arm-hisiv300-linux/bin/arm-hisiv300-linux-uclibcgnueabi-gcc") set(CMAKE_CXX_COMPILER "/opt/hisi-linux/x86-arm/arm-hisiv300-linux/bin/arm-hisiv300-linux-uclibcgnueabi-g++") set(CMAKE_FIND_ROOT_PATH /opt/hisi-linux/ /opt/hisi-linux/x86-arm/arm-hisiv300-linux/) set(ARM_LINUX_SYSROOT /opt/hisi-linux/x86-arm/arm-hisiv300-linux/ CACHE PATH "ARM cross compile system root") MESSAGE(STATUS "This is cross compile dir --->"$(CMAKE_C_COMPILER)) #find_program(CMAKE_C_COMPILER NAMES arm-linux-gnueabi${FLOAT_ABI_SUFFIX}-gcc-${GCC_COMPILER_VERSION}) #find_program(CMAKE_CXX_COMPILER NAMES arm-linux-gnueabi${FLOAT_ABI_SUFFIX}-g++-${GCC_COMPILER_VERSION}) #set(ARM_LINUX_SYSROOT /usr/arm-linux-gnueabi${FLOAT_ABI_SUFFIX} CACHE PATH "ARM cross compilation system root") #set(CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags") #set(CMAKE_C_FLAGS "" CACHE STRING "c flags") #set(CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags") #set(CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags") #set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi") set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now ${CMAKE_SHARED_LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now ${CMAKE_MODULE_LINKER_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now ${CMAKE_EXE_LINKER_FLAGS}") if(USE_NEON) message(WARNING "You use obsolete variable USE_NEON to enable NEON instruction set. Use -DENABLE_NEON=ON instead." ) set(ENABLE_NEON TRUE) elseif(USE_VFPV3) message(WARNING "You use obsolete variable USE_VFPV3 to enable VFPV3 instruction set. Use -DENABLE_VFPV3=ON instead." ) set(ENABLE_VFPV3 TRUE) endif() #set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${ARM_LINUX_SYSROOT}) if(EXISTS ${CUDA_TOOLKIT_ROOT_DIR}) set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${CUDA_TOOLKIT_ROOT_DIR}) endif() set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." ) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) # macro to find programs on the host OS macro( find_host_program ) set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) if( CMAKE_HOST_WIN32 ) SET( WIN32 1 ) SET( UNIX ) elseif( CMAKE_HOST_APPLE ) SET( APPLE 1 ) SET( UNIX ) endif() find_program( ${ARGN} ) SET( WIN32 ) SET( APPLE ) SET( UNIX 1 ) set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) endmacro() # macro to find packages on the host OS macro( find_host_package ) set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) if( CMAKE_HOST_WIN32 ) SET( WIN32 1 ) SET( UNIX ) elseif( CMAKE_HOST_APPLE ) SET( APPLE 1 ) SET( UNIX ) endif() find_package( ${ARGN} ) SET( WIN32 ) SET( APPLE ) SET( UNIX 1 ) set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) endmacro() 

2、交叉编译
设置好了以后,开始进行交叉编译:
建立好执行cmake的路径:build_softfp,建立好编译后的安装路径:install_dir

[zzz@localhost linux]$ ll
total 20
-rw-r--r--.  1 zzz zzz 4196 Jan 22 16:35 arm-gnueabi.toolchain.cmake
drwxrwxr-x. 15 zzz zzz 4096 Jan 22 16:38 build_softfp
drwxrwxr-x.  6 zzz zzz 4096 Jan 22 15:51 install_dir

执行:

[zzz@localhost build_softfp]$ pwd
/home/zzz/software/opencv-3.1.0/platforms/linux/build_softfp
[zzz@localhost build_softfp]$ cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=../install_dir/ -D SOFTFP=ON -D ENABLE_NEON=ON -D CMAKE_TOOLCHAIN_FILE=../arm-gnueabi.toolchain.cmake ../../../

等待10几分钟。

二、编写测试程序

1、程序内容
简单测试对图片的加载:

#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;
int main(int argc,char* argv[]){

    string path="/home/zzz/facedata/lena.jpg";


     Mat image = imread( path, 1 );

     if(image.isContinuous()){
         cout<<"read picture successfully!"<<endl;
     }else{
         cout<<"fail to read picture!"<<endl;
     }

     return 0;

}

2、编译
CMakeLists.txt:

# this is required
set(CMAKE_SYSTEM_NAME Linux)

set(CMAKE_FIND_ROOT_PATH /opt/hisi-linux/ /opt/hisi-linux/x86-arm/arm-hisiv300-linux/)
set(ARM_LINUX_SYSROOT /opt/hisi-linux/x86-arm/arm-hisiv300-linux/ CACHE PATH "ARM cross compile system root")


# search for programs in the build host directories (not necessary)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

set(TOOLCHAIN_DIR "/opt/hisi-linux/x86-arm/arm-hisiv300-linux/")

set(CMAKE_C_COMPILER "/opt/hisi-linux/x86-arm/arm-hisiv300-linux/bin/arm-hisiv300-linux-uclibcgnueabi-gcc")
set(CMAKE_CXX_COMPILER "/opt/hisi-linux/x86-arm/arm-hisiv300-linux/bin/arm-hisiv300-linux-uclibcgnueabi-g++")


set(CMAKE_VERBOSE_MAKEFILE ON)


cmake_minimum_required(VERSION 2.8)
project( LoadImage )


set(OpenCV_DIR /home/zzz/software/opencv-3.1.0/platforms/linux/build_softfp/)
include_directories(/home/zzz/software/opencv-3.1.0/platforms/linux/install_dir/include)

#set(OpenCV_DIR /home/zzz/software/opencv-2.4.9/release)
#include_directories(/home/zzz/software/opencv-2.4.9/build/include)

find_package( OpenCV REQUIRED )
add_executable( LoadImage LoadImage.cpp )
target_link_libraries( LoadImage ${OpenCV_LIBS} )

可以把上半部分的内容抽取出来,作为交叉编译的指示文件:

# this is required
set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_FIND_ROOT_PATH /opt/hisi-linux/ /opt/hisi-linux/x86-arm/arm-hisiv300-linux/) set(ARM_LINUX_SYSROOT /opt/hisi-linux/x86-arm/arm-hisiv300-linux/ CACHE PATH "ARM cross compile system root") # search for programs in the build host directories (not necessary) SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # for libraries and headers in the target directories SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(TOOLCHAIN_DIR "/opt/hisi-linux/x86-arm/arm-hisiv300-linux/") set(CMAKE_C_COMPILER "/opt/hisi-linux/x86-arm/arm-hisiv300-linux/bin/arm-hisiv300-linux-uclibcgnueabi-gcc") set(CMAKE_CXX_COMPILER "/opt/hisi-linux/x86-arm/arm-hisiv300-linux/bin/arm-hisiv300-linux-uclibcgnueabi-g++") set(CMAKE_VERBOSE_MAKEFILE ON) 

执行如下:

[zzz@localhost basictest]$ cmake .
-- The C compiler identification is GNU 4.8.3 -- The CXX compiler identification is GNU 4.8.3 -- Check for working C compiler: /opt/hisi-linux/x86-arm/arm-hisiv300-linux/bin/arm-hisiv300-linux-uclibcgnueabi-gcc -- Check for working C compiler: /opt/hisi-linux/x86-arm/arm-hisiv300-linux/bin/arm-hisiv300-linux-uclibcgnueabi-gcc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working CXX compiler: /opt/hisi-linux/x86-arm/arm-hisiv300-linux/bin/arm-hisiv300-linux-uclibcgnueabi-g++ -- Check for working CXX compiler: /opt/hisi-linux/x86-arm/arm-hisiv300-linux/bin/arm-hisiv300-linux-uclibcgnueabi-g++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Configuring done -- Generating done -- Build files have been written to: /home/zzz/workspace/arm-opencv3.1.0/src/basictest [zzz@localhost basictest]$ make
Scanning dependencies of target LoadImage
[100%] Building CXX object CMakeFiles/LoadImage.dir/LoadImage.cpp.o
Linking CXX executable LoadImage
[100%] Built target LoadImage
[zzz@localhost basictest]$ 

三、在板上运行
需要设置好LD_LIBRARY_PATH,使其也指向一开始生成的opencv的库文件路径,或者直接将这些库拷贝到LD_LIBRARY_PATH指定的当前路径中。

四、问题
一开始没有设定好cmake的交叉编译设置,导致在编译测试程序的时候,使用的是系统的c++编译器在编译链接,结果提示无法读取opencv的so的符号等。所以对cmake的设置要在实践中慢慢掌握全面一些。

后记(2016-1-28):
由于使用的板子有浮点运算单元以及neon,但是上面的编译脚本没有使用相关的参数,包括编译opencv的库以及编译自己的执行程序时都没有用上。因此,编译出来的程序没有用上硬件浮点单元的特性。需要进行修改:
1、修改opencv的交叉编译脚本
主要是设置:

27 
 28 set(CMAKE_CXX_FLAGS           "-mthumb -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -mno-unaligned-access -fno-aggressi ve-loop-optimizations"     CACHE STRING "c++ flags")
 29 set(CMAKE_C_FLAGS             "${CMAKE_CXX_FLAGS}"                    CACHE STRING "c flags")
 30 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_FLAGS}"                    CACHE STRING "shared linker flags")
 31 set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_CXX_FLAGS}"                    CACHE STRING "module linker flags")
 32 set(CMAKE_EXE_LINKER_FLAGS    "${CMAKE_CXX_FLAGS} -Wl,-z,nocopyreloc"  CACHE STRING "executable linker flags")
 33 
 34 #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
 35 #set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -mthumb -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
 36 
 37 #set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,- z,now ${CMAKE_SHARED_LINKER_FLAGS}")
 38 #set(CMAKE_MODULE_LINKER_FLAGS "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,- z,now ${CMAKE_MODULE_LINKER_FLAGS}")
 39 #set(CMAKE_EXE_LINKER_FLAGS    "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,- z,now ${CMAKE_EXE_LINKER_FLAGS}")
 40 

我这里只需要生成so,是否只需要设置CMAKE_SHARED_LINKER_FLAGS这个就可以了?

2、编译出来的so的情况:

[zzz@localhost build_softfp]$ cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=../install_dir/ -D SOFTFP=ON -DENABLE_NEON=ON -D CMAKE_TOOLCHAIN_FILE=../arm-gnueabi.toolchain.cmake ../../../


[zzz@localhost build_softfp]$ readelf -a lib/libopencv_imgproc.so.2.4.9 
...
Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "Cortex-A7"
  Tag_CPU_arch: v7
  Tag_CPU_arch_profile: Application
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-2
  Tag_FP_arch: VFPv4
  Tag_Advanced_SIMD_arch: NEONv1 with Fused-MAC
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_enum_size: int
  Tag_ABI_HardFP_use: SP and DP
  Tag_CPU_unaligned_access: v6
  Tag_MPextension_use: Allowed
  Tag_DIV_use: Allowed in v7-A with integer division extension
  Tag_Virtualization_use: TrustZone and Virtualization Extensions
[zzz@localhost build_softfp]$ 

我加了一个-DENABLE_NEON=ON,不加也可以。

3、修改执行程序的脚本
在toolchainfile里增加:

set(CMAKE_CXX_FLAGS           "-mthumb -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -mno-unaligned-access -fno-aggressive-loop-optimizations"     CACHE STRING "c++ flags")
set(CMAKE_C_FLAGS             "${CMAKE_CXX_FLAGS}"                    CACHE STRING "c flags")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_FLAGS}"                    CACHE STRING "shared linker flags")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_CXX_FLAGS}"                    CACHE STRING "module linker flags")
set(CMAKE_EXE_LINKER_FLAGS    "${CMAKE_CXX_FLAGS} -Wl,-z,nocopyreloc"  CACHE STRING "executable linker flags")

经过测试,其实不设置CMAEK_CXX_FLAGS,CMAKE_C_FLAGS及其他,只设置CMAKE_EXE_LINKER_FLAGS,都能达到目标。
产生的exe的情况:

Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "Cortex-A7"
  Tag_CPU_arch: v7
  Tag_CPU_arch_profile: Application
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-2
  Tag_FP_arch: VFPv4
  Tag_Advanced_SIMD_arch: NEONv1 with Fused-MAC
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_enum_size: int
  Tag_ABI_HardFP_use: SP and DP
  Tag_CPU_unaligned_access: v6
  Tag_MPextension_use: Allowed
  Tag_DIV_use: Allowed in v7-A with integer division extension
  Tag_Virtualization_use: TrustZone and Virtualization Extensions

4、弄明白cmake的几个变量的含义

你可能感兴趣的:(opencv,移植)