Raspberry Piのセットアップ時にやっておくと後々嬉しいこと
独断と偏見しかない (なぜか下書きに埋もれていたので投稿)
USBテザリングができるようにする
皆さんご存知の通りRPiのWifiは弱い 外出先の大事なデモの直前にWifiに繋がらないみたいな手遅れにならんように、USBでiPhoneと繋げばすぐネットワークに繋がってsshできるような準備をしておきましょう
sudo apt install ipheth-utils
参考: Raspberry Pi 2/3/Zero でiPhoneのUSBテザリングを使う - Qiita
Android? 知らないですね...
C++17対応コンパイラを入れる
人権を導入します
公式でバイナリがある*1clangを入れていきましょう
wget http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-armv7a-linux-gnueabihf.tar.xz
参考:
- Raspberry Pi - Install Clang 8 and compile C++17 programs | Solarian Programmer
- Raspberry Pi - Install GCC 8 and compile C++17 programs | Solarian Programmer
まとめ
うちにあるラズパイ全滅したかと思ってめちゃ焦った(なんか頑張ったら動くようになった)
— 歯車.v (@coord_e) 2019年1月21日
*1:嬉しい
C++17と標準ライブラリ: C++17を使うときに気をつけたいこと
この記事では、現在(2019/1/19)新規プロジェクトでC++17を気軽に使い始めて困らないかということを、主に標準ライブラリに焦点を当てて考察する。
C++17は2017年に標準規格化されたC++バージョンだ。C++14、C++11と比べるととても使いやすくなっているので自分も使っていきたいと思うし、広く普及して欲しいと思っている。
しかし結論から言うと、まだC++17(の標準ライブラリ)は軽い気持ちで使い始められるものではないように感じた。
C++17に対応した標準ライブラリは、多くの安定版ディストリビューションでまだ使用可能ではないからだ。
※頑張って正確性に気を使っていますが、事実でない部分などありましたら教えてください。申し訳ない。
C++を構成する要素
一口にC++と言ってもそう単純ではなくて、以下の3つの要素の組み合わせを私たちは普段"C++"と呼んでいる。
3つ要素があるということはそれぞれにバージョンがあるわけで、C++17だったら"C++17のプリプロセッサ"、"C++17のコア言語"、"C++17の標準ライブラリ"がある。
例えば
__has_include
ディレクティブ: "C++17で入ったプリプロセッサの機能"- 構造化束縛: "C++17で入ったコア言語機能"
<filesystem>
: "C++17で入った標準ライブラリ"
となる。
さて、今回問題になるのはこの3つのうちの標準ライブラリである。(前者2つはコンパイラが対応していればいい、という単純な話なので)
C++の標準ライブラリ
これはコンパイラとは独立したもので*1、様々な実装が出回っている。
ここでは代表的なものとして以下の2つを題材にする*2:
C++17の代表的な新機能について、それぞれの実装がC++17に対応したバージョンを以下に示す:
<variant> |
<any> |
<optional> |
<filesystem> |
<string_view> |
Parallelism TS | <type_traits> の_v |
|
---|---|---|---|---|---|---|---|
libstdc++ | 7.1 | 7.1 | 7.1 | 8.1 | 7.1 | No | 7.1 |
libc++ | 4.0 | 4.0※ | 4.0※ | 7.0 | 4.0※ | No | 7.0 |
※公式ページではP0220R1はIn progressになっている(2019/1/19)が、どうやら4.0のあたりでこの3つは入っているらしい
なおこれは2019/1/19時点の情報であり、最新の情報は以下の一次ソースで確認して欲しい:
一般的な環境
次に一般的に使われている環境*3で、どのバージョンの標準ライブラリが使える*4かを以下に示す。
Ubuntu Bionic | Debian Stretch | Fedora 29 | CentOS 7 | |
---|---|---|---|---|
libstdc++ | 6.4 | 6.3 | 8.2 | 4.8.5 |
libc++ | 6.0 | 3.5 | 7.0 | No |
と、いうことで、C++17標準ライブラリを使用したソースは、ほとんどの環境でコンパイルできないのである。
LLVM公式のリポジトリを使えばUbuntu/Debianでは最新のlibc++が手に入るので*5、これを使えば救いがあるように見える。
しかし、libc++
でコンパイルされたオブジェクトには、libstdc++
でコンパイルされたライブラリをリンクできない。一般的にバイナリで配布されているライブラリはlibstdc++でコンパイルされているため*6、libc++でうまくいくと有頂天になっている矢先、下のようなエラーで詰む。
../lib/libflom.so: undefined reference to `google::protobuf::util::MessageToJsonString(google::protobuf::Message const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, google::protobuf::util::JsonPrintOptions const&)' ../lib/libflom.so: undefined reference to `google::protobuf::Message::ParseFromIstream(std::__1::basic_istream<char, std::__1::char_traits<char> >*)' ../lib/libflom.so: undefined reference to `google::protobuf::util::MessageToJsonString(google::protobuf::Message const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, google::protobuf::util::JsonPrintOptions const&)'
これはlibstdc++でコンパイルされたprotobufを、libc++でコンパイルされたライブラリにリンクしようとした時に出たエラーの一部です。きつい。*7
バイナリ配布なら問題ないのでは?
「ユーザーがビルドする」というシチュエーションがないと断言できる場合。
これは問題なさそうだが、<filesystem>
などは実行時にlibstdc++/libc++の共有ライブラリが必要なのでやはり慎重にならなければならない。
あんまり調べてないけど、他にも実行時に共有ライブラリが必要な機能はあると思う。
結論
C++17(の標準ライブラリ)を使い始めるときはビルドする環境や外部ライブラリをリンクするかなどをよく考えて、慎重になった方が良さそう
特に<optional>
なんかは手軽さから一度使い始めるとかなり依存してしまいがち(私は)なので、突然「ラズパイでビルドするぞ!」などとなった時やXenialまでしか使えないCIなどで詰む
おまけ
主要ディストリのC++17標準ライブラリ対応状況(コンパイル可能: Y, コンパイル不可能: N)
libstdc++ | Ubuntu Bionic | Debian Stretch | Fedora 29 | CentOS 7 |
---|---|---|---|---|
<variant> |
N | N | Y | N |
<any> |
N | N | Y | N |
<optional> |
N | N | Y | N |
<filesystem> |
N | N | Y | N |
<string_view> |
N | N | Y | N |
Parallelism TS | N | N | N | N |
<type_traits> の_v |
N | N | Y | N |
libc++ | Ubuntu Bionic | Debian Stretch | Fedora 29 | CentOS 7 |
---|---|---|---|---|
<variant> |
Y | N※ | Y | N |
<any> |
Y | N※ | Y | N |
<optional> |
Y | N※ | Y | N |
<filesystem> |
N※ | N※ | Y | N |
<string_view> |
Y | N※ | Y | N |
Parallelism TS | N | N | N | N |
<type_traits> の_v |
Y | N※ | Y | N |
※https://apt.llvm.org/から最新のlibc++を入手すれば使えるようになるでしょう(それはそう)
Fedora最強かよ。
2019/1/19更新: タイトルと冒頭をより意図が伝わるように修正、libc++の表を一部修正
【適当】モチベーションを維持しながら開発する方法
注: このブログでは内容の正しさを検証する気がないので真に受けると後悔するかもしれません
エモくなったのでCIが頑張ってる間に書く
🎉 一週間かけてやっとCI通過🎉
— coordeは起きれない (@coord_e) 2018年12月26日
今回1週間ぐらいCIが通らなくて病んでしまったので(なんてか弱い心!)、そこからちょっと教訓じみたものを捻り出しました
それは何かというと: (自分からの距離)x(1サイクルにかかる時間)が大きい環境で試行錯誤をしない
※主観しかないので、任意の文の先頭に"coordeの場合は"をつけていただければ幸いです。
自分からの距離 is
コードが走る場所と自分の、心理的な距離
イメージとしては ローカル<コンテナ内<リモート<CI
になる
このパラメータは、
- シェルが使いたいときに使えるか
- こちらからの操作に対するレスポンスが早いか
- ファイルシステムにアクセスできるか
- 物理的な距離
- など
で評価される気がします。知らんけど。
1サイクルにかかる時間 is
結果が得られて、次の行動を決定するまでにかかる時間
。多分。
ビルドするのに時間がかかるプロジェクトならこれが大きくなるし、Dockerイメージのビルドとかもでかい。
これが大きくなる最悪のパターンとしては機械学習がある(と思う)。
(自分からの距離)x(1サイクルにかかる時間)が大きいこと is
CIで機械学習する
とか、CIで大きなプロジェクトをビルドする
とか
どうやって小さくするのか
まあCIでビルドするな!なんて無理な話なので、近くの環境でうまくいくことを保証してから遠くに持っていけばいいと思う、するとCIで試行錯誤する範囲が小さくなるので...
なので僕の場合はDockerイメージに固めて、ローカルでうまくいったDockerfileをCIに使わせることで心の健康を取り戻しました。やったね。
まとめ
Dockerを使い始めたら何もかもがうまくいくようになりました ここ一週間の苦労が嘘のようです (10代男性)
— coordeは起きれない (@coord_e) 2018年12月26日
ブログではなるべく敬語ではなく普通に書こうと思っていたんだけど、難しい...やめるか