OpenCV 3.0.0 の raspberry pi クロスコンパイルに挑戦
せっかく raspberry pi のクロスコンパイル環境を構築↓したので、OpenCV 3.0.0 のクロスコンパイルに挑戦してみた。
いやー、面倒臭かったです。
前提条件として、opencv-2.4.1 パッケージをインストールし、Ubuntu に吸い出している
とする。
私の環境では raspberry pi から吸いだしたバイナリ/インクルードファイルは
/opt/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/root
以下に入っているので仮にこれを ROOTDIR と名付けるとして、まず以下の
2つのファイルを作成する。
source.sh の中身。
#!/bin/bash export ARCH=arm export CROSS_COMPILE=arm-linux-gnueabihf- export ROOTDIR=/opt/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/root export PKG_CONFIG_PATH="${ROOTDIR}/arm-linux-gnueabihf/pkgconfig:${ROOTDIR}/usr/lib/pkgconfig" export PATH="/opt/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:${PATH}" pushd ${ROOTDIR}/etc . ld.so.cache popd
ld.so.cache という(よくない名前の)ファイルの中身。
#!/bin/sh dirs=`ls ld.so.conf.d` objpath="" ldpath="-Xlinker -rpath-link -Xlinker /lib/arm-linux-gnueabihf -Xlinker -rpath-link -Xlinker /usr/lib/arm-linux-gnueabihf" for d in $dirs; do echo "for $d" files=`cat ld.so.conf.d/$d` for f in $files; do echo "for $f" objpath="-L${ROOTDIR}$f $objpath" ldpath="-Xlinker -rpath-link -Xlinker ${ROOTDIR}$f $ldpath" done done export CROSS_LIBDIRS="$objpath" export CROSS_LINKDIRS="$ldpath"
ld.so.conf.d には ROOTDIR 以下や元々付いていたライブラリのディレクトリを書いておく。
source source.sh として、これらの環境変数を定義しておきます。
次に OpenCV-3.0.0 の platforms/linux/arm-gnueabi.toolchain.cmake を書き換える。
*** platforms/linux/arm-gnueabi.toolchain.cmake 2015-06-04 02:21:34.000000000 +0900 --- arm-gnueabi.toolchain.cmake 2015-07-10 22:59:23.213124021 +0900 *************** *** 2,8 **** set(CMAKE_SYSTEM_VERSION 1) set(CMAKE_SYSTEM_PROCESSOR arm) ! set(GCC_COMPILER_VERSION "4.6" CACHE STRING "GCC Compiler version") set(FLOAT_ABI_SUFFIX "") if (NOT SOFTFP) --- 2,8 ---- set(CMAKE_SYSTEM_VERSION 1) set(CMAKE_SYSTEM_PROCESSOR arm) ! set(GCC_COMPILER_VERSION "4.8.3" CACHE STRING "GCC Compiler version") set(FLOAT_ABI_SUFFIX "") if (NOT SOFTFP) *************** *** 10,30 **** endif() 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." ) --- 10,35 ---- endif() 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++) ! set(ARM_LINUX_SYSROOT ${ROOTDIR} CACHE PATH "ARM cross compilation system root") ! set(CMAKE_CXX_FLAGS "-nostdinc++" CACHE STRING "c++ flags") ! set(CMAKE_C_FLAGS "-nostdinc" CACHE STRING "c flags") ! set(CMAKE_SHARED_LINKER_FLAGS "$ENV{CROSS_LIBDIRS} $ENV{CROSS_LINKDIRS}" CACHE STRING "shared linker flags") ! set(CMAKE_MODULE_LINKER_FLAGS "$ENV{CROSS_LIBDIRS} $ENV{CROSS_LINKDIRS}" CACHE STRING "module linker flags") ! set(CMAKE_EXE_LINKER_FLAGS "$ENV{CROSS_LIBDIRS} $ENV{CROSS_LINKDIRS} -Wl,-z,nocopyreloc" CACHE STRING "executable linker flags") ! ! set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi") ! #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_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi") ! ! set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now ${CMAKE_SHARED_LINKER_FLAGS}") ! #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,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now ${CMAKE_MODULE_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,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now ${CMAKE_EXE_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." )
更に cmake-armel.sh というファイルを作成する。
(OpenCV のソースは /usr/local/src に置いてあるとします。)
#!/bin/bash CPATH1="${ROOTDIR}/usr/include":"${ROOTDIR}/usr/include/arm-linux-gnueabihf" CROOT="${ROOTDIR}/../arm-linux-gnueabihf" CPATH2="${CROOT}/include":"${CROOT}/include/arm-linux-gnueabihf":"${CROOT}/libc/usr/include":"${CROOT}/libc/usr/include/arm-linux-gnueabihf" CROOT3="${CROOT}/../lib/gcc/arm-linux-gnueabihf/4.8.3/" CPATH3="${CROOT3}/include":"${CROOT3}/finclude":"${CROOT3}/include-fixed" CPLUS_INCLUDE_PATH="${CROOT}/include/c++/4.8.3":"${CROOT}/include/c++/4.8.3/arm-linux-gnueabihf" CPATH_GTK="${ROOTDIR}/usr/include/gtk-2.0":"${ROOTDIR}/usr/include/cairo":"${ROOTDIR}/usr/include/pango-1.0":"${ROOTDIR}/usr/lib/arm-linux-gnueabihf/gtk-2.0/include":"${ROOTDIR}/usr/include/gdk-pixbuf-2.0":"${ROOTDIR}/usr/include/atk-1.0" export CPATH="${CPATH1}":"${CPATH3}":"${CPLUS_INCLUDE_PATH}":"${CPATH2}":"${CPATH_GTK}" export PKG_CONFIG_SYSTEM_INCLUDE_PATH= export PKG_CONFIG_SYSTEM_LIBRARY_PATH= export PKG_CONFIG_SYSTEM_ALLOW_SYSTEM_CFLAGS=1 export PKG_CONFIG_SYSTEM_ALLOW_SYSTEM_LIBS=1 export PKG_CONFIG_DIR= export PKG_CONFIG_LIBDIR="${ROOTDIR}/usr/local/ffmpeg/lib/pkgconfig":"${ROOTDIR}/usr/lib/arm-linux-gnueabihf/pkgconfig":"${ROOTDIR}/usr/lib/pkgconfig":"${ROOTDIR}/usr/share/pkgconfig" export PKG_CONFIG_SYSROOT_DIR="${ROOTDIR}" cmake -DCMAKE_INSTALL_PREFIX="${ROOTDIR}/usr/local/ffmpeg" -DCMAKE_TOOLCHAIN_FILE="../arm-gnueabi.toolchain.cmake" /usr/local/src/opencv-3.0.0
mkdir armel; cd armel; cp ../cmake-armel.sh .
を実行してcmake-armel.sh をコピーする。更に
source cmake-armel.sh
として Makefile を作成する。
あとは普通に make -j4; make install で ROOTDIR/usr/local/ffmpeg 以下にバイナリが
インストールされます。
1つ気をつけなければならないのは、pkg-config のバージョンで、クロスコンパイラ付属
のものはバージョンが古く、SYSROOT がまともに動かない点です。freedesktop から
0.28 を持ってきてコンパイルすれば OK。
動作確認が残っているけど今日はこれで寝ます。