最近はNix on raspberry pi zero をやった
イントロ
raspberry pi zeroをちょっと前に2枚買ったのが特に用途がない
強いて用があるとすれば、この前買ったserial通信経由でデータが取れるco2計測器がLinuxの方が読みやすそうだなってぐらい。 これはこのco2計測器が悪いわけではなく、macにマウントされるserial device?がちょっといまいちな挙動をしているからだ。
というわけで 何かと開発する上で便利なので、Raspberry Pi OSにnixをいれていく。
余談だが、rasipbian OSはRaspberry Pi OSに名前が変わっていた。
install
Nixをいれるのは適当にやってもらっていいが、以下の行に注意する必要がある
nix/install.in at master · NixOS/nix · GitHub
"$(uname -s).$(uname -m)"
の実行結果が Linux.armv6l_linux
になることを期待しているが、 少なくとも自分の環境では Linux.armv6l
になる
これは Linux.armv6l_linux
が返ってくる環境が世の中にあるのかわからないのでバグなのかわからないが、armv6lのRaspberry Pi OSにNixを入れようとしている人間がzeroに近いことを演繹させてくれる有力な証拠である。
ちなみに NixOS on raspberry pi zeroをやっている人間はGitHubを見た感じでは何人かいることが観測できたので、そのうちやると思う。
build on pi
普通の環境では(ここでいう普通の環境とはflake-utilsのdefaultSystemsとか)「はい!あとはプログラムを書いて終わり!」となるが、ここはarmv6l、一切のcacheが降ってこない砂漠地帯、nix-shellが要求するbashInteractiveですらgccのビルドから始まってしまう。
というわけで gccとstdenvのビルドをやっていく。
まぁ時間さえあれば終わるでしょうと思っていてビルドを走らせていたわけだが、途中で止まってしまう。
どうやらメモリが足りなくなってOOMで落ちたっぽいエラーを観測した。足りないのは時間ではなくメモリ。
正直 パイゼロは500Mしかメモリがない、がしかし「20年前のPCでも500Mあったし流石にgccはビルドできるのは?」という気持ちも捨てがたい。そして「SD上にswapを増やしても大変な遅さになってしまうのでは?」と思いパイゼロ上でビルドするのはやめた。
なのでここからはmacでビルドしてラズパイに送る戦略をとる。
build on mac
ところでDockerDesktopという便利なものがある。何が便利かというと、マルチCPUアーキテクチャサポートがある
つまり armv6lのlinuxが豊富なメモリと屈強なCPUを積んだmacで動いてくれるわけだ。
今回は arm32v6/alpine
Docker Hub にNixをインストールする戦略をとる。
余談だが NixのcrossCompile機能を使ってやるという手法もあるのだが、derivationが異なってしまう恐れを直感的に感じ取り今回はやめた。 具体的には crossCompileでビルドしたgccを使って ラズパイ上で他のものをビルドすること際に気を使う必要がある可能性を感じた、これは試していないからわからない
話を戻し、まずは bashをビルドしていく。ここで必要なのは時間と忍耐力で、具体的には一晩の時間とmacのファンの音を気にしない心だ。
ここで 一旦 ラズパイの方に できた bashを送る。 nix copy -s --to $ビルドされたbashのpath
。
送る際に because it lacks a valid signature
と言われると思うので、nix.confに require-sigs = false
を足して nix-daemonを再起動させる。
おそらく動くと思うし、bashをbuildしようとしてもbuildされずに先程送ったpathが返ってくると思う。もしビルドが始まった場合同一のderivationをビルドしようとしていない可能性が高いと思う。
あとはstdenvをビルドしていく。
あとはビルドするだけと思いきや、ここでstdenvの依存の中に含まれるpcreのtest phaseでコケてしまう。
「そんなわけがないだろう」という気持ちになるが、手元にはすでにコンパイル済みのgccがいるのでラズパイに送りさえすればビルドできるので試してみたところ pcreはビルドできてしまった。
ビルドできてしまったこと自体も「そんなわけがないだろう」という気持ちになったが、pcreがビルドされていれば後はmacのdocker側に持って来ればいいだけなので nix copy --from
で持ってくる。もはやキャッチボールだ。
stdenvとbashInteractiveをラズパイ側に送りつけ、 nix-shell
できることを確認する。
よかったですね
何故こういったことをやっていたのか忘れてしまったが、おおよそ、私の目的はビルドでプログラムの実行は副作用でしかないので、よかったですね。
pcre debug編
なぜpcreのテストが失敗したのか調査していくと pcregrepの -L オプションで失敗しているようだった。
pcreのソースコードを読んでいくとreaddirの挙動がおかしいように感じたので、疑似的なプログラムを書いて試してみると確かに動かない。
比較するために
の三つの環境で疑似プロを動かしたところ armv6lでだけ動かない。
最初はoverlayfsあたりが悪さをしているのでは?と考えたがどうやら違うらしい。
そもそもマルチCPUアーキテクチャが qemuを使っているので、そこら辺のワードと共に探っていくと以下のIssueに行き着いた。
これは...ダメですね...