C++
Mac
RaspberryPi
docker
VisualStudioCode

macでラズパイ用にc++のクロスコンパイルしてリモートデバッグした際のメモ

Macでクロス開発

クロス開発の勉強がてらmacでRaspberry Pi向けにOpenCVをコンパイルしてアプリケーションを作成してリモートデバッグした時のメモ

環境

  • macOS High Sierra (10.13.6)
  • Raspberry Pi3 (Raspbian Stretch Lite)
  • Docker for Mac (Version 18.06.0-ce-mac70)
  • Visual Studio Code

Raspbian Stretch Liteのインストール

公式からとりあえず最新のやつ落としてきてddコマンドでインストール

https://www.raspberrypi.org/downloads/raspbian/

sudo dd if=~/Downloads/2017-07-05-raspbian-jessie.img of=/dev/rdisk2 bs=1m conv=sync

OpenCVをクロスコンパイル

準備

それぞれRaspbianのToolsとOpenCVのソースをクローン
mac用のlinux-armツールチェーンでも行けると思うけどとりあえず今回はToolsを使う。

git clone https://github.com/opencv/opencv.git
git clone https://github.com/raspberrypi/tools.git

Toolsのツールチェーンを利用するためのdockerコンテナを適当に作成してcmakeをインストールしておく。
とりあえず今回はubuntuのコンテナを思考停止で準備

コンパイル

dockerコンテナ内で下記コマンドを実行
※コンパイラのパスだとかインストールパスはその場に応じたパスで。

cmake -DCMAKE_C_COMPILER=/path/to/gcc ¥
    -DCMAKE_CXX_COMPILER=/path/to/g++ ¥
    -DCMAKE_TOOLCHAIN_FILE=../platforms/linux/arm-gnueabi.toolchain.cmake ¥
    -DWITH_QT=OFF -DWITH_CUDA=OFF ¥
    -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DBUILD_TESTS=OFF -DBUILD_PREFTESTS=OFF ¥
    -DCMAKE_INSTALL_PREFIX=/path/to/install/ ..

インストール

コンパイル物をRaspberry Piの/usr/local以下に配置しRaspberry Pi上でldconfigを実行

Visual Studio Codeでアプリケーション作成

クロスコンパイル用にCMakeListsを作成

※target_link_librariesは適当に使用する物を指定

CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "--std=c++11")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g03")

if(RASPBIAN)
    set(CMAKE_C_COMPILER ${RASPBIAN_TOOLS}/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc)
    set(CMAKE_CXX_COMPILER ${RASPBIAN_TOOLS}/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-g++)
    include_directories(${RASPBIAN_ROOTFS}/usr/local/include)
    link_directories(${RASPBIAN_ROOTFS}/usr/local/lib)
endif()

project(sample)
add_executable(sample main.cpp)

target_link_libraries(sample opencv_core opencv_imgproc opencv_imgcodecs opencv_videoio)

コーディング

適当にWebカメラ使って画像処理にかかる時間を計測してみた。

main.cpp
#include <iostream>
#include <time.h>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/videoio.hpp"

int main(int argc, char *argv[]) {
    cv::VideoCapture cap(0);
    cv::Mat frame, gray, dst;

    double thresh, capture, convert, threshold;

    clock_t st, t1, t2, t3;

    for(int i = 0; i < 10; i++) {
        st = clock();
        cap >> frame;
        t1 = clock();
        cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
        t2 = clock();
        thresh = cv::threshold(gray, dst, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
        t3 = clock();

        capture = t1 - st;
        convert = t2 - t1;
        threshold = t3 - t2;

        std::cout << "[" << i << "]" << std::endl;
        std::cout << "Capture time:" << (double)capture / CLOCKS_PER_SEC << std::endl;
        std::cout << "Convert time:" << (double)convert  / CLOCKS_PER_SEC << std::endl;
        std::cout << "Threshold time:" << (double)threshold  / CLOCKS_PER_SEC << std::endl;
        std::cout << "Total time:" << (double)(capture + convert + threshold)  / CLOCKS_PER_SEC << std::endl;
    }

    return 0;
}

クロスコンパイル

tasks.jsonを編集してMac用のバイナリとRaspberry Pi用のバイナリをコンパイル出来るようにしてみた。

tasks.json
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "docker-cmake-raspbian",
            "type": "shell",
            "command": "ls . | xargs rm -r && docker exec -w /home/raspbian-cross/sample/build/raspbian raspbian-cross cmake -DRASPBIAN=TRUE -DRASPBIAN_TOOLS=/home/raspbian-cross/tools -DRASPBIAN_ROOTFS=/home/raspbian-cross/rootfs ../..",
            "options": {
                "cwd": "./build/raspbian"
            }
        },
        {
            "label": "docker-build-raspbian",
            "type": "shell",
            "command": "docker exec -w /home/raspbian-cross/sample/build/raspbian raspbian-cross make",
            "dependsOn": "docker-cmake-raspbian"
        },
        {
            "label": "docker-cmake-raspbian-debug",
            "type": "shell",
            "command": "ls . | xargs rm -r && docker exec -w /home/raspbian-cross/sample/build/raspbian raspbian-cross cmake -DRASPBIAN=TRUE -DRASPBIAN_TOOLS=/home/raspbian-cross/tools -DRASPBIAN_ROOTFS=/home/raspbian-cross/rootfs ../.. -DCMAKE_BUILD_TYPE=RelWithDebInfo",
            "options": {
                "cwd": "./build/raspbian"
            }
        },
        {
            "label": "docker-build-raspbian-debug",
            "type": "shell",
            "command": "docker exec -w /home/raspbian-cross/sample/build/raspbian raspbian-cross make",
            "dependsOn": "docker-cmake-raspbian-debug"
        },
        {
            "label": "cmake",
            "type": "shell",
            "command": "ls . | xargs rm -r && cmake ../..",
            "options": {
                "cwd": "./build/osx"
            }
        },
        {
            "label": "build",
            "type": "shell",
            "command": "make",
            "options": {
                "cwd": "./build/osx"
            },
            "dependsOn": "cmake"
        }
    ]
}

リモートデバッグ

こちらの方の記事を参考にさせていただきリモートデバッグ環境の構築
(https://qiita.com/take-iwiw/items/5b20558f8ab3f27ca4a4)

下記コードを実行してmac用にLinux(ARM)用のGDBをコンパイル
※x.x.xは適宜置き換え

wget http://www.gnu.org/software/gdb/download/gdb-x.x.x.tar.gz
tar xvzf gdb-x.x.x.tar.gz
cd gdb-x.x
mkdir build
../configure --target=arm-buildroot-linux-gnueabi -with-expat
make -j8
make install

成功していたらarm-buildroot-linux-gnueabi-gdbコマンドを実行すると下記のようになる。
hostがdarwinでtargetがarm-buildroot-linux-gnueabiであることを一応確認。

MacBook-Pro:~ admin$ arm-buildroot-linux-gnueabi-gdb
GNU gdb (GDB) 8.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-apple-darwin17.7.0 --target=arm-buildroot-linux-gnueabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb)

launch.jsonも上の記事を参考にさせていただきリモートデバッグを実行

結果

Macでクロス開発ができた(?)