徒然なる日々を送るソフトウェアデベロッパーの記録(2)

技術上思ったことや感じたことを気ままに記録していくブログです。さくらから移設しました。

OpenCV 3.0.0 の raspberry pi クロスコンパイルに挑戦

せっかく raspberry pi のクロスコンパイル環境を構築↓したので、OpenCV 3.0.0 のクロスコンパイルに挑戦してみた。

minosys.hateblo.jp

いやー、面倒臭かったです。
前提条件として、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。

動作確認が残っているけど今日はこれで寝ます。