在做porting 移植移植Opencv之前, 需要提前了解下CMAKE cross compiling的工作原理。 因为现在opencv 自从2.0版本后采用 cmake编译, 而以前的版本用的是autotools。 编译的方式发送了变化, 所以看下cmake 还是很有必要的。 这里可以参考下: http://www.vtk.org/Wiki/CMake_Cross_Compiling
1/ 环境配置好了, cmake -DCMAKE_TOOLCHAIN_FILE=mytoolchain.cmake . , 这一步可以生成makefile文件。 其中 mytoolchain.cmake 文件是自己写的,可以参考上面提供的网址的内容。
2/ cmake执行成功后,执行make命令。 在编译 gl_core_3_1.cpp 这个文件的时候,会提示 __extern_inline 错误。 下面就是我的解决方案:
9.在 /home/sundh/opencv-2.4.4/build/modules/core/precomp.hpp 里面加代码:
运行命令编译, 发现 没有出现 #error “_extern_inline define” 和 #error “_extern_inline“ 的错误。可见,修改precomp.hpp 文件对编译是完全没有影响的,感觉编译根本就没有包含/home/sundh/opencv-2.4.4/build/modules/core/precomp.hpp 这个文件一样。 验证我们的猜想,删除/home/sundh/opencv-2.4.4/build/modules/core/precomp.hpp文件, 然后用 arm-v7a15v3r1-linux-gnueabi-g++ … -include"/home/sundh/opencv-2.4.4/build/modules/core/precomp.hpp"-Winvalid-pch -o CMakeFiles/opencv_core.dir/src/gl_core_3_1.cpp.o -c/home/sundh/opencv-2.4.4/modules/core/src/gl_core_3_1.cpp,居然不报找不到precomp.hpp 文件的错误。
10.额, 问题很严重了哦。 重新make发现 生成了precom.hpp 和 precomp.hpp.gch 。 precomp.hpp.gch这个东西是 gcc的一种预编译技术——预编译头技术,就是将头文件先编译成一种二进制中间格式,以供后续编译使用的。
gcc在编译过程中会自动查找相应的.gch文件,并且自动检测其可用性,如果不可用,gcc会给出警告,然后使用对应的.h文件,抛弃当前.gch。 噢,这下明白了一点, arm-v7a15v3r1-linux-gnueabi-g++ … -include"/home/sundh/opencv-2.4.4/build/modules/core/precomp.hpp"-Winvalid-pch -o CMakeFiles/opencv_core.dir/src/gl_core_3_1.cpp.o -c/home/sundh/opencv-2.4.4/modules/core/src/gl_core_3_1.cpp运行时,真正用到的是 *.gch 文件, 相应的头文件是可有可无的。 呵呵,
11. 那我把precomp.hpp.gch删除掉,编译就会用到precom.hpp文件了。 尝试了下,是这样的。在precom.hpp文件中添加log, 是能打出来的, 但执行arm-v7a15v3r1-linux-gnueabi-g++… -include "/home/sundh/opencv-2.4.4/build/modules/core/precomp.hpp"-Winvalid-pch -o CMakeFiles/opencv_core.dir/src/gl_core_3_1.cp p.o -c/home/sundh/opencv-2.4.4/modules/core/src/gl_core_3_1.cpp却不报错了。 问题有来了? 看来precomp.hpp.gch不止包含了precom.hpp的文件信息, 而且还包含了其他的一些信息。 看来要研究precom.hpp 如何生存precomp.hpp.gch文件了。
12. precom.hpp 如何生存precomp.hpp.gch?? 怎么生存的。 测试发现做cmake … 这步的时候,生存了precom.hpp 如何生存precomp.hpp.gch 这个文件夹。 那具体生成的命令是什么呢?
用 cmake … --trace ..可以把cmake生存makefile的编译过程显示出来,而且是超级详细哦。呵呵,一下子感觉到前面的路,豁然开朗。保存这样的信息到文件A中。
13.在文件A中查找关键字precomp.hpp.gch, 可以看到这样的命令:
/home/sundh/opencv-2.4.4/cmake/OpenCVPCHSupport.cmake(117): SET(_command ${CMAKE_CXX_COMPILER} ${_compile_FLAGS} -x c++-header -o/home/sundh/opencv-2.4.4/build/modules/core/precomp.hpp.gch/opencv_core_Release.gch/home/sundh/opencv-2.4.4/build/modules/core/precomp.hpp ) 原来是在这里通过这条命令生成的,接着查找_compile_FLAGS的值是什么,就这样。一直可以找到
14,经过很长时间的调整查找,可以找到这样的命令:
/usr/local/share/cmake-2.8/Modules/FindZLIB.cmake(56): FIND_PATH(ZLIB_INCLUDE_DIR NAMES zlib.h ${${search}}PATH_SUFFIXES include )
/usr/local/share/cmake-2.8/Modules/FindZLIB.cmake(57): FIND_LIBRARY(ZLIB_LIBRARY NAMES ${ZLIB_NAMES} ${${search}}PATH_SUFFIXES lib )
CMakeList.txt 里面会调用 cmake里面的 FindZLIB.cmake文件, 这个文件是cmake自己搞的一套查找zlib头文件和库文件的脚本。PATH_SUFFIXES后面是什么东东?呀,被震惊到了。居然要找路径中包含 include和 lib 的文件夹。也就是说你的zlib库文件和头文件要放到lib和include 的文件夹下, 不然是找不到的。
15 .回想下,因为arm编译工具链把这个zlib给剪辑掉了,所以zlib库是我自己编译的。我给zlib头文件和库文件的文件名都是随便取的一个,与include/lib不相符. 额,被cmake内部的配置脚本给阴了。
16. 总结: cmake中的FindZLIB.cmake脚本要查找zlib的头文件和库文件,如果找不到,就会到/usr/include和/usr/lib下面找。这时肯定是能找到的,结果就把 /usr/include路径放到头文件的搜索路径里面去。这时候进行arm编译的时候,就会使用/usr/include下面的头文件。结果就会出现很奇葩的错误。
//filename: mytoolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER $ENV{CROSS_COMPILE}gcc)
set(CMAKE_CXX_COMPILER $ENV{CROSS_COMPILE}g++)
set(CMAKE_FIND_ROOT_PATH $ENV{CROSS_ROOT_PATH} $ENV{OPENSOURCE_DIR}/Utility/ZLIB/1.2.6)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_INSTALL_PREFIX .)
#filename: opencv.sh
#!/bin/bash
#This is opencv shell script
OPENCV_ROOT=`pwd`
export OPENCV_ROOT
if [ ! -d "opencv-2.4.4" ]; then
echo "Unpacking opencv source ..."
tar jxvf OpenCV-2.4.4a.tar.bz2
fi
CROSS_ROOT_PATH=/home/data001/toolchain/toolchain/arm-v7a15v3r1-20121018/bin/../arm-v7a15v3r1-linux-gnueabi/sys-root
if [ ! -n "$CROSS_COMPILE" ]; then
export CROSS_COMPILE=arm-v7a15v3r1-linux-gnueabi-
fi
if [ ! -d "opencv-2.4.4/build" ];then
mkdir opencv-2.4.4/build
cp mytoolchain.cmake opencv-2.4.4/build
cp opencv-2.4.4/modules/imgproc/src/smooth.cpp opencv-2.4.4/modules/imgproc/src/smooth.cpp.bak
cp -f src/smooth.cpp opencv-2.4.4/modules/imgproc/src
#echo "add ZLIB to the directory"
#mkdir $ENV{OPENSOURCE_DIR}/Utility/ZLIB/1.2.6/include
#mkdir $ENV{OPENSOURCE_DIR}/Utility/ZLIB/1.2.6/lib
ln -sf $OPENSOURCE_DIR/Utility/ZLIB/1.2.6/Inc $OPENSOURCE_DIR/Utility/ZLIB/1.2.6/include
ln -sf $OPENSOURCE_DIR}Utility/ZLIB/1.2.6/Lib/FOXP/dbg $OPENSOURCE_DIR/Utility/ZLIB/1.2.6/lib
echo "cmake..., make -j8"
cd opencv-2.4.4/build
cmake -DCMAKE_TOOLCHAIN_FILE=mytoolchain.cmake -DBUILD_opencv_highgui=OFF -DBUILD_opencv_apps=OFF -DBUILD_opencv_legacy=OFF -DBUILD_opencv_ml=OFF -DBUILD_opencv_nonfree=OFF -DBUILD_opencv_python=OFF -DBUILD_opencv_ts=OFF -DBUILD_opencv_stitching=OFF -DBUILD_opencv_video=OFF -DBUILD_opencv_videostab=OFF -DBUILD_opencv_world=OFF -DWITH_TIFF=OFF -DWITH_JPEG=OFF -DWITH_OPENEXR=OFF -DWITH_PNG=OFF -DWITH_JASPER=OFF ..
make clean; make -j8
else
echo "make -j8"
cd opencv-2.4.4/build
make -j8
fi
echo "copy opencv-2.4.4 header files and library"
if [ -d "$OPENCV_ROOT/Inc" ];then
rm -rf $OPENCV_ROOT/Inc
fi
if [ -d "$OPENCV_ROOT/Lib" ];then
rm -rf $OPENCV_ROOT/Lib
fi
mkdir $OPENCV_ROOT/Inc
mkdir $OPENCV_ROOT/Lib
cp -f $OPENCV_ROOT/opencv-2.4.4/build/lib/*.so* $OPENCV_ROOT/Lib
cp -rf $OPENCV_ROOT/opencv-2.4.4/include/opencv $OPENCV_ROOT/Inc
cp -rf $OPENCV_ROOT/opencv-2.4.4/include/opencv2 $OPENCV_ROOT/Inc
cp -rf $OPENCV_ROOT/opencv-2.4.4/modules/calib3d/include/opencv2/* $OPENCV_ROOT/Inc/opencv2
cp -rf $OPENCV_ROOT/opencv-2.4.4/modules/core/include/opencv2/* $OPENCV_ROOT/Inc/opencv2
cp -rf $OPENCV_ROOT/opencv-2.4.4/modules/features2d/include/opencv2/* $OPENCV_ROOT/Inc/opencv2
cp -rf $OPENCV_ROOT/opencv-2.4.4/modules/flann/include/opencv2/* $OPENCV_ROOT/Inc/opencv2
cp -rf $OPENCV_ROOT/opencv-2.4.4/modules/imgproc/include/opencv2/* $OPENCV_ROOT/Inc/opencv2
cp -rf $OPENCV_ROOT/opencv-2.4.4/modules/photo/include/opencv2/* $OPENCV_ROOT/Inc/opencv2
cp -rf $OPENCV_ROOT/opencv-2.4.4/modules/objdetect/include/opencv2/* $OPENCV_ROOT/Inc/opencv2