singularityを使ったRustコンパイラのデバッグビルド

学科システムにはsingularityというコンテナサービスを導入している。動かしているpodmanと比較するとこのあたりが便利と思っています。

  • ceph fs上でも結構高速に動作
  • root権限がいらない
    • podmanもrootlessではあるが、ceph FS上だと遅い...
  • singularity shellで気軽にコンテナのシェルを立ち上げられる
  • 科学計算向きなのでスパコンなどでの利用実績がある
  • ホームディレクトリなどがattachしたタイミングで自動的にコンテナにマウントされる

とはいえ良い事ばかりではなくツラミポイントもあります。 例えばDockerを使っている場合は構成をDockerfileで書きたくなりますが、singularityで同様のビルドファイルを作ろうとした場合、各コマンドのキャッシュが効きません。

dockerの場合は行単位でキャッシュが効いていたのですが、singularity build的な感じでファイルからビルドしようとすると、失敗した場合最初からになるため、本筋ではないapt updateなどで莫大な時間を浪費します。

しかしsingularityはdockerと違い、--sandboxで実行するといかにもchrootlinux namespaceみがあるディレクトリを作成し、この上で様々な構築をインタラクティブにしたあとにシングルバイナリのsifに固めるという技があるので、dockerファイルの様なファイル形式でなく、インタラクティブに構築する方法が適していそうです。

今回はRustコンパイラデバッグ環境をsingularityで作るのを通して、インタラクティブな構築方法を見てみます。

インタラクティブに構築する場合は、--sandbox--writable を使ってビルド及び環境構築を行います。

sandbox環境の作成

とりあえずaptのupdateだけするファイルrust-debug.defを生成します。

 BootStrap: docker
 From: ubuntu:20.04
 
 %post
     apt-get -y update
     apt-get -y upgrade

sandbox環境のビルド

$singularity build --sandbox --fakeroot rust-debug rust-debug.def

  • sifではなくディレクトリが生成されます
    • ディレクトリの中身はlinux namespaceで区切られていそうな気配ですが、コンテナの中の/移行が置かれています

sandbox環境にシェルログインして環境を作る

$singularity shell --fakeroot --writable rust-debug

こうするとシェルログインが出来ます。 --fakerootはホストOS側でroot権限がないユーザーでも、コンテナの中でrootとして振る舞う事ができるオプションです。

Rustコンパイラデバッグ環境の構築

さてシェルログインできたら、Rustcompilerのデバッグビルドに必要そうなものをインストールします。 なにが必要かはGitHubリポジトリに書いてあるので読んでみます。

github.com

Singularity> apt install -y cmake python3 clang ninja-build lldb gdb curl git

とりあえず必要そうなものをinstall

  • cmake
  • python3
  • clang
  • ninja-build
    • ninjaはaptだとこの名前
  • lldb
  • gdb
  • curl
  • git

無事にインストールされたら、singularityコンテナの中でpythonと入力するとpython3が起動するように仕込みます。

update-alternatives --install /usr/bin/python python /usr/bin/python3 10

参考 Unable to set default python version to python3 in ubuntu

/rootにRustのリポジトリを起きたいところですが、ここは実行ユーザーの$HOMEとマウントされるので適当なディレクトリをつくります

  • $mkdir /rust
  • $cd /rust

Rustコンパイラデバッグビルド

rustのリポジトリをcloneします - $git clone https://github.com/rust-lang/rust.git

Rustはビルドの設定をTOMLで記述します。exampleをもとにするのが良いらしいので、copyします。

  • $cp config.toml.example config.toml

aptでvimをinstallし、設定を書き換えていきます。 まずdebugビルドするので、デバッグオプションを有効化します。 ビルド時にninjaを使いたいのでninjaを有効にし、趣味でinstall先のprefixを変えておきます。

まとめると次のような変更をします。

  • #debug = falsedebug = true
  • #ninja = falseninja = true
  • #prefix = "/usr/local"prefix = "/usr/local"

Rustのビルドとインストール

RustはビルドスクリプトPythonで書かれたx.pyですので、これを実行します

  • ./x.py build && ./x.py install

今回は/rust/rustリポジトリで、ここでビルドを実行しました。 そのため生成されたRustのバイナリは/rust/rust/build/x86_64-unknown-linux-gnu/以下に配置されています。

例えばLLDBでデバッグする場合はrust-lldb /rust/rust/build/x86_64-unknown-linux-gnu/stage1/bin/rustcとするとデバッグ可能です。

ビルドした結果をsifに変換する

sandbox環境で無事ビルドできたので、これを配布可能なsif形式に固めます。

固めるときはbuildで、defファイルでなくディレクトリを指定します。

  • $singularity build --fakeroot debugging-rust-compiler.sif rust-debug

この結果、debugging-rust-compiler.sifが生成されており、以降はこれを使います。

設定したsifに接続する

作成したsifにシェルログインしてみます

$singularity shell debugging-rust-compiler.sif

あわせてよみたい

singularityを使ったRustのデバッグビルド - cr-ryukyu

singularityでRustコンパイラのデバッグ - cr-ryukyu