Raspberry PiのクロスコンパイルとVSCodeによるリモートデバッグ開発環境の構築

この記事は最終更新日から1年以上が経過しています。

この記事について

以前、この記事(https://qiita.com/take-iwiw/items/46119bb7d41c6030d34f )で、お手軽にラズパイ用のC/C++開発環境の構築を行いました。この時は、ビルドやデバッグは全てラズパイ上で行いました。

今回は、Ubuntu上でのクロスコンパイルと、gdbserverを使用したリモートデバッグ方法について記します。最終的には、ホストPC上のVSCodeからGUI操作でラズパイのデバッグをできるようにします。デバッグはUbuntu, Windowsのどちらからもできるようにしました。

なお、本記事ではラズパイを対象に記載していますが、一般的な組み込みLinuxのクロス開発にも適用できると思います。

環境

  • Target
    • Raspberry Pi (IPアドレスなどは適宜読み替えてください)
      • IPアドレスは192.168.1.89
      • SSHは有効済み
  • Host
    • Ubuntu 16.04 on VirtualBox on Windows 10
      • クロスコンパイル用
      • デバッグ用
    • MSYS2 64-bit
      • デバッグ用 (デバッグをWindowsから行いたい人用)

クロスコンパイル (on Ubuntu)

クロスコンパイラの取得

基本的に1回だけやればOKです。

Ubuntu上のターミナル
sudo apt-get update
sudo apt-get install build-essential libncurses-dev git git-core
mkdir ~/raspberry
cd ~/raspberry
git clone https://github.com/raspberrypi/tools

ビルド

下記のような~/work/pi/sample01/sample01.cppをビルドしてみます。

sample01.cpp
#include <stdio.h>
int main()
{
    printf("Hello World\n");
    for (int i = 0; i < 10; i++)
        printf("i = %d\n", i);
    return 0;
}
Ubuntu上のターミナル
mkdir ~/work/pi/sample01 && cd ~/work/pi/sample01
code sample01.cpp &
ARCH=arm ~/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-g++ sample01.cpp
# ARCH=arm ~/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ sample01.cpp
scp a.out pi@192.168.1.89:.

最後のscpコマンドで転送したa.outをラズパイ上で実行できます。
32-bit環境の場合は、raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/binの方がいいかもしれません。

リモートデバッグ

こちらの記事を大変参考にさせていただきました。(https://qiita.com/tetsu_koba/items/ebbac47e3fb43c86f412 )。ありがとうございます。

準備

基本的に1回だけやればOKです。

gdbserverのインストール (on ラズパイ)

ラズパイ上のターミナル
sudo apt-get install gdbserver

ARM用gdbバイナリの作成 (on Ubuntu)

Ubuntu上のターミナル
mkdir ~/temp && cd ~/temp
wget http://ftp.jaist.ac.jp/pub/GNU/gdb/gdb-8.0.1.tar.gz
tar xf gdb-8.0.1.tar.gz
cd gdb-8.0.1
mkdir build && cd build
sudo apt-get install libexpat1-dev expat
../configure --target=arm-buildroot-linux-gnueabi  --with-expat
make -j4
sudo make install

リモートデバッグする

gdbserverの起動 (on ラズパイ)

ラズパイ上のターミナル
gdbserver --multi :5555

gdb実行 (on Ubuntu)

デバッグしたい実行ファイルと同じところに、以下のようなファイル(~/work/pi/sample01/gdb_load)を作っておきます。

gdb自動実行用スクリプト
target extended-remote 192.168.1.89:5555
file ./a.out
remote put ./a.out /home/pi/a.out
set remote exec-file /home/pi/a.out
start

gdb_loadとa.outと同じパスで下記コマンドを実行すると、デバッグが始まります。
デバッグ情報はUbuntu側のターミナルに、printf等の出力はラズパイ側のターミナルに出力されます。

Ubuntu上のターミナル
arm-buildroot-linux-gnueabi-gdb -x gdb_load
# ↓はgdb内のプロンプト
>>> n

デバッグをやり直すとき (on Ubuntu)

基本的にラズパイ側で起動したgdbserverは常時起動でOKです。そのため、ラズパイ側での操作は不要です。
Ubuntu側のgdbターミナルで、qをして、再度gdbを実行させれば再起動します。

VSCodeからリモートデバッグする (on Ubuntu)

gdbコマンドによるデバッグでは、よっぽど慣れた人でないと効率が悪いと思います。VisualStudio CodeからGUIによってデバッグできるようにします。一般のアプリケーション開発と同様に、ステップ実行やブレークポインタの設定をGUIからできるようにして、スコープ内の変数なども自動で参照できるようにします。

VisualStudio Codeの設定 (on Ubuntu)

~/work/pi/sample01/ディレクトリをVSCodeから開き、F5キーを押してデバッグしようとします。その後、デバッグ設定を作るように聞かれるので、C++(GDB/LLDB)を選択します。

01.jpg

launch.jsonが開かれるので、下記のように編集します。

launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/a.out",  // ★編集
            "args": [],
            "stopAtEntry": true,                    // ★編集(お好みで)
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "arm-buildroot-linux-gnueabi-gdb",        // ★追加
            "setupCommands": [                                          // ★追加
                {"text": "target extended-remote 192.168.1.89:5555"},
                {"text": "file a.out"},
                {"text": "remote put a.out /home/pi/a.out"},
                {"text": "set remote exec-file /home/pi/a.out"}
            ]
        }
    ]
}

VisualStudio Codeからデバッグする (on Ubuntu)

再度F5キーを押すと、デバッグが始まります。以後、本ディレクトリのプロジェクトをデバッグするときはF5キーを押すだけでOKです。
printf等の出力はラズパイ側のターミナルに出力されます。

02.jpg

Windowsからリモートデバッグする

一般的に、ターゲットがLinuxの場合には開発用HOST環境もLinuxだと思います。しかし、何らかの理由でコードの編集やデバッグをWindowsPCで行いたいというのはよくあると思います。(例えば、ビルドはLinuxのビルドサーバーで行い、開発者のWindowsPCにビルドされたバイナリをダウンロードして、それをターゲットに書き込む、などはよくある運用だと思います)。
このような環境では、デバッグのためだけにUbuntuを入れるのが面倒だと思いますので、Windows上でもできるようにします。ターミナル操作のために、MSYS2を使用します。

ARM用gdbバイナリの作成 (on Windows(MSYS2))

下記コマンドでARM用のgdbバイナリを作成します。

MSYS上のターミナル
mkdir ~/temp && cd ~/temp
wget http://ftp.jaist.ac.jp/pub/GNU/gdb/gdb-8.0.1.tar.gz
tar xf gdb-8.0.1.tar.gz
cd gdb-8.0.1
mkdir build && cd build
../configure --target=arm-buildroot-linux-gnueabi  --with-expat
make -j4
make install

メモ
一度ビルドは成功したのですが、その後pythonのインストール(pacman -S python2)をしたり色々してたら、再ビルドが出来なくなってしまいました。。。

VisualStudio Codeの設定 (on Windows)

基本的にはUbuntuでやったのと全く同じです。ソースコードとビルド済みARM用バイナリがC:/Users/tak/Desktop/win_share/sample01/にあるとします。

launch.jsonを下記のように編集します。

launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/a.out",      // ★編集
            "args": [],
            "stopAtEntry": true,                        // ★編集(お好みで)
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "C:/msys64/mingw64/bin/arm-buildroot-linux-gnueabi-gdb.exe",  // ★追加
            "setupCommands": [                                                      // ★追加
                {"text": "target extended-remote 192.168.1.89:5555"},
                {"text": "file C:/Users/tak/Desktop/win_share/sample01/a.out"},
                {"text": "remote put C:/Users/tak/Desktop/win_share/sample01/a.out /home/pi/a.out"},
                {"text": "set remote exec-file /home/pi/a.out"}
            ]
        }
    ]
}

注意点として、自分でビルドしたARM用gdbにはWindows上でのパスを通していないので、フルパス指定する必要があります。また、ロードするバイナリファイルもフルパス指定する必要がありました。${workspaceFolder}を使って省略できないか試したのですが、上手くいきませんでした。

VSCodeからリモートデバッグする (on Windows)

再度F5キーを押すことで、下記のようにデバッグできます。

03.jpg

ラズパイ用の僕の運用

僕はメインPCがWindowsなので、ビルドだけラズパイで行い、デバッグはWindows上のVSCodeでやっています。

  1. Windows上のVSCodeで、コードを書く
  2. Windows上のVSCodeで、sftpエクステンション機能でコードをラズパイにアップロード
  3. ラズパイ上で、ビルド(./a.outを作成)
    • g++ -O0 -g3 sample01.cpp
  4. Windows上のVSCodeで、sftpエクステンション機能でバイナリ(./a.out)をダウンロード
  5. Windows上のVSCodeで、デバッグ実行

その他

  • gdbserverを終了するときは、ホスト側のgdbプロンプトからmonitor exit
  • 共有ライブラリの場所を指定するときは、set sysroot ./
  • ビルド環境とgdb実行環境でソース構成やパスが異なるときは、set substitute-path from-path to-path
    • 環境が違っても、一応うまく動いてはくれた。相対パスがあっていたら多少は大丈夫そう。
iwatake2222
Embedded software engineer
ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
ユーザーは見つかりませんでした