Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
❄️ NixOS/nixpkgsにSATySFiサポートを実装する
Search
Mutsuha Asada
March 09, 2025
Programming
2
260
❄️ NixOS/nixpkgsにSATySFiサポートを実装する
Nix meetup #2
Mutsuha Asada
March 09, 2025
Tweet
Share
More Decks by Mutsuha Asada
See All by Mutsuha Asada
🔨 小さなビルドシステムを作る
momeemt
4
740
情報科学類で学べる専門科目38選
momeemt
0
620
❄️ tmux-nixの実装を通して学ぶNixOSモジュール
momeemt
1
270
Wasmで拡張できる軽量マークアップ言語 Brack
momeemt
0
110
Intel系FPGA上へのRISC-Vプロセッサの実装
momeemt
0
150
情報科学若手の会 2024 LT「WebAssemblyで拡張可能な軽量マークアップ言語の開発」
momeemt
0
47
Nixでつくるdotfiles
momeemt
1
80
情報特別演習I 最終発表「理工学の紙書籍を用いた学習の効率を向上させるインタフェース」
momeemt
0
45
SATySFi Conf 2023「SATySFiを使って学類新歓冊子を発行した」
momeemt
0
27
Other Decks in Programming
See All in Programming
なぜあの開発者はDevRelに伴走し続けるのか / Why Does That Developer Keep Running Alongside DevRel?
nrslib
3
380
いま中途半端なSwift 6対応をするより、Default ActorやApproachable Concurrencyを有効にしてからでいいんじゃない?
yimajo
2
360
私はどうやって技術力を上げたのか
yusukebe
43
17k
なぜGoのジェネリクスはこの形なのか? Featherweight Goが明かす設計の核心
ryotaros
7
1k
GitHub Actions × AWS OIDC連携の仕組みと経緯を理解する
ota1022
0
240
Le côté obscur des IA génératives
pascallemerrer
0
130
CSC305 Lecture 06
javiergs
PRO
0
210
フロントエンド開発に役立つクライアントプログラム共通のノウハウ / Universal client-side programming best practices for frontend development
nrslib
7
3.9k
CSC509 Lecture 01
javiergs
PRO
1
430
ソフトウェア設計の実践的な考え方
masuda220
PRO
3
500
あなたの知らない「動画広告」の世界 - iOSDC Japan 2025
ukitaka
0
420
GraphQL×Railsアプリのデータベース負荷分散 - 月間3,000万人利用サービスを無停止で
koxya
1
1.2k
Featured
See All Featured
The Language of Interfaces
destraynor
162
25k
Art, The Web, and Tiny UX
lynnandtonic
303
21k
Done Done
chrislema
185
16k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
610
Mobile First: as difficult as doing things right
swwweet
224
10k
Six Lessons from altMBA
skipperchong
28
4k
Building an army of robots
kneath
306
46k
Code Review Best Practice
trishagee
72
19k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.7k
Fireside Chat
paigeccino
40
3.7k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.4k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
36
2.5k
Transcript
NixOS/nixpkgsに SATySFiサポートを実装する Nix meetup #2 2025.03.09 浅田睦葉 @mutsuha_asada
🎓 所属 ・筑波大学情報学群情報科学類 B3 🐣 興味 ・コンパイラやそのツールチェーン、ビルドシステム ・2年くらいNixOSとNixを利用している (2022/12~) ・ちょっとOSS活動
・NixOS/nix: 1 PR merged ・NixOS/nixpkgs: 36 PRs merged, 197 PRs reviewed ・nixpkgs用のLinterを作りたいな〜と思っています ・興味がある方、ぜひお話ししましょう! 自己紹介 @momeemt @mutsuha_asada https://momee.mt 2
概要 ・組版処理システムであるSATySFiのパッケージビルドをnixpkgsでサポートしたい ・そのためのderivationを追加する作業をしているので今日はそれについて話す ・NixOS/nixpkgs #372555 ( 🚧 WIP 🚧) 📚
目次 nixpkgsにおけるSATySFiサポートの現状 1. NixによるSATySFiビルドの先行研究 2. satyrographosInstallHookの実装(パッケージビルドのサポート) 3. パッケージの依存解決の実装(パッケージを利用可能にする) 4. 今後の課題・展望 5. まとめ 6. 3
1. nixpkgsにおけるSATySFiサポートの現状 4
SATySFi ・gfngfn氏によって開発された静的型付き組版処理システム ・ 🐪 OCamlで実装されている ・LaTeXとは異なり可読性が高く、詳細なエラー報告が実現されている ・SATySFiパッケージの多くはOCamlのソースコードは含まれないが、 Opamパッケージとして配布されている ・公式のパッケージマネージャやビルドツールは存在しないが、 Satyrographosという有志により開発されたパッケージマネージャがある
→ ~/.opam/<ocaml-version>/share/satysfi/<package> にインストールされた SATySFiパッケージを、~/.satysfi/dist にコピーする 5
現状 ・ 🙆♀️ nixpkgs 24.11ではSATySFiとemacsのSATySFiプラグインが利用可能 ・ 😞 third-party製のパッケージ、LSPなどの周辺ツールはなく、実用的ではない ▲ 寂しい
6
動機 ・個人的な経験として、SATySFiは環境構築が複雑 → 1年生の頃、新歓パンフレットの組版に利用したが Dockerイメージを作って環境を配布した ・opam installでコケたり、依存関係でコケたり... ・mt-caret氏によりnixpkgsにSATySFiが追加されている → PythonやOCamlのようにパッケージやLSPも入れれば
気軽にSATySFiで文書を書ける! 7
2. NixによるSATySFiビルドの先行研究 8
・ ・2つのderivationを提供 ・文書をビルドするための`buildDocument` ・パッケージをビルドするための`buildPackage` 先行研究① (AumyF/satyxin) 9
先行研究① (AumyF/satyxin) 10
先行研究① (AumyF/satyxin) 11
先行研究① (AumyF/satyxin) ・パッケージをビルドするときに、setupHookにより環境変数SATYSFI_LIBPATHに 当該パッケージのパス($1/lib/satysfi)が追加される ・ドキュメントをビルドする際には、SATYSFI_LIBPATHをコンパイラに渡すことで コンパイラがパッケージを見つけられるようにする ・ 👏 良い点 ・パッケージ名とパス、ソースを渡すだけでパッケージングができる
・わかりやすく明快 ・ ☹️ 機能不足な点 ・フォントやハッシュファイルなど、lib/satysfi/dist/packages 以外に配置するべきファイル をコピーすることができない ・複数のファイルを含むパッケージに対応できない ・devShell環境ではコンパイラからパッケージが見えていない 12
先行研究② (SnO2WMaN/satyxin) ・AumyF/satyxinのフォーク ・既にパッケージング済みのパッケージを多数提供していて、簡単に始められる ・フォーク元で不足していたpackages以外のファイル/ディレクトリや複数ファイルを含む パッケージにも対応している 13
先行研究② (SnO2WMaN/satyxin) ・installPhaseで、packages以外の パッケージ要素(フォント、ハッシュなど)の 存在をチェックしてコピーすることで、 適切にファイルを配置できる◎ ・フォントハッシュのマージにも対応(後述) 14
先行研究② (SnO2WMaN/satyxin) ・フォーク元とは異なり、`buildSatysfiDist`を提供 ・これは依存パッケージをプロジェクトルートに生成するためのderivation ・SATySFiコンパイラはパッケージパスとしてプロジェクトルートを参照する → devShell環境でコンパイラがパッケージを見つけられる 15
先行研究② (SnO2WMaN/satyxin) ・satysfi-zrbaseのパッケージング ・依存パッケージがなく最もシンプル ・`build-package`を利用して、 コピー対象のファイルを明示的に`copyfrom`へ指定 16
先行研究② (SnO2WMaN/satyxin) ・ 👏 良い点 ・パッケージ名とパス、ソースを渡すだけでパッケージングができる ・フォントやハッシュファイルなども含めてビルドできるので、 全てのSatyrographosに対応したSATySFiパッケージをパッケージングできる ・複数のファイルを含むパッケージに対応◎ ・devShell環境でもコンパイラからパッケージが見える
・ ☹️ 機能不足な点 ・ハッシュファイルのマージスクリプトにバグがあり、ときおり壊れる ・Satyrographosのビルドファイル(Satyristes)に コピー対象のファイルが与えられている(library.source)が、明示的に記述する必要がある ・ローカルに.satysfiDistを生成する必要がある(nix-direnvが実質的には必要) 17
3. satyrographosInstallHookの実装 18
インストール工程の共通化 ・SATySFiパッケージをパッケージングする際に複雑なのはインストール工程 ・たとえば... ・satyファイルやフォントファイルなどのソースをコピーする ・フォントファイルが複数ある場合にはハッシュファイルをマージする ・実は(`buildSATySFiPackage`のような)ビルダーから提供する必要はない ・ビルドやパッチなど他の工程も複雑だったり、特殊な工程のAPIを提供したりしたい場合は ビルダーを実装する価値があるが、今回のケースはそうではない ・インストール工程のみをスクリプトとして括り出してフックとして提供すれば 🆗
→ 既存のフックの実装はどうなっているだろうか...? 19
pip-install-hook ・たとえば、Pythonのパッケージマネージャであるpipのインストールフックを眺めてみる ・スクリプトの処理 ・pipを利用して、distは以下のwheelを出力先に展開する ・環境変数`PYTHONPATH="$out/@pythonSitePackages@"`を設定することで、 `prefix=”$out”`のようにpipからライブラリが見えるように実行できる 20
pkgs.makeSetupHook ・ここで、`pkgs.makeSetupHook` によってフックを作成している ・フックとして定義されたderivationは、`stdenv`側で自動的に呼び出される ・したがって、`nativeBuildInputs`に追加しておくだけで`installPhase`を書き換えられ、 結果的にwheelを出力先に展開することができる 21
Satyrographos ・SATySFiのデファクトスタンダードなパッケージマネージャ ・Satyristesというビルドファイルを読んでビルドを代行する ・多くのSATySFiパッケージはSatyrographosを利用して開発されている → これを利用したインストールフックを実装すればビルド工程を共通化できる ・実際、Satyrographosはそのようなソフトウェアであり、 インストールフックの実装はエミュレートするスクリプトを実装することと同じ → では、Satyristesの仕様を見てみよう
💪 22
Satyristes https://github.com/na4zagin3/satyrographos/blob/master/README.md#satyristes-file-syntax 23
Satyristes ・library宣言の、特に sources が重要 ・ここに配置するべきソースとパスが記述されている ・例えば、mypackageという名前のパッケージにおいて (font “/dst” “/src”) は、/src
配下のファイルを dist/fonts/mypackage/ 以下に配置する ・name はパスを特定するために必要 ・version, opam, dependencies, compatibility は無視できる ・そもそもこのファイルはS式によって記述されている ・S式をパースできるライブラリを利用して該当の処理を行えば良さそう ・今回はsexpdataというライブラリを用いてPythonスクリプトを書く 24
satyrographosInstallHook ・実装したPythonスクリプトを用いて インストールフックを定義する ・このフックを利用することで、 nativeBuildInputs = [ satyrographosInstallHook ]; だけでインストール工程が行われる
25
satysfi-zrbaseのパッケージング 26 記述量が多く、 パッケージごとの差異もあってかなり大変 😕
フックを利用したsatysfi-zrbaseのパッケージング 27 処理が共通化されて すっきりまとまるようになった! 🌟
satyxinによるsatysfi-zrbaseのパッケージング (再掲) 28 satyxinと比べても、Satyristesを用いた インストールフックの恩恵は大きい
29 4. パッケージの依存解決の実装
/nix/store /nix/store/xxx-satysfi-0.0.11 bin シェル環境でコンパイラからパッケージが見えない ・各パッケージは /nix/store 以下に結果が作成されるので、 何らかの方法でパスを渡さなければコンパイラからパッケージが見えない 30 lib
share ~/.satysfi ~/doc/nix-meetup (プロジェクトルート) /nix/store/xxx-satysfi- zrbase-0.4.0 /nix/store/xxx-satysfi- fss-0.2.0 利用したいパッケージはここにいるのに... 👀
/nix/store /nix/store/xxx-satysfi-0.0.11 bin lib share ~/.satysfi ~/doc/nix-meetup (プロジェクトルート) /nix/store/xxx-satysfi- zrbase-0.4.0
/nix/store/xxx-satysfi- fss-0.2.0 $SATYSFI_LIBRARY シェル環境でコンパイラからパッケージが見えない ・AumyF/satyxinでは、セットアップフックで環境変数 SATYSFI_LIBRARY にパッケージの パスが追記されるようにした上で、ビルド時にコンパイラにパスを渡していた → この方法ではシェル環境ではいちいちコンパイラに引数を渡す必要があるし、 LSPなどのツールチェーンにも同様の手間が発生する 31 --config
シェル環境でコンパイラからパッケージが見えない ・SnO2WMaN/satyxinでは、プロジェクトルートにパッケージがコピーされるような derivationを提供していた → この方法だとコンパイラのデフォルトの探索先なので手間が必要ない◎ → 一方で、nix-direnvの利用が必須になる 32 /nix/store /nix/store/xxx-satysfi-0.0.11
bin lib share ~/.satysfi ~/doc/nix-meetup /nix/store/xxx-satysfi- zrbase-0.4.0 /nix/store/xxx-satysfi- fss-0.2.0 $SATYSFI_LIBRARY --config /nix/store/xxx-satysfi- zrbase-0.4.0 /nix/store/xxx-satysfi- fss-0.2.0 link link
シェル環境でコンパイラからパッケージが見えない ・できればどちらの問題も解決した上でシェル環境で扱えるようにしたい... 😖 ・つまり、コンパイラがデフォルトで探索するパスに環境に入った時点でパッケージを配置したい → SATySFiの $out/share/satysfi/dist にパッケージをコピーすれば良いのでは? 33 /nix/store
/nix/store/xxx-satysfi-0.0.11 bin lib share ~/.satysfi ~/doc/nix-meetup (プロジェクトルート) /nix/store/xxx-satysfi- zrbase-0.4.0 /nix/store/xxx-satysfi- fss-0.2.0 zrbase fss copy copy
SATySFiがパッケージセットを受け取るようにする ・SATySFiのderivationを見て、パッケージセットを受け取って配置するようにする → パッケージを使いたいときは、override してパッケージを渡す ・override は、derivationの引数を書き換えることができる機能 34 ▲ このような使い方を想定
依存パッケージの解決をする ・SATySFiのパッケージには依存関係がある ・たとえば、fssはbaseに依存しており、baseはfonts-dejavuとtestに依存している ・パッケージの依存は dependencies に記述する(規約)ことにして、 畳み込み関数を使って再帰的に依存するパッケージを集めてくる 35
集めたパッケージをshare/satysfi/distに配置 ・基本的には $out/share/satysfi/dist を再配置するだけ ・しかし、フォントのハッシュファイルを適切にマージする必要がある 36
フォントハッシュファイルのマージ ・フォントハッシュファイルは、フォント名に対してメタデータを引くためのファイル ・JSONではなく、Yojsonによって記述されている → https://mjambon.github.io/mjambon2016/yojson.html ・普通のJSONパーサではパースできない記法が含まれている... 😞 ・実はYojsonに対する複雑な操作が行われることはなく、2つのYojsonを結合するだけ → 同様にPythonで正規表現を使った結合スクリプトを書いてderivationを定義
・1ページ前のスクリプトにあるように、すでにハッシュファイルが存在している場合には 結合スクリプトを呼び出して適切にマージされるように実装した 37
パッケージセットをトップレベルに定義する ・定義したSATySFiのパッケージは、pkgs.satysfiPackages.xxx のように アクセスできると便利!☺️ → pkgs/top-level/satysfi-packages.nix にパッケージのエイリアスを張って、 pkgs/top-level/all-packages.nix で satysfiPackages
にまとめる 38 ▲ さっきのshell.nixが使えるように! ✊
次のリポジトリで試すことができます ・momeemt/nix-satysfi-sandbox ・興味があれば触ってみてください 🙌 39
40 5. 今後の課題・展望
・パッケージのドキュメント(libraryDoc属性)について全く実装していない ・最終的にはドキュメントを $out/share/doc に生成するようにしたい ・パッケージドキュメントはパッケージに依存するので工夫しないと循環する ・Yojsonを真面目にパースしていないので壊れる可能性がある(前例があるため) ・SatyristesをパースするPythonスクリプトをシェルスクリプトに埋め込んでいるため 保守性に不安がある ・SATySFi、Nixについて経験があるそこのあなた! 🫵
・レビューにご協力いただけるとありがたいです! ・指摘、ご意見などどんなことでも構いません ・NixOS/nixpkgs #372555 です! 現在わかっている課題点 41
展望 ・目下の目標はmasterにマージされてunstableで利用できるようにすること ・中期的には以下のようなツールもnixpkgsに入れたい ・SATySFiパッケージ(約80個ある) ・satysfi-language-server, satysfi-formatter ・SATySFi v0.1.0で新しく入るエコシステム(プロトタイプはSapheと呼ばれている)が 実用されるようになったらそちらのサポートも行う ・テストへの対応
・SATySFiは全然関係ないですが、nixpkgsを支えるインフラや自動化ツールについて もっと解像度を深めて有用なツールを作ることができればいいなと思っています 🪄 42
43 6. まとめ
まとめ ・現在取り組んでいる、NixOS/nixpkgsへのSATySFiビルドサポートについて紹介した ・現状(nixpkgs 24.11)ではSATySFi本体とemacsの拡張機能のみが存在している状態であり、 環境構築を容易にするためにはSATySFiパッケージや周辺ツールの拡充が必要 ・特にSATySFiパッケージのパッケージングをサポートするderivationをnixpkgsに導入したい ・過去の事例としては、セットアップフックと環境変数を組み合わせてパッケージビルド、 ドキュメントビルドを提供するAumyF/satyxinや、より高度なビルダーや パッケージセットを含むdistを生成する機能を提供するSnO2WMaN/satyxinなどがあった ・今回の発表では、Satyrographosのビルドファイルを用いてパッケージのインストール工程を
共通化するフックであるsatyrographosInstallHookの実装と、 SATySFiへのパッケージオーバーロードを拡張する方法について説明した ・シェル環境でコンパイラからパッケージが見えるようにするために、SATySFiの share/satysfi/distに依存パッケージを集めてきて、マージハッシュを行った上で格納した ・パッケージのドキュメントビルド、derivationが循環することの解消、YojsonやSatyristesの 仕様に適切に則った堅牢なスクリプトに修正していくことなどが今後の課題 44