RaspberryPi：Macでクロスコンパイル＆デバッグ

# RaspberryPiプログラムをMacでコンパイルおよびデバッグ
RaspberryPiプログラムをLinux上でクロスコンパイル＆デバッグする記事は見かけるが、Mac上でこれらを行っているものはあまり見かけないので、備忘録も兼ねて記録する。

## 環境
### Mac
macOS Catalina 10.15.7
### RaspberryPi
大昔に買ったもの。バージョンなどは下記のとおり。（これらの確認方法については[参照サイト](https://reasonable-code.com/raspberrypi-version-show/)参照）

```
pi@raspberrypi:~ $ uname -a
Linux raspberrypi 4.19.97+ #1294 Thu Jan 30 13:10:54 GMT 2020 armv6l GNU/Linux
pi@raspberrypi:~ $ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 10 (buster)
Release:	10
Codename:	buster
pi@raspberrypi:~ $ cat /proc/device-tree/model 
Raspberry Pi Model B Plus Rev 1.2
```

## クロスコンパイラ＆クロスコンパイル
ほぼ、[こちらの記事](https://blog.meinside.dev/Build-Cross-Compile-Tools-for-Raspberry-Pi-on-macOS/)に従う。

***１　Command line toolおよびHomebrewをインストール***
[こちら](https://qiita.com/royroy/items/338362362de73a94fc0c)のとおり。

***２　wgetインストール（オプション）***

```
$ brew install wget
```
***３　クロスコンパイラ用ディレクトリの作成***

```
$ mkdir -p raspbian-sdk/{prebuilt,sysroot}
```

***４　clang+llvmのダウンロードおよび解凍***

```
$ wget https://github.com/llvm/llvm-
project/releases/download/llvmorg-11.0.0/clang+llvm-11.0.0-x86_64-apple-darwin.tar.xz
$ tar -xzf clang+llvm-11.0.0-x86_64-apple-darwin.tar.xz -C "raspbian-sdk/prebuilt" --strip-components=1
```

***５　binutilsのインストール***
私の環境では、v2.31以上のbinutilsはうまくBuildできず、v2.30を利用。

```
$ wget http://ftp.gnu.org/gnu/binutils/binutils-2.30.tar.xz
$ tar -xzf binutils-2.30.tar.xz
$ cd binutils-2.30
$ brew install coreutils
$ ./configure --prefix="`/usr/local/bin/realpath ../raspbian-sdk/prebuilt`" \
	--target=arm-linux-gnueabihf \
	--enable-gold=yes \
	--enable-ld=yes \
	--enable-targets=arm-linux-gnueabihf \
	--enable-multilib \
	--enable-interwork \
	--disable-werror \
	--quiet
$ make && make install
```

***６　最初のディレクトリに戻る***

```
$ cd ..
```

***７　rsync導入***
Macにインストール済のrsyncでは、この後に実施する何かのオプションが足りないらしい（どこかの記事にあり）。

```
$ brew install rsync
```

***８　RaspberryPiからライブラリやヘッダをMacにコピー***
本題からそれるが、RaspberryPiにはavahi-daemonが動作する設定をしているので、IPアドレスではなく、"raspberrypi.local"でRaspberryPiを指定することが可能。

```
$ /usr/local/bin/rsync -rzLR --safe-links \
	pi@raspberrypi.local:/usr/lib/arm-linux-gnueabihf \
	pi@raspberrypi.local:/usr/lib/gcc/arm-linux-gnueabihf \
	pi@raspberrypi.local:/usr/include \
	pi@raspberrypi.local:/lib/arm-linux-gnueabihf \
	raspbian-sdk/sysroot
```

***９　クロスコンパイル用のスクリプト作成***

```
$ vi raspbian-sdk/prebuilt/bin/arm-linux-gnueabihf-clang
```
```sh:arm-linux-gnueabihf-clang
#!/bin/bash
BASE=$(dirname $0)
SYSROOT="${BASE}/../../sysroot"
TARGET=arm-linux-gnueabihf
COMPILER_PATH="${SYSROOT}/usr/lib/gcc/${TARGET}/8"
exec env COMPILER_PATH="${COMPILER_PATH}" \
	"${BASE}/clang" --target=${TARGET} \
		--sysroot="${SYSROOT}" \
		-isysroot "${SYSROOT}" \
		-L"${COMPILER_PATH}" \
		--gcc-toolchain="${BASE}" \
		"$@"
```
```
$ chmod +x raspbian-sdk/prebuilt/bin/arm-linux-gnueabihf-clang
```

***１０　ビルド＆RaspberryPiへのコピー***
ここでは次のソースコードをビルド＆デバッグの対象とする。

```c:abc.c
#include <stdio.h>

int main() {
  int i, sum=0;
  printf("Bonjour!\n");
  for (i=1; i<=10; i++) {
    sum += i;
    printf("i=%d sum=%d\n", i, sum);
  }
  printf("Au revoir!\n");
  return(0);
}
```
```
$ ls
abc.c
$ ../raspbian-sdk/prebuilt/bin/arm-linux-gnueabihf-clang -g3 -o abc abc.c
$ scp abc pi@raspberrypi.local:
```

## デバッグ環境（gdb）
### RaspberryPi
gdbserverをインストール。

```
pi@raspberrypi:~ $ sudo apt install gdbserver
```

### Mac
[こちら](https://mynewt.apache.org/v1_5_0/get_started/native_install/cross_tools.html)か[こちら](https://github.com/ARMmbed/homebrew-formulae)を参考にして、ARM用gdbをインストール。

```
$ brew install arm-none-eabi-gdb 
```
など。[Linaro](https://www.linaro.org)などにもBuildされたgdbが見つかる。

## デバッグ
### RaspberryPi

```
pi@raspberrypi:~ $ gdbserver --multi :5555
Listening on port 5555
```

### Mac(CLI)
gdb用スクリプト(gdb_local)を用意して、arm-none-eabi-gdbを起動する。

```
$ cat gdb_load 
target extended-remote raspberrypi.local:5555
file /Users/xyz/proj/pi/abc
remote put /Users/xyz/proj/pi/abc /home/pi/abc
set remote exec-file /home/pi/abc
start
$
$ arm-none-eabi-gdb -x gdb_load

　多数メッセージ省略

Temporary breakpoint 1 at 0x10424: file abc.c, line 4.
warning: A handler for the OS ABI "GNU/Linux" is not built into this configuration
of GDB.  Attempting to continue with the default armv6 settings.


Temporary breakpoint 1, main () at abc.c:4
4	  int i, sum=0;
(gdb)
```

この時のRaspberryPi側表示。

```
Remote debugging from host 192.168.10.107
Process /home/pi/abc created; pid = 850
```

あとは、煮るなり焼くなりする。

### Mac(VSCode)
VSCodeは使ったことがないので、[こちらの記事](https://qiita.com/iwatake2222/items/5b20558f8ab3f27ca4a4)を参考にして、素人レベルの視点で記載。

ソースコードがあるディレクトリを開いた後、VSCodeにてデバッグ開始。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/e7ab3ced-f084-e9b5-cd3a-b03fee100ca5.png", width=90%>
すると、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/11e00008-c410-8942-1b58-8e6150ace7f6.png", width=90%>
となり、「C++(GDB/LLDB)」を選択する。その後、launch.jsonが開くので、次のように編集。

```json:launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "arm-none-eabi-gcc - アクティブ ファイルのビルドとデバッグ",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/abc",
            "args": [],
            "stopAtEntry": true,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "arm-none-eabi-gdb",
            "setupCommands": [
                {"text": "target extended-remote raspberrypi.local:5555"},
                {"text": "file ${workspaceFolder}/abc"},
                {"text": "remote put ${workspaceFolder}/abc /home/pi/abc"},
                {"text": "set remote exec-file /home/pi/abc"}
            ]
        }
    ]
}
```
適宜、メニューから「デバッグの開始」を選択し、設定したい行にブレークポイントを設定する。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/233538de-0782-2c47-bccd-f80ce35f56d5.png", width=40%>
ブレークポイント選択後の様子（８行目）。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/dbda453b-317c-2094-2aaa-eb509906c789.png", width=50%>
変数の状況を見るには、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/eb9bd048-5611-6d3c-4865-7672354fa867.png", width=50%>
ビューを開くから、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/54a40fe5-f77c-e092-6759-915f46462360.png", width=90%>
「変数」を検索すると、変数を表示するWindowが表示される。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/6009f28f-b556-fe08-a1d2-ff4b8d37136f.png", width=90%>
変数をクリックすれば、値を変更することも可能。

## 終わりに
参考サイトの方、トレビアンです。