C/C++のコンパイルを毎回ラズパイ上で行うのは面倒ですよね。マシンパワーも非力でコンパイルに時間も掛かりますし。
というわけで、PC(macOS)上にクロスコンパイラ環境を構築する方法を紹介します。簡単にできるのでMacユーザーはぜひ導入してみてはいかがでしょうか。
前提条件
構築手順に入る前に、まず下記の前提条件を満たしている必要があります。
- ラズパイとMacが通信できる(USBやWi-Fi経由で)
- MacにHomebrewがインストール済み
条件を満たしている方は以降の構築手順に進んでください。
Homebrewのインストールがまだ済んでいない方は、下記のHomebrew公式ページを見ながらインストールしてください。といってもターミナル上でコマンド1つ実行するだけですが(めちゃ楽!)
ラズパイ用C/C++のクロスコンパイラ環境構築手順
クロスコンパイラ環境の構築手順を解説します。手順は大きく3つに分類されます。
- Homebrewで環境構築に必要なツールのインストール
- ラズパイからPCへライブラリ等をコピー
- コンパイル用スクリプト作成
手順1:Homebrewで環境構築に必要なツールのインストール
Macのターミナルを開いて下記コマンドを実行します。
brew install arm-linux-gnueabihf-binutils llvm rsync
このコマンドによって以下の3つのツールがインストールされます。
- arm-linux-gnueabihf-binutils:ARM用プログラミングツール
- LLVM:コンパイラ基板ツール
- rsync:データ転送ツール
手順2:ラズパイからPCへライブラリ等をコピー
次にラズパイからコンパイル時に必要なライブラリ等を取得します。
Macのターミナル上で下記コマンドを実行します。(実行するディレクトリは任意ですが、ユーザーホームが分かりやすいかと)
/usr/local/bin/rsync -rzLRP --safe-links --append\
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/sysroot
このコマンドによってラズパイからライブラリ等をPCへコピーします。それなりに時間がかかるので気長に待ちましょう。
手順3:コンパイル用スクリプト作成
手順2まででコンパイルできる状態になりましたが、コンパイルのコマンドが長いのでスクリプト化しておきます。
まず、Macのターミナル上で下記コマンドを実行して、スクリプトを書き込むファイルを開きます。(viで開いていますが、お好みのエディタで開いて頂いても良いです)
mkdir -p raspbian/prebuilt/bin
vi raspbian/prebuilt/bin/arm-linux-gnueabihf-clang
"arm-linux-gnueabihf-clang"が開かれたら、下記をコピペして保存した後、閉じてください。
#!/bin/bash
BASE=$(dirname $0)
SYSROOT="${BASE}/../../sysroot"
TARGET=arm-linux-gnueabihf
ARCH=armv6
COMPILER_PATH="${SYSROOT}/usr/lib/gcc/${TARGET}/8"
LLVM_PATH=`brew --prefix llvm`
exec env COMPILER_PATH="${COMPILER_PATH}" \
"${LLVM_PATH}/bin/clang" --target=${TARGET} \
-march="${ARCH}" \
--sysroot="${SYSROOT}" \
-L"${COMPILER_PATH}" \
"$@"
5行目の"ARCH=armv6"の部分は『ラズパイZero』の場合の値です。もし他のラズパイを使うのであれば、そのラズパイのARMに合わせて値を変えてください。たとえば『ラズパイ4』用にコンパイルを行う場合は"ARCH=armv8"に変えます。
または、複数のラズパイを持っていて、それぞれ搭載されているラズパイのバージョンが違うのであれば、引数で渡してあげたりする方が便利かもしれません。
あとは作成したスクリプトファイルに実行可能にするために下記コマンドを実行します。
chmod +x raspbian/prebuilt/bin/arm-linux-gnueabihf-clang
以上でクロスコンパイラ環境の構築は完了です。
ついでに"arm-linux-gnueabihf-clang"にPATHを通しておくと楽なので、ユーザーホームにある".zshrc"をviなどで開いて下記を追加します。(ユーザーホーム以外の場所で環境構築した場合は、適宜パスを変更してください)
export PATH=~/raspbian/prebuilt/bin:$PATH
追加したら忘れずに下記コマンドを実行してPATHを反映させましょう。
source ~/.zshrc
コンパイル方法と動作確認
構築したクロスコンパイラで実際にコンパイルしてみましょう。とりあえずお馴染みのHelloWorldを用意します。
#include <stdio.h>
int main(void)
{
printf("Hello World!\n");
return 0;
}
"helloworld.c"の用意ができたらMacのターミナルで下記コマンドを実行してコンパイルします。
arm-linux-gnueabihf-clang helloworld.c
コンパイルが成功すると"a.out"ファイルが生成されます。
次に生成された"a.out"をラズパイに転送します。下記コマンドを実行するとラズパイのホームディレクトリ直下に転送されます。
scp a.out pi@raspberrypi.local:~/
あとはラズパイにSSH接続してラズパイのターミナルを開き、ホームディレクトリで"a.out"を実行すると"Hello World!"が出力されるはずです。
pi@raspberrypi:~ $ ./a.out
Hello World!
まとめ
やはりクロスコンパイラ環境があるとプログラミングも捗ります。コードも大事ですが、快適なプログラミング環境の構築も同じくらい重要なので、ラズパイをバシバシ動かす方はクロスコンパイラ環境を構築しておきましょう。
コメント
コメント一覧 (2件)
MickeyOhさん
質問ありがとうございます。各質問に対して返答させて頂きます。
> 手順2:ラズパイからPCへライブラリ等をコピー
> この意味はローカルのラズパイOSで動作しているターゲットからコピーするとの意味ですか。
MickeyOhさんの仰る通りです。
Raspberry Pi上で動作しているRaspberry Pi OSで動作しているライブラリを、macPC上へコピーするという意味になります。
> ネットから入手する方法はありませんか。
少し調べてみましたがネット上から入手する方法は見つかりませんでした。また、クロスコンパイラ環境はPC上のライブラリとRaspberry Pi上のライブラリを一致させた方が確実に動作できるので、手順通りRaspberry Pi上のライブラリをコピーした方が良いと思います。
> また、このライブラリーは、ラズパイOS上で動作する事を前提にしているんでしょうか。
はい、このライブラリはラズパイOS上で動作することを前提にしています。
> MacOS上でクロスコンパイルしたオプジェクトをラズバイのハードに組込み、動かしたいんです。
このページで紹介している方法で、MacOS上でコンパイルしたオブジェクトをラズパイ上で動かすことができると思います。ただ、質問されているということは、おそらくMickeyOhさんの環境で動作していないと推測しています。どのように動作しなかったのか情報を頂けないでしょうか。より的確なコメントが出来ると思いますので。
以下の点で教えて下さい。よろしくお願いします。
> 手順2:ラズパイからPCへライブラリ等をコピー
この意味はローカルのラズパイOSで動作しているターゲットからコピーするとの意味ですか。
ネットから入手する方法はありませんか。
また、このライブラリーは、ラズパイOS上で動作する事を前提にしているんでしょうか。
MacOS上でクロスコンパイルしたオプジェクトをラズバイのハードに組込み、動かしたいんです。