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
250
❄️ 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
690
情報科学類で学べる専門科目38選
momeemt
0
590
❄️ tmux-nixの実装を通して学ぶNixOSモジュール
momeemt
1
250
Wasmで拡張できる軽量マークアップ言語 Brack
momeemt
0
110
Intel系FPGA上へのRISC-Vプロセッサの実装
momeemt
0
150
情報科学若手の会 2024 LT「WebAssemblyで拡張可能な軽量マークアップ言語の開発」
momeemt
0
47
Nixでつくるdotfiles
momeemt
1
63
情報特別演習I 最終発表「理工学の紙書籍を用いた学習の効率を向上させるインタフェース」
momeemt
0
41
SATySFi Conf 2023「SATySFiを使って学類新歓冊子を発行した」
momeemt
0
27
Other Decks in Programming
See All in Programming
Rancher と Terraform
fufuhu
2
550
Namespace and Its Future
tagomoris
6
710
今だからこそ入門する Server-Sent Events (SSE)
nearme_tech
PRO
3
240
Introducing ReActionView: A new ActionView-compatible ERB Engine @ Rails World 2025, Amsterdam
marcoroth
0
710
デザイナーが Androidエンジニアに 挑戦してみた
874wokiite
0
540
FindyにおけるTakumi活用と脆弱性管理のこれから
rvirus0817
0
530
アプリの "かわいい" を支えるアニメーションツールRiveについて
uetyo
0
270
Azure SRE Agentで運用は楽になるのか?
kkamegawa
0
2.4k
複雑なフォームに立ち向かう Next.js の技術選定
macchiitaka
2
180
ファインディ株式会社におけるMCP活用とサービス開発
starfish719
0
1.9k
Deep Dive into Kotlin Flow
jmatsu
1
360
請來的 AI Agent 同事們在寫程式時,怎麼用 pytest 去除各種幻想與盲點
keitheis
0
120
Featured
See All Featured
The Invisible Side of Design
smashingmag
301
51k
Documentation Writing (for coders)
carmenintech
74
5k
How GitHub (no longer) Works
holman
315
140k
Rails Girls Zürich Keynote
gr2m
95
14k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
GraphQLの誤解/rethinking-graphql
sonatard
72
11k
[RailsConf 2023] Rails as a piece of cake
palkan
57
5.8k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
580
A designer walks into a library…
pauljervisheath
207
24k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
920
Music & Morning Musume
bryan
46
6.8k
Facilitating Awesome Meetings
lara
55
6.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