<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://katei.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://katei.dev/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-09-11T02:35:58+09:00</updated><id>https://katei.dev/feed.xml</id><title type="html">Yuta Saito</title><subtitle>Software engineer working on Swift, Ruby, and WebAssembly.</subtitle><entry><title type="html">近況 2026/09</title><link href="https://katei.dev/blog/2026/09/09/update" rel="alternate" type="text/html" title="近況 2026/09" /><published>2026-09-09T21:22:04+09:00</published><updated>2026-09-09T21:22:04+09:00</updated><id>https://katei.dev/blog/2026/09/09/update</id><content type="html" xml:base="https://katei.dev/blog/2026/09/09/update"><![CDATA[<p>二月ごろから仕事でロンドンで働いていた。いた、というのは最近ようやく東京に帰って来れたのだ。</p>

<p>結局半年ほどロンドンにいたわけだが、良くも悪くも色々経験できたと思う。</p>

<p>よかったこと</p>
<ul>
  <li>ユーロスターで気軽にヨーロッパ旅行できる。国内も公共交通機関はそれなりに便利。</li>
  <li>ミュージアムは基本入場料がタダ。週末やることに困らない。</li>
  <li>適当なパブでもいろんな種類のクラフトビールが飲める。結局Neck Oilが一番好きだった。</li>
  <li>周りに移民が多かったので外国人として過ごすには楽だったと思う。</li>
</ul>

<p>驚いたこと</p>
<ul>
  <li>歩行者信号はみんな守らない。</li>
  <li>グリニッジ展望台は意外と小さい。</li>
  <li>エアコンの設置率が本当に低い。ヒートウェーブの週のエアコン無しの地下鉄の中で死を覚悟した。夏は過ごしやすいと聞いてたのに。話と違う！</li>
  <li>食に関しては本当にマズいものに出くわすことはそうそう無い。（自分の中ですでに基準が調整されてるかも）<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></li>
</ul>

<p>というわけで長い出張から日本に帰ってきた。</p>

<p>これは毎日通ったパディントン駅にいる熊。</p>

<p><img src="/assets/images/20260911-paddington.jpg" alt="" /></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p><a href="https://en.wikipedia.org/wiki/Itsu">Itsu</a>という日本食チックなファストフード店が出してる”Chilli miso noodles”というカップ麺だけは想像を絶した。機会があったら食べてみてほしい。 <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name></name></author><summary type="html"><![CDATA[二月ごろから仕事でロンドンで働いていた。いた、というのは最近ようやく東京に帰って来れたのだ。]]></summary></entry><entry><title type="html">Swift 6.2でWebAssemblyサポートを公式化した</title><link href="https://katei.dev/blog/2025/09/20/214804/" rel="alternate" type="text/html" title="Swift 6.2でWebAssemblyサポートを公式化した" /><published>2025-09-20T21:48:04+09:00</published><updated>2025-09-20T21:48:04+09:00</updated><id>https://katei.dev/blog/2025/09/20/2025-09-20-214804</id><content type="html" xml:base="https://katei.dev/blog/2025/09/20/214804/"><![CDATA[<p>Swift 6.2 のリリースで、公式に WebAssembly ターゲットをサポートしました。</p>

<p><a href="https://www.swift.org/blog/swift-6.2-released/#webassembly-support" target="_blank" rel="noopener noreferrer">https://www.swift.org/blog/swift-6.2-released/#webassembly-support</a></p>

<p><blockquote data-conversation="none" class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">With ✨Swift 6.2 ✨, you can now target WebAssembly, including WASI support. Get started here: <a href="https://t.co/iNMnNgto6D" target="_blank" rel="noopener noreferrer">https://t.co/iNMnNgto6D</a> <a href="https://twitter.com/hashtag/Wasm?src=hash&amp;ref_src=twsrc%5Etfw" target="_blank" rel="noopener noreferrer">#Wasm</a> <a href="https://t.co/2oIdeXBtQA" target="_blank" rel="noopener noreferrer">pic.twitter.com/2oIdeXBtQA</a></p>&mdash; Swift Language (@SwiftLang) <a href="https://twitter.com/SwiftLang/status/1968398412329730180?ref_src=twsrc%5Etfw" target="_blank" rel="noopener noreferrer">September 17, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>  </p>

<h2 id="61から何が変わったか">6.1から何が変わったか</h2>

<p><a href="https://zenn.dev/katei/articles/swiftwasm-6-1-release" target="_blank" rel="noopener noreferrer">SwiftWasm 6.1のリリースを自慢したい</a> でも書いた通り、6.1 の時点で必要なパッチはすべてアップストリーム済みでした。ただし当時は WebAssembly 向けの Swift SDK を swiftwasm 側が配布していました。6.2 からはこれが swift.org から提供されます。基本的には「配布元が変わっただけ」で機能差はありません。</p>

<p>とはいえこれは信用の話として効いてきます。これまでは Swift SDK がサードパーティからの配布だったため、いくつかのSwiftパッケージにWasm の CI チェックを入れる提案に渋い反応をもらうことがありました。今回公式化されたことで話が通りやすくなり、実際にいろんなパッケージで Wasm ビルドを CI に入れてもらえるようになりました。</p>

<h2 id="WasmKit-が同梱">WasmKit が同梱</h2>

<p>6.2 の OSS ツールチェイン（Xcode 同梱版ではなく swift.org で配布される方）には、僕がswiftwasm で引き継いで開発している WebAssembly ランタイム <a href="https://github.com/swiftwasm/WasmKit" target="_blank" rel="noopener noreferrer">WasmKit</a> も同梱されています。コンパイラツールチェインにWasmランタイムが同梱されているのはなかなか珍しいと思います。</p>

<h2 id="おわりに">おわりに</h2>

<p>公式ドキュメントに step-by-step のガイドがあるので試してみてください。
<a href="https://www.swift.org/documentation/articles/wasm-getting-started.html" target="_blank" rel="noopener noreferrer">https://www.swift.org/documentation/articles/wasm-getting-started.html</a></p>]]></content><author><name></name></author><summary type="html"><![CDATA[Swift 6.2 のリリースで、公式に WebAssembly ターゲットをサポートしました。]]></summary></entry><entry><title type="html">2024年の振り返り</title><link href="https://katei.dev/blog/2024/12/31/171101/" rel="alternate" type="text/html" title="2024年の振り返り" /><published>2024-12-31T17:11:01+09:00</published><updated>2024-12-31T17:11:01+09:00</updated><id>https://katei.dev/blog/2024/12/31/2024-12-31-171101</id><content type="html" xml:base="https://katei.dev/blog/2024/12/31/171101/"><![CDATA[<h2 id="大学院">大学院</h2>

<p>今年はM2をやっていた。授業はM1で取り切っていたので研究をひたすら頑張る形。
去年は渡米や諸々によりほとんど進捗がなかったが（たいへん申し訳ない気持ち）、今年は国際ジャーナルを通せたので良かった。</p>

<p>なお修論は全く別のテーマで書いているので現在進行形で大変マズい状況。修了したい。</p>

<h2 id="仕事">仕事</h2>

<p>引き続きGoodnotesでパートタイムで働いている。ロールも変わらずSwiftコンパイラツールチェインとWebAssemblyを仲良くさせる仕事。</p>

<p>ちょうど今年web.devで事例紹介の記事が公開されたので貼っておく。
<a href="https://web.dev/case-studies/goodnotes" target="_blank" rel="noopener noreferrer">Goodnotes everywhere &nbsp;|&nbsp; web.dev</a></p>

<p>チームメイトのおかげでプロダクトも育ってきており良い感じ。今年も相当量のSwiftのコードが新しくWebと共有できた。クロスプラットフォームなコードが増えていくたびちょっと嬉しい。</p>

<h2 id="就職">就職</h2>

<p>就活をしてもいいかなと思ってはいたが気がついたら25卒のウィンドウが閉じていたので結果的にほとんど何もしていない。</p>

<p>ありがたいことに大変良いオファーをもらえたので4月からもGoodnotesで働き続ける。ハーフタイマーだったのがフルタイマーにジョブチェンジ。拠点も移すことなく東京からフルリモート。</p>

<h2 id="OSS">OSS</h2>

<h3 id="Swift">Swift</h3>

<p>今年は仕事で必要な話しか進められなかった印象。目立った（といっても別にどこかで宣伝したわけじゃない）話としては</p>

<ul>
<li><p>WasmでSwiftのランタイムメタデータをうまく扱えるようにオブジェクトファイルの仕様に手を入れたり
<a href="https://github.com/llvm/llvm-project/pull/81539" target="_blank" rel="noopener noreferrer">[WebAssembly] Add segment RETAIN flag to support private retained data by kateinoigakukun &middot; Pull Request #81539 &middot; llvm/llvm-project &middot; GitHub</a></p></li>
<li><p>WebAssemblyターゲット上のコードカバレッジ収集に対応したり（これはSwiftに依存しない話）
<a href="https://github.com/llvm/llvm-project/pull/111332" target="_blank" rel="noopener noreferrer">[Coverage][WebAssembly] Add initial support for WebAssembly/WASI by kateinoigakukun &middot; Pull Request #111332 &middot; llvm/llvm-project &middot; GitHub</a></p></li>
<li><p>スレッド生成に対応したターゲット（<code>wasm32-unknown-wasip1-threads</code>）を追加した。</p></li>
</ul>


<p>地味な話題としてはswift-foundationへの移行に伴い<a href="https://github.com/swiftwasm/swift/issues/5586" target="_blank" rel="noopener noreferrer">大量のパッチを書いた</a></p>

<p>コミュニティでは自分以外からWasmに関する話がいくつか出たのはよかった。</p>

<ul>
<li><a href="https://youtu.be/mfrGe4e_fSs?si=ucqEgp9K94CXkndm" target="_blank" rel="noopener noreferrer">Introduction to WebAssembly for Swift Developers - Max Desiatov | SwiftLeeds 2024
</a></li>
<li><a href="https://www.pointfree.co/episodes/ep291-cross-platform-swift-webassembly" target="_blank" rel="noopener noreferrer">Episode #291: Cross-Platform Swift: WebAssembly</a></li>
</ul>


<h3 id="Ruby">Ruby</h3>

<p>ruby.wasmにDynamic Linking対応を入れた。本質的に難しくないはずなんだけど、ビルドプロセスが複雑になりすぎててなかなか手間取った。</p>

<p>その成果としてRailsがブラウザで動くようになった。なんとMastodonやRedmineも動いた。
Mastodonがブラウザで動いて何が嬉しいのかは自分でも分かってない。無意味で楽しい。</p>

<ul>
<li><a href="https://www.farend.co.jp/blog/2024/10/redmine-in-the-browser/" target="_blank" rel="noopener noreferrer">ruby/ruby.wasm &#x3092;&#x4F7F;&#x3063;&#x3066; Redmine &#x3092;&#x30D6;&#x30E9;&#x30A6;&#x30B6;&#x5185;&#x3067;&#x52D5;&#x304B;&#x3059;&#x8A71; - &#x30D5;&#x30A1;&#x30FC;&#x30A8;&#x30F3;&#x30C9;&#x30C6;&#x30AF;&#x30CE;&#x30ED;&#x30B8;&#x30FC;&#x682A;&#x5F0F;&#x4F1A;&#x793E;</a></li>
<li><a href="https://speakerdeck.com/palkan/sf-ruby-march-2024-rails-on-wasm" target="_blank" rel="noopener noreferrer">[SF Ruby, March 2024] Rails on Wasm - Speaker Deck</a></li>
<li><a href="https://speakerdeck.com/kateinoigakukun/rubygems-on-ruby-dot-wasm" target="_blank" rel="noopener noreferrer">RubyGems on ruby.wasm - Speaker Deck</a></li>
</ul>


<h2 id="登壇">登壇</h2>

<ul>
<li>try! Swift Tokyo 2024 <a href="https://speakerdeck.com/kateinoigakukun/building-a-smaller-app-binary" target="_blank" rel="noopener noreferrer">Building a Smaller App Binary - Speaker Deck</a></li>
<li>RubyKaigi 2024 （沖縄） <a href="https://speakerdeck.com/kateinoigakukun/rubygems-on-ruby-dot-wasm" target="_blank" rel="noopener noreferrer">RubyGems on ruby.wasm - Speaker Deck</a></li>
<li>EuRuKo 2024 （サラエボ） <a href="https://speakerdeck.com/kateinoigakukun/what-you-can-do-with-ruby-on-webassembly" target="_blank" rel="noopener noreferrer">What you can do with Ruby on WebAssembly - Speaker Deck</a></li>
<li>Swift Server Side Meetup #3  <a href="https://speakerdeck.com/kateinoigakukun/running-swift-on-webassembly-platforms" target="_blank" rel="noopener noreferrer">Running Swift on WebAssembly Platforms - Speaker Deck</a></li>
</ul>


<p>招待して頂いたEuRuKoではElixirのJosé Valimと話せて良かった。
サラエボ旅行のハイライト（たまたま行きも帰りもMatzと同じ便だった）:
<blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「ドーハ行きはチェックインあと2分です」と言われてまつもとさんと顔を見合わせる瞬間があった😶</p>&mdash; Yuta Saito (@kateinoigakukun) <a href="https://twitter.com/kateinoigakukun/status/1834893300039401514?ref_src=twsrc%5Etfw" target="_blank" rel="noopener noreferrer">2024年9月14日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>  </p>

<h2 id="旅行">旅行</h2>

<p>しれっと友達と南米旅行に行ってきた。かなり良かった。英語が通じないことと高山病とトイレットペーパーが流せないことだけは大変だった。</p>

<h2 id="まとめ">まとめ</h2>

<p>比較的健康に過ごせたので良かったと思う。では修論に戻ります。</p>]]></content><author><name></name></author><summary type="html"><![CDATA[大学院]]></summary></entry><entry><title type="html">RubyKaigiとiOSDCでWasmの話をしてきた</title><link href="https://katei.dev/blog/2022/09/18/215351/" rel="alternate" type="text/html" title="RubyKaigiとiOSDCでWasmの話をしてきた" /><published>2022-09-18T21:53:51+09:00</published><updated>2022-09-18T21:53:51+09:00</updated><id>https://katei.dev/blog/2022/09/18/2022-09-18-215351</id><content type="html" xml:base="https://katei.dev/blog/2022/09/18/215351/"><![CDATA[<p>09/08-10に三重で開催されたRubyKaigi、09/10-12に東京で開催されたiOSDCにどちらもスピーカーとして参加してきました。</p>

<p>カンファレンスはしごされた方はお疲れ様でした。</p>

<h2 id="RubyKaigi-Keynote">RubyKaigi Keynote</h2>

<p>初めてのRubyKaigiでの発表で、さらにキーノートで、さらにトップバッターという大変貴重な体験でした。いやー緊張した。<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p>

<p>当日のスライドはこちら。</p>

<script async class="speakerdeck-embed" data-id="fbfddfe5eccb4700a3ae600b814a9ce9" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>


<p>Ruby 3.2でサポート予定のRubyのWebAssembly/WASI対応について話してきました。</p>

<p>前半でモチベーションや出来るようになったことをデモを交えつつオーディエンスと共有して、後半は実装について自分の好きなことを話す、という構成でした。</p>

<p><a href="https://github.com/ruby-syntax-tree/syntax_tree" target="_blank" rel="noopener noreferrer"><code>syntax_tree</code></a>を使ったデモはちょっと上手くいかなかったんですが <sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>、
一番見せたかったIRBでSVGを表示するデモがうまくいって良かったです。IRBのデモはこちらで遊べます。</p>

<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Firb-wasm.vercel.app%2F" title="irb.wasm: IRB on browser powered by wasm" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="http://irb-wasm.vercel.app/" target="_blank" rel="noopener noreferrer">irb-wasm.vercel.app</a></cite></p>

<p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">SVG画像綺麗〜 <a href="https://twitter.com/hashtag/rubykaigi?src=hash&amp;ref_src=twsrc%5Etfw" target="_blank" rel="noopener noreferrer">#rubykaigi</a> <a href="https://t.co/ODy1I1f7Ar" target="_blank" rel="noopener noreferrer">pic.twitter.com/ODy1I1f7Ar</a></p>&mdash; 桐生あんず@BOOTH新刊出てます (@anzu_mmm) <a href="https://twitter.com/anzu_mmm/status/1567696955928883200?ref_src=twsrc%5Etfw" target="_blank" rel="noopener noreferrer">2022年9月8日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p>

<p>少しでもKaigiを盛り上げられたなら嬉しいです。発表練習に付き合ってくださった皆さんありがとうございました。</p>

<p>さっそく遊んでくださっている方もちらほら見られたり、「WebAssemblyのことは今まであまり知らなかったけど興味が出てきた」といった声を頂くこともあり、大きな場で話す機会の重要性を実感しました。</p>

<p>最終日途中でiOSDCの方に移動してしまったのでクロージングはきちんと見られていないんですが、TRICKの受賞作品をブラウザで動かすというアツい展開もあったようですね。</p>

<h3 id="気になったトーク">気になったトーク</h3>

<p><a href="https://rubykaigi.org/2022/presentations/k0kubun.html#day1" target="_blank" rel="noopener noreferrer">Towards Ruby 4 JIT - RubyKaigi 2022</a></p>

<p>コンパイラ側の気持ちに興味があるため、JITの話はかなり面白かったです。自分で手軽にJITコンパイラをかける口があるとのことなので試してみたいと思います。特にLLVMよりコンパイル時間が安く済むと噂のCraneliftは一度試してみたいので。</p>

<p><a href="https://rubykaigi.org/2022/presentations/jemmaissroff.html#day2" target="_blank" rel="noopener noreferrer">Implementing Object Shapes in CRuby - RubyKaigi 2022</a></p>

<p>Object Shapeの話も直感的にはグッと速くなるのかなと思っていたんですが、意外と伸び悩んでいたのでどこに原因があるのか、そもそもここにネックはないのか？と色々と考えることがあって面白いなと。これも追っていきたいです。</p>

<p><a href="https://rubykaigi.org/2022/presentations/alanwusx.html#day3" target="_blank" rel="noopener noreferrer">Stories from developing YJIT - RubyKaigi 2022</a></p>

<p>例によってこれも実際には聴けていないんですが、反応を見る限りかなり自分の興味に合いそうなので気になっています。動画が出たらすぐに見たい。</p>

<h3 id="おいしいRubyKaigi">おいしいRubyKaigi</h3>

<p>ありがたいことに大変おいしい思いをさせていただきました。
うなぎも松坂牛もウマー😋 ご馳走様でした。</p>

<div class="images-row mceNonEditable"><span itemscope itemtype="http://schema.org/Photograph"><img src="/assets/images/hatena/20220918154712.jpg" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="/assets/images/hatena/20220918155043.jpg" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></div>


<h2 id="iOSDC">iOSDC</h2>

<p>RubyKaigi最終日の昼過ぎに会場を出て、iOSDC初日の終わりの方から参加していました。iOSDCでは今年で通算4回目の発表でした。</p>

<p>懲りずに自分がメンテしているSwiftWasmプロジェクトについての発表だったんですが、今年はプロダクションでの採用事例やデモを多めにすることで、「あれ、意外ともう使えるんじゃないか？」と思ってもらうことがメインの狙いでした。どうでしたか？</p>

<script async class="speakerdeck-embed" data-id="28758222163d4fd085bd04ef64dd8fd4" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>


<p>また、実際に手を動かしてコントリビューションしてくださる例もあり、大変ありがたかったです。</p>

<p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">iOSDCで <a href="https://twitter.com/kateinoigakukun?ref_src=twsrc%5Etfw" target="_blank" rel="noopener noreferrer">@kateinoigakukun</a> が、swiftwasmは多様な難易度/レイヤで取り組めるからやってみてねって言っていたので、チャレンジしてみたら僕でも出来る事がありました！<br>今日からswiftwasmコントリビューターやな！！<a href="https://t.co/k3R92PUppf" target="_blank" rel="noopener noreferrer">https://t.co/k3R92PUppf</a></p>&mdash; noppe (@noppefoxwolf) <a href="https://twitter.com/noppefoxwolf/status/1570024707000504321?ref_src=twsrc%5Etfw" target="_blank" rel="noopener noreferrer">2022年9月14日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p>

<h3 id="気になったトーク-1">気になったトーク</h3>

<p><a href="https://fortee.jp/iosdc-japan-2022/proposal/9d542893-3c30-4077-a85a-1c7ec68caa9c" target="_blank" rel="noopener noreferrer">Xcode &#x304C;&#x9045;&#x3044;! &#x3068;&#x306B;&#x304B;&#x304F;&#x9045;&#x3044;!! &#x9045;&#x3044; Xcode &#x3092;&#x306A;&#x3093;&#x3068;&#x304B;&#x3059;&#x308B;&#x65B9;&#x6CD5; by Yoshimasa Niwa | &#x30C8;&#x30FC;&#x30AF; | iOSDC Japan 2022 - fortee.jp</a></p>

<p>ある程度大きなプロジェクトを経験したことがあったので、共感できることも多かったです。正しく根本の原因を特定し、現実的なワークアラウンドに落とし込んでいく様子はソフトウェアエンジニアリング感がありこうありたいなと思いました。</p>

<h2 id="まとめ">まとめ</h2>

<p>RubyKaigiではほぼ皆さんはじめましての状態だったんですが、おかげさまで楽しいコミュニケーションができました。これからもよろしくお願いします。
iOSDCでは久しぶり皆さんにもご挨拶できたのでオフライン開催ありがたかった…</p>

<p>来年もどちらも参加したいです。（幸い来年は日程が離れてそう）</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>緊張の結果がこれです  <a href="https://twitter.com/kateinoigakukun/status/1567708097900331008" target="_blank" rel="noopener noreferrer">https://twitter.com/kateinoigakukun/status/1567708097900331008</a><a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>これはいまだに原因が分からない… ライブコーディングはむずかしい。<a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
</ol>
</div>]]></content><author><name></name></author><summary type="html"><![CDATA[09/08-10に三重で開催されたRubyKaigi、09/10-12に東京で開催されたiOSDCにどちらもスピーカーとして参加してきました。]]></summary></entry><entry><title type="html">GoodNotesでSwiftWasmの仕事を始めた</title><link href="https://katei.dev/blog/2022/05/25/190556/" rel="alternate" type="text/html" title="GoodNotesでSwiftWasmの仕事を始めた" /><published>2022-05-25T19:05:56+09:00</published><updated>2022-05-25T19:05:56+09:00</updated><id>https://katei.dev/blog/2022/05/25/2022-05-25-190556</id><content type="html" xml:base="https://katei.dev/blog/2022/05/25/190556/"><![CDATA[<p>近況アップデート</p>

<p>5月の初旬からGoodNotes社で働いている。
GoodNotes社はiPad向けノートアプリGoodNotesを開発しているところ。</p>

<p>実は、去年の10月くらいからGoodNotesの人々がSwiftWasmプロジェクトにコントリビュートしてくれていた。
詳細は控えるが、GoodNotesアプリのコードベースをWebAssemblyにコンパイルして、クロスプラットフォームに移植することが目的。</p>

<p>コミュニティのDiscordでそこそこの頻度で社員と議論していたことで、お互いに顔見知りになり、声がかかったという流れ。</p>

<p>働くモチベーションとしては、</p>

<ul>
<li>自分が育てた技術を使ったプロダクトで価値を届けたい</li>
<li>（恐らく）現状自分の価値が最も高い環境でどの程度の評価をされるのか知りたい</li>
</ul>


<p>の2つが大きい。</p>

<p>ロールとしては、プロダクト開発で発生した問題の相談に乗ったり、得られたフィードバックを元に実際に手を動かしてSwiftWasmツールチェインを改善したり、とコンサルタント的な感じ。
大規模なアプリ故のパフォーマンス問題や、製品レベルの品質を達成するための課題など、見えてこなかったポイントが見えてきたので楽しくやっていけそう。</p>

<p>オフィスはロンドンと香港にあるが、割とフルリモートで働いている人が多く、自分も日本からリモートで働いてる。
タイムゾーンを跨いでいるのでコミュニケーションは基本非同期だが、情報共有の工夫やドキュメンテーションの文化のおかげでなんとか働けている。</p>

<p>英語は周りに介護してもらってなんとか…という感じ。</p>

<p>まだ始まったばかりだが、ひとまずここ2週間くらいはチームメンバーからの信頼を得るためにあくせく働いている。</p>]]></content><author><name></name></author><summary type="html"><![CDATA[近況アップデート]]></summary></entry><entry><title type="html">muslでビルドするにはmusl.ccが便利</title><link href="https://katei.dev/blog/2022/02/18/232723/" rel="alternate" type="text/html" title="muslでビルドするにはmusl.ccが便利" /><published>2022-02-18T23:27:23+09:00</published><updated>2022-02-18T23:27:23+09:00</updated><id>https://katei.dev/blog/2022/02/18/2022-02-18-232723</id><content type="html" xml:base="https://katei.dev/blog/2022/02/18/232723/"><![CDATA[<p><a href="https://github.com/webassembly/binaryen" target="_blank" rel="noopener noreferrer">Binaryen</a>のビルド済みwasm-optを使うとセグフォする現象に遭遇した時、ビルドを手元で再現するためにmuslを使う必要があったのでメモ。<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p>

<h2>musl libc</h2>

<p>muslはlibcなので、コンパイラはgccのままsysrootを差し替えることで大体うまいことコンパイルできる。</p>

<p>この設定をmusl-toolsパッケージのmusl-gccラッパーコマンドが勝手にやってくれるが、C++用のラッパーが用意されてなかったりスッとはビルドできない。あとツールチェインに入ってるSanitizer達がglibcを想定してビルドされてたり出来ないことが結構ある。</p>

<p>なので、最初からmuslをターゲットとしてビルドされたツールチェインが欲しくなり、そこでビルド済みのmuslツールチェインを配布している<a href="https://musl.cc" target="_blank" rel="noopener noreferrer">musl.cc</a>が便利。<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup></p>

<pre class="code" data-lang="" data-unlink>$ curl -LO https://musl.cc/x86_64-linux-musl-native.tgz
$ tar xfz x86_64-linux-musl-native.tgz
$ tree -L 1 ./x86_64-linux-musl-native
./x86_64-linux-musl-native
|-- bin
|-- include
|-- lib
|-- libexec
|-- share
|-- usr -&gt; .
`-- x86_64-linux-musl
</pre>


<h2>CMakeで使う</h2>

<p>musl.ccのツールチェインはsysrootをgccコマンドの相対で設定してくれるので、CMAKE_C_COMPILERさえ設定していれば、特に追加で指定する必要はない。</p>

<pre class="code" data-lang="" data-unlink>cmake ../.. -G Ninja \
  -DCMAKE_C_COMPILER=./x86_64-linux-musl-native/bin/gcc \
  -DCMAKE_CXX_COMPILER=./x86_64-linux-musl-native/bin/g++</pre>



<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>これは結局muslのスレッドスタックサイズのデフォルト値がglibcよりかなり小さくてスタックオーバーフローしてただけだった <a href="https://github.com/WebAssembly/binaryen/issues/4401" target="_blank" rel="noopener noreferrer">https://github.com/WebAssembly/binaryen/issues/4401</a><a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>これはOfficialではないが<a href="https://github.com/openjdk/jdk/blob/master/doc/building.md" target="_blank" rel="noopener noreferrer">OpenJDKとかでも使われてる</a><a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
</ol>
</div>]]></content><author><name></name></author><summary type="html"><![CDATA[Binaryenのビルド済みwasm-optを使うとセグフォする現象に遭遇した時、ビルドを手元で再現するためにmuslを使う必要があったのでメモ。1]]></summary></entry><entry><title type="html">Rubyのコミッタになりました</title><link href="https://katei.dev/blog/2022/01/23/004407/" rel="alternate" type="text/html" title="Rubyのコミッタになりました" /><published>2022-01-23T00:44:07+09:00</published><updated>2022-01-23T00:44:07+09:00</updated><id>https://katei.dev/blog/2022/01/23/2022-01-23-004407</id><content type="html" xml:base="https://katei.dev/blog/2022/01/23/004407/"><![CDATA[<p>実は先日 <a href="https://twitter.com/_ko1" target="_blank" rel="noopener noreferrer">ko1</a>さんと<a href="https://twitter.com/mametter" target="_blank" rel="noopener noreferrer">mame</a>さんから推薦をいただき、<a href="https://bugs.ruby-lang.org/issues/18488" target="_blank" rel="noopener noreferrer">Rubyのコミッタになりました。</a></p>

<p>ここ数ヶ月間、Rubyアソシエーションの開発助成プロジェクトとしてCRubyのWASIサポートを進めており、WASIのプラットフォームメンテナが必要ということで。</p>

<p>WASI対応の話はPublickeyさんに良い感じにまとめていただきました。詳しい実装の話は後日書こうと思います。<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p>

<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.publickey1.jp%2Fblog%2F22%2Frubywebassemblywasiwebassemblyruby.html" title="RubyがWebAssemblyのWASI対応へ前進。ブラウザでもサーバでもエッジでもどこでもWebAssembly版Rubyが動くように" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.publickey1.jp/blog/22/rubywebassemblywasiwebassemblyruby.html" target="_blank" rel="noopener noreferrer">www.publickey1.jp</a></cite></p>

<p>正直Rubyのことを聞かれても答えられる自信はありませんが、CRubyの実装はほんのり分かるようになりました。あとビルドスクリプトはどこもつらい。<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup></p>

<p>という訳で、晴れてSwiftとRubyのコミッタという謎の人材になりました。
引き続きどちらもやっていくので、よろしくおねがいします。</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>書きました <a href="https://itnext.io/final-report-webassembly-wasi-support-in-ruby-4aface7d90c9" target="_blank" rel="noopener noreferrer">An Update on WebAssembly/WASI Support in Ruby | by kateinoigakukun | ITNEXT</a><a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>SwiftはカスタムターゲットまみれのCMake、CRubyは4000行以上のconfigure.acが…<a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
</ol>
</div>]]></content><author><name></name></author><summary type="html"><![CDATA[実は先日 ko1さんとmameさんから推薦をいただき、Rubyのコミッタになりました。]]></summary></entry><entry><title type="html">TypeProf for IDEの開発をお手伝いしました at クックパッド</title><link href="https://katei.dev/blog/2021/09/12/123857/" rel="alternate" type="text/html" title="TypeProf for IDEの開発をお手伝いしました at クックパッド" /><published>2021-09-12T12:38:57+09:00</published><updated>2021-09-12T12:38:57+09:00</updated><id>https://katei.dev/blog/2021/09/12/2021-09-12-123857</id><content type="html" xml:base="https://katei.dev/blog/2021/09/12/123857/"><![CDATA[<h2>TL;DR</h2>

<ul>
<li>8月週3クックパッドインターン</li>
<li>フルタイムRubyコミッタのチームでTypeProf for IDEの開発</li>
<li>インパクトの大きい貢献チャンスはその辺に転がってるかもしれない</li>
</ul>


<h2>インターンの内容</h2>

<p>TypeProfはクックパッドでフルタイムRubyコミッタをされている<a href="https://twitter.com/mametter" target="_blank" rel="noopener noreferrer">@mametter</a>さんが開発しているRubyの型プロファイラです。
Rubyのプログラムにできるだけ型注釈を入れずに抽象解釈によって型を推論する、という面白い特徴があります。</p>

<p>Ruby 3.0ではRBSのプロトタイプを生成するためのツールとしてRubyにバンドルされています。</p>

<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fruby%2Ftypeprof%2F" title="GitHub - ruby/typeprof: An experimental type-level Ruby interpreter for testing and understanding Ruby code" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/ruby/typeprof/" target="_blank" rel="noopener noreferrer">github.com</a></cite></p>

<p>今回のインターンでは、TypeProfの解析結果を利用したRubyのLanguage Serverの実装をお手伝いしました。</p>

<p>TypeProf for IDEについては<a href="https://rubykaigi.org/2021-takeout/presentations/mametter.html" target="_blank" rel="noopener noreferrer">今年のRubyKaigi Takeout 2021のKeynote</a>で発表があったので、雰囲気を知りたい方はこちらを見てください。</p>

<p><iframe src="https://www.youtube.com/embed/uNttp63ELoE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=uNttp63ELoE" target="_blank" rel="noopener noreferrer">www.youtube.com</a></cite></p>

<p><iframe src="https://www.slideshare.net/slideshow/embed_code/key/9pxYYHtUcXCkvP" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/mametter/typeprof-for-ide-enrich-development-experience-without-annotations" title="TypeProf for IDE: Enrich Development Experience without Annotations" target="_blank">TypeProf for IDE: Enrich Development Experience without Annotations</a> </strong> from <strong><a href="https://www.slideshare.net/mametter" target="_blank">mametter</a></strong> </div>  <cite class="hatena-citation"><a href="https://www.slideshare.net/mametter/typeprof-for-ide-enrich-development-experience-without-annotations" target="_blank" rel="noopener noreferrer">www.slideshare.net</a></cite></p>

<h3>実装</h3>

<p>そもそもRubyを触るのが久々かつ、TypeProfがそこそこ大きいプログラムであったため、<code>binding.irb</code>でデバッグ可能な環境を作るところからはじめました。</p>

<p>これを初手で準備したことでその後のコードリーディング効率が格段に上がりました。やはりデバッガは偉大。</p>




<p><a href="https://github.com/ruby/typeprof/pull/34" target="_blank" rel="noopener noreferrer">Add --port option to lsp server for debugging purpose by kateinoigakukun &middot; Pull Request #34 &middot; ruby/typeprof &middot; GitHub</a></p>

<p>その後mameさんに助けてもらいながら数種類のコードジャンプを実装しました。
ジャンプ先候補はTypeProfの解析結果を使っているので、解析器自体の実装も勉強できて良かったです。</p>

<ul>
<li><a href="https://github.com/ruby/typeprof/pull/36" target="_blank" rel="noopener noreferrer">LSP: Support local variable definition jump</a></li>
<li><a href="https://github.com/ruby/typeprof/pull/39" target="_blank" rel="noopener noreferrer">LSP: Support instance variable definition jump</a></li>
<li><a href="https://github.com/ruby/typeprof/pull/45" target="_blank" rel="noopener noreferrer">LSP: Support Find References for methods</a></li>
<li><a href="https://github.com/ruby/typeprof/pull/47" target="_blank" rel="noopener noreferrer">LSP: Support class/const definition jump</a></li>
</ul>


<p>もうひとつ面白い改善として、コード補完の高速化を行いました。</p>

<p>TypeProf for IDEではユーザが1タイプするごと (<code>textDocument/didChange</code>) にプログラムを解析し直すのですが、解析の仕組み的に一回の解析にかなり時間がかかります。
オリジナルの実装では解析中サーバスレッドをブロックしていたため、タイプするごとに解析待ちのリクエストが溜まっていました。</p>

<p>さらに、コード補完 (<code>textDocument/completion</code>)では変更後のプログラムを検証する解析とは別の解析がサーバスレッドで行われているため、1タイプごとに貯まる重いタスクが更に増え、若干もっさりしていました。</p>

<p>LSPでは<code>didChange</code>は通知であり、すぐに結果を返却しなくても良く、更にコード補完リクエストもリクエストとレスポンスの順序を気にしないメソッドなので、高速化のために解析スレッドを分けることにしました。
また、新しい <code>didChange</code> 通知が来た時点で前の状態での解析結果は無効になるため、解析を途中で打ち切る機構を追加しました。</p>

<p><span itemscope itemtype="http://schema.org/Photograph"><img src="/assets/images/hatena/20210912110945.png" alt="f:id:kateinoigaku:20210912110945p:plain" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>

<table>
<thead>
<tr>
<th style="text-align:center;">before </th>
<th style="text-align:center;"> after </th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center;"><img src="https://user-images.githubusercontent.com/11702759/132969301-e4315e91-fc0c-4d0d-bd5e-b081641722a3.gif" alt="typeprof-before" /></td>
<td style="text-align:center;"> <img src="https://user-images.githubusercontent.com/11702759/132969322-a7f9406b-82cd-4ed7-8d23-d27f60944bc4.gif" alt="typeprof-after" /> </td>
</tr>
</tbody>
</table>


<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fruby%2Ftypeprof%2Fpull%2F42" title="LSP: Background analysis by kateinoigakukun · Pull Request #42 · ruby/typeprof" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/ruby/typeprof/pull/42" target="_blank" rel="noopener noreferrer">github.com</a></cite></p>

<p>その他にも色々と実装できて楽しかったです。</p>

<p><a href="https://github.com/ruby/typeprof/pulls?q=is%3Apr+author%3Akateinoigakukun+is%3Aclosed+created%3A%3C2021-08-31" target="_blank" rel="noopener noreferrer">インターン中のPRs</a></p>

<h3>Ruby本体への貢献</h3>

<p>TypeProf for IDEは最新の開発版MRI (Matz's Ruby Interpreter) のAPIを使っており、CIではデイリービルドされた最新のRubyバイナリを使っています。</p>

<p>具体的には、<a href="https://github.com/ruby/setup-ruby" target="_blank" rel="noopener noreferrer">ruby/setup-ruby</a> のGitHub Actionsのアクション経由で <a href="https://github.com/ruby/ruby-dev-builder" target="_blank" rel="noopener noreferrer">ruby/ruby-dev-builder</a> でビルドされた成果物を使っていました。</p>

<p>しかし、ある日直近で入ったAPI変更に追従する変更をTypeProfに入れたところ、CI上のテストが失敗し始めました。</p>

<p>調査したところ、ruby/ruby-dev-builderのデイリービルドがmacOS上で数十日間失敗しており、最新のバイナリが全くアップロードされていないことがわかりました。具体的には、macOSにデフォルトで同梱されているGNU Makeのバージョンが古いことが原因で、最新のruby/rubyのMakefileを正しく解釈できていませんでした。</p>

<p>そして、特定のビルドオプションを付けたときのみ再現する問題であったため、ruby本体のCIを奇跡的に通り抜けていました。</p>

<p>（macOSはGPLv3を避けるためにGNU Makeのバージョンを3.81で止めている。<a href="https://savannah.gnu.org/forum/forum.php?forum_id=4380" target="_blank" rel="noopener noreferrer">ちなみに3.81は2006年リリース。最新は4.2</a>）</p>

<p>とりあえずの対処としてGNU Make 3.81で最新のバージョンと同様の動作をさせるためのワークアラウンドを追加しました。</p>

<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fruby%2Fruby%2Fpull%2F4776" title="Fix build failure on macOS with --enable-shared by kateinoigakukun · Pull Request #4776 · ruby/ruby" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/ruby/ruby/pull/4776" target="_blank" rel="noopener noreferrer">github.com</a></cite></p>

<p>ということで晴れてRuby Contributorの実績も解除できました。</p>

<h2>クックパッドの環境</h2>

<p>ruby-devチームの朝会では<a href="https://twitter.com/_ko1" target="_blank" rel="noopener noreferrer">@_ko1</a> さんと<a href="https://twitter.com/mametter" target="_blank" rel="noopener noreferrer">@mametter</a>さんがRubyの話を、僕がSwiftとWebAssemblyの話をする機会があったり、母国語で言語処理系のプロと働けるとても貴重な環境でした。</p>

<h2>感想</h2>

<p>Ruby自体の経験は浅かったものの、言語処理系や巨大プロジェクト開発の経験のお陰で、ある程度の貢献ができたかなと思います。</p>

<p>また、Ruby開発には単純に人手が足りず、自分でも貢献できそうなインパクトの大きいタスクが残っていたり、出来ることはたくさんありそうなので、時間を見つけて継続して関わっていけたらなと思います。</p>

<p>今回のインターン中関わってくださった皆さんありがとうございました。</p>]]></content><author><name></name></author><summary type="html"><![CDATA[TL;DR]]></summary></entry><entry><title type="html">SwiftコンパイラのAuto-linkingとそれを直した話</title><link href="https://katei.dev/blog/2021/09/02/110000/" rel="alternate" type="text/html" title="SwiftコンパイラのAuto-linkingとそれを直した話" /><published>2021-09-02T11:00:00+09:00</published><updated>2021-09-02T11:00:00+09:00</updated><id>https://katei.dev/blog/2021/09/02/2021-09-02-110000</id><content type="html" xml:base="https://katei.dev/blog/2021/09/02/110000/"><![CDATA[<p>前回のエントリでAuto-linkingについて解説しました。今回はSwiftコンパイラにおけるAuto-linkingの使われ方と、最近それを直した話をします。</p>

<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fkateinoigakukun.hatenablog.com%2Fentry%2F2021%2F08%2F28%2F223951" title="Auto-linkingまとめ - kateinoigakukunのブログ" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://kateinoigakukun.hatenablog.com/entry/2021/08/28/223951" target="_blank" rel="noopener noreferrer">kateinoigakukun.hatenablog.com</a></cite></p>

<h2>用語定義</h2>

<ul>
<li>モジュール: Swiftのimportできる単位。 <code>.swiftmodule</code>、<code>.swiftinterface</code>または <code>module.modulemap</code> が実態。Cで言うヘッダ</li>
<li>ライブラリ: <code>libfoo.a</code> とか <code>libfoo.dylib</code>。大抵モジュールと1対1になってる。</li>
</ul>


<h2>SwiftのAuto-linking</h2>

<p>C言語では以下のようなpragmaを書くことでリンクするライブラリを指定していました。</p>

<pre class="code lang-c" data-lang="c" data-unlink><span class="synPreProc">#include </span><span class="synConstant">&lt;math.h&gt;</span>

<span class="synPreProc">#pragma comment(lib, </span><span class="synConstant">&quot;m&quot;</span><span class="synPreProc">)</span>
</pre>


<p>一方で、Swiftでは <code>import</code> 文を書くだけで、インポートしたモジュールに紐づくライブラリがリンクされます。
XcodeでiOSアプリを書く際、明示的にUIKitのリンク設定をすることなくビルドが成功しているのは、Auto-linkingの仕組みのおかげです。</p>

<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">import</span> UIKit
</pre>


<p>モジュールにライブラリを紐付ける為には、モジュールをビルドする際に <code>-module-link-name</code> オプションを付ける必要があります。このオプションを明示的に指定しない場合Auto-linkingは有効になりません。</p>

<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synComment">// foo.swift</span>
<span class="synStatement">public</span> <span class="synPreProc">func</span> <span class="synIdentifier">inc</span>(_ v<span class="synSpecial">:</span> <span class="synType">Int</span>) <span class="synSpecial">-&gt;</span> <span class="synType">Int</span> { v <span class="synIdentifier">+</span> <span class="synConstant">1</span> }

<span class="synComment">// main.swift</span>
<span class="synPreProc">import</span> foo
_ <span class="synIdentifier">=</span> inc(<span class="synConstant">1</span>)
</pre>




<pre class="code bash" data-lang="bash" data-unlink># モジュール &#34;foo&#34; をコンパイル
$ swiftc -emit-module -emit-library foo.swift -module-link-name foo
$ ls
foo.swift
foo.swiftmodule
libfoo.dylib
foo.swiftdoc
foo.swiftsourceinfo

# -lfoo 無しで動く
$ swiftc main.swift -I. -L.</pre>


<p><code>llvm-bcanalyzer -dump foo.swiftmodule</code> でモジュールファイルの中身を眺めると、 <code>LINK_LIBRARY</code> に <code>"foo"</code> が指定されていることがわかると思います。
コンパイラはimport文で読み込んだモジュールファイルから<code>LINK_LIBRARY</code>エントリを探し、得られたライブラリの情報をオブジェクトファイルに格納します。</p>

<pre class="code" data-lang="" data-unlink>// foo.swiftmodule
&lt;MODULE_BLOCK NumWords=610 BlockCodeSize=2&gt;
  &lt;INPUT_BLOCK NumWords=23 BlockCodeSize=4&gt;
    &lt;IMPORTED_MODULE abbrevid=4 op0=0 op1=0 op2=0/&gt; blob data = &#39;Swift&#39;
    &lt;IMPORTED_MODULE abbrevid=4 op0=0 op1=0 op2=0/&gt; blob data = &#39;SwiftOnoneSupport&#39;
    &lt;LINK_LIBRARY abbrevid=6 op0=0 op1=0/&gt; blob data = &#39;foo&#39;
  &lt;/INPUT_BLOCK&gt;
&lt;/MODULE_BLOCK&gt;</pre>


<p>以下にmacOS上でのMach-Oオブジェクトファイルの内容を示します。<a href="https://kateinoigakukun.hatenablog.com/entry/2021/08/28/223951" target="_blank" rel="noopener noreferrer">前回のエントリ</a>で紹介した <code>LC_LINKER_OPTION</code> に <code>-lfoo</code> が埋め込まれていますね。これをリンカに渡すことでユーザはリンカオプションを渡すこと無く、ライブラリをリンクできます。実は標準ライブラリも同様の仕組みでリンクされています。</p>

<pre class="code" data-lang="" data-unlink>$ swiftc -c main.swift -I. -o main.o
$ llvm-objdump -m -x main.o
...
Load command 4
     cmd LC_LINKER_OPTION
 cmdsize 24
   count 1
  string #1 -lfoo
Load command 5
     cmd LC_LINKER_OPTION
 cmdsize 40
   count 1
  string #1 -lswiftSwiftOnoneSupport
Load command 6
     cmd LC_LINKER_OPTION
 cmdsize 24
   count 1
  string #1 -lswiftCore
</pre>


<h2>間接依存するライブラリのAuto-linking</h2>

<p>さて、モジュールとライブラリの依存関係が次のようになっていた場合を考えてみましょう。
mainはbarだけをインポートしていて、barを介してfooに間接依存していますね。</p>

<p>この場合、最終的な成果物にはfooとbar両方がリンクされていて欲しいです。</p>

<pre class="code" data-lang="" data-unlink>main -&gt; bar -&gt; foo</pre>




<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synComment">// foo.swift</span>
<span class="synStatement">public</span> <span class="synPreProc">func</span> <span class="synIdentifier">inc</span>(_ v<span class="synSpecial">:</span> <span class="synType">Int</span>) <span class="synSpecial">-&gt;</span> <span class="synType">Int</span> { v <span class="synIdentifier">+</span> <span class="synConstant">1</span> }

<span class="synComment">// bar.swift</span>
<span class="synPreProc">import</span> foo
<span class="synStatement">public</span> <span class="synPreProc">func</span> <span class="synIdentifier">dec</span>(_ v<span class="synSpecial">:</span> <span class="synType">Int</span>) <span class="synSpecial">-&gt;</span> <span class="synType">Int</span> { inc(v) <span class="synIdentifier">-</span> <span class="synConstant">2</span> }

<span class="synComment">// main.swift</span>
<span class="synPreProc">import</span> bar
_ <span class="synIdentifier">=</span> dec(<span class="synConstant">1</span>)
</pre>


<p>コンパイラが <code>main.swift</code> を処理する中で <code>import bar</code>から、<code>bar.swiftmodule</code>を読み込みます。
直接依存する<code>bar.swiftmodule</code>には ライブラリ<code>bar</code>をリンクする<code>LINK_LIBRARY</code>エントリと、barモジュールがfooモジュールに依存していることを示す <code>IMPORTED_MODULE</code> エントリが含まれています。
コンパイラは <code>IMPORTED_MODULE</code> によるモジュールの依存グラフを辿っていき、全てのモジュールから <code>LINK_LIBRARY</code> をかき集めます。</p>

<pre class="code" data-lang="" data-unlink>// bar.swiftmodule
&lt;MODULE_BLOCK NumWords=612 BlockCodeSize=2&gt;
  &lt;INPUT_BLOCK NumWords=25 BlockCodeSize=4&gt;
    &lt;IMPORTED_MODULE abbrevid=4 op0=0 op1=0 op2=0/&gt; blob data = &#39;Swift&#39;
    &lt;IMPORTED_MODULE abbrevid=4 op0=0 op1=0 op2=0/&gt; blob data = &#39;SwiftOnoneSupport&#39;
    &lt;IMPORTED_MODULE abbrevid=4 op0=0 op1=0 op2=0/&gt; blob data = &#39;foo&#39;
    &lt;LINK_LIBRARY abbrevid=6 op0=0 op1=0/&gt; blob data = &#39;bar&#39;
  &lt;/INPUT_BLOCK&gt;
&lt;/MODULE_BLOCK&gt;</pre>


<p>最終的にオブジェクトファイルには期待通りfooとbar両方のリンカオプションが埋め込まれます。</p>

<pre class="code" data-lang="" data-unlink>Load command 4
     cmd LC_LINKER_OPTION
 cmdsize 24
   count 1
  string #1 -lbar
Load command 5
     cmd LC_LINKER_OPTION
 cmdsize 24
   count 1
  string #1 -lfoo</pre>


<h2>プライベートな依存を表現する <code>@_implementaionOnly</code></h2>

<p>Swiftにはimport文にいくつかのバリエーションがあり、その内の1つに<code>@_implementaionOnly</code>というアトリビュートがあります。</p>

<p>セマンティクスは「importしたモジュールの型が自身のpublicなAPI/ABIに露出していないことを保証する」です。
言い換えると、「API/ABIは再エクスポートせず実装のみをライブラリ内で使う」になると思います。</p>

<p>これにより、ライブラリ作成者は自身の依存をプライベートにでき、ライブラリのABIを壊さずに依存ライブラリを変更出来るようになります。</p>

<p>詳しい議論については以下のフォーラム投稿を見てください。</p>

<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fforums.swift.org%2Ft%2Fupdate-on-implementation-only-imports%2F26996" title="Update on implementation-only imports" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://forums.swift.org/t/update-on-implementation-only-imports/26996" target="_blank" rel="noopener noreferrer">forums.swift.org</a></cite></p>

<p>ここで、次のケースを考えます。モジュールfooに依存するモジュールbarはfooをプライベートにインポートします。
依存をプライベートにする、ということはライブラリの利用者mainは間接依存するfooの存在について関知せず、mainのリンク時にfooをリンクする必要があるか分かりません。
たとえば、barが共有ライブラリとして配布されている場合、そこにfooが静的にリンクされている場合もあります。その場合mainをリンクする際には <code>-lbar</code> だけあれば良いです。むしろ <code>libfoo.a</code> が配布されているとは限らないため、 <code>-lfoo</code>をmainのリンク時に渡すと、ライブラリfooが見つからずリンクエラーになるかもしれません。</p>

<pre class="code" data-lang="" data-unlink>main -&gt; bar -&gt; foo</pre>




<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synComment">// foo.swift</span>
<span class="synStatement">public</span> <span class="synPreProc">func</span> <span class="synIdentifier">inc</span>(_ v<span class="synSpecial">:</span> <span class="synType">Int</span>) <span class="synSpecial">-&gt;</span> <span class="synType">Int</span> { v <span class="synIdentifier">+</span> <span class="synConstant">1</span> }

<span class="synComment">// bar.swift</span>
<span class="synType">@_implementaionOnly</span> <span class="synType">import</span> foo
<span class="synStatement">public</span> <span class="synPreProc">func</span> <span class="synIdentifier">dec</span>(_ v<span class="synSpecial">:</span> <span class="synType">Int</span>) <span class="synSpecial">-&gt;</span> <span class="synType">Int</span> { inc(v) <span class="synIdentifier">-</span> <span class="synConstant">2</span> }

<span class="synComment">// main.swift</span>
<span class="synPreProc">import</span> bar
_ <span class="synIdentifier">=</span> dec(<span class="synConstant">1</span>)
</pre>


<p>ということで、 <code>@_implementaionOnly</code> 付きでインポートされると、その先のモジュール依存グラフを追わなくなります。
つまり、<code>bar</code>をインポートする環境に<code>foo.swiftmodule</code> が配布されていなくても良いわけです。</p>

<p><code>@_implementaionOnly</code>の有無によるbar.swiftmoduleの差分を以下に示します。なにやら <code>IMPORTED_MODULE</code> エントリにフラグが立っていますね。
これが<code>@_implementaionOnly</code>の印です。</p>

<p>このbarをインポートしたmain.swiftをコンパイルすると、<code>-lbar</code> だけが埋め込まれたオブジェクトファイルができます。fooへの依存が隠蔽されてますね。</p>

<pre class="code lang-diff" data-lang="diff" data-unlink>// bar.swiftmodule
 &lt;MODULE_BLOCK NumWords=612 BlockCodeSize=2&gt;
   &lt;INPUT_BLOCK NumWords=25 BlockCodeSize=4&gt;
     &lt;IMPORTED_MODULE abbrevid=4 op0=0 op1=0 op2=0/&gt; blob data = 'Swift'
     &lt;IMPORTED_MODULE abbrevid=4 op0=0 op1=0 op2=0/&gt; blob data = 'SwiftOnoneSupport'
<span class="synSpecial">-    &lt;IMPORTED_MODULE abbrevid=4 op0=0 op1=0 op2=0/&gt; blob data = 'foo'</span>
<span class="synIdentifier">+    &lt;IMPORTED_MODULE abbrevid=4 op0=2 op1=0 op2=0/&gt; blob data = 'foo'</span>
     &lt;LINK_LIBRARY abbrevid=6 op0=0 op1=0/&gt; blob data = 'bar'
   &lt;/INPUT_BLOCK&gt;
 &lt;/MODULE_BLOCK&gt;
</pre>


<h2><code>@_implementaionOnly</code> によって壊れた静的Auto-linking</h2>

<p>さて、<code>@_implementaionOnly</code> 付きでもAuto-linkingはうまく動いているように思われましたが、実はこれだけでは上手く行かないケースがあります。</p>

<p>ここでは実際に壊れてしまった Foundation (<a href="https://github.com/apple/swift-corelibs-foundation" target="_blank" rel="noopener noreferrer">apple/swift-corelibs-foundation</a>)のケースを紹介します。
Foundationのモジュール依存関係は以下のようになっています。（説明のため簡略化してます）</p>

<pre class="code" data-lang="" data-unlink>Foundation -&gt; CoreFoundation</pre>


<p>さらに、CoreFoundationモジュールは <code>module.modulemap</code>で定義されており、依存ライブラリとして <code>icui18n</code> を指定しています。
そのためライブラリの依存関係としては、次のようになっています。</p>

<pre class="code" data-lang="" data-unlink>Foundation -&gt; CoreFoundation -&gt; icui18n</pre>


<p>CoreFoundationはツールチェインユーザーから直接使われることを想定しておらず、Foundationのプライベートな依存であるため、ある日全ての <code>import CoreFoundation</code> が <code>@_implementaionOnly</code> 付きに変更されました。これにより、ツールチェインにCoreFoundationのヘッダやmodulemapを含める必要が無くなります。（実際はまだ含まれていますが究極的には必要ないです。）</p>

<p>しかし、よく考えてみてください。「Foundationのプライベートな依存CoreFoundation」が依存するICUのicui18nは本当にプライベートな依存ライブラリでしょうか？
icui18nはSwift標準ライブラリでも使われており、プログラム全体で共有すべき依存です。
しかし、Foundationはicui18nへの直接のライブラリ依存を持っておらず、CoreFoundationへの依存がプライベートとなってしまった状態ではリンカオプションを伝播する手段がありません。</p>

<p>この問題により、Swift 5.4のLinux向けツールチェインではFoundationの静的リンク時にシンボル不足エラーが出ています。</p>

<p><a href="https://bugs.swift.org/browse/SR-14536" target="_blank" rel="noopener noreferrer">[SR-14536] Importing FoundationNetworking with -static-stdlib is broken with missing symbols on Linux - Swift</a></p>

<h2>修正編</h2>

<p>この問題を解消するためには、Foundationにicui18nへのライブラリ依存（=LINK_LIBRARYエントリ）を持たせれば良いわけです。
しかしSwift 5.4当時のコンパイラに任意のライブラリの <code>LINK_LIBRARY</code> エントリをモジュールに差し込む機能はありませんでした。</p>

<p>そこで、Swift Forumで解決策について議論した上で、コンパイラに新しいオプションを追加実装しました。</p>

<p>このパッチでは、<code>-public-autolink-library</code> というオプションを追加して、指定したライブラリを <code>LINK_LIBRARY</code>エントリ に出力するようにしています。</p>

<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fforums.swift.org%2Ft%2Fautolinking-behavior-of-implementationonly-with-static-linking%2F44393" title="Autolinking behavior of @_implementationOnly with static linking" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393" target="_blank" rel="noopener noreferrer">forums.swift.org</a></cite></p>

<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fapple%2Fswift%2Fpull%2F35936" title="[Frontend] Add -public-autolink-library option by kateinoigakukun · Pull Request #35936 · apple/swift" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/apple/swift/pull/35936" target="_blank" rel="noopener noreferrer">github.com</a></cite></p>

<p>コンパイラ側のパッチがマージされると、ようやくFoundation側の修正に取り組めます。
このパッチでは、追加したオプションを使って <code>icui18n</code> へのライブラリ依存をFoundationに足しています。</p>

<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fapple%2Fswift-corelibs-foundation%2Fpull%2F2996" title="Fix autolink mechanism for static libraries on Linux by kateinoigakukun · Pull Request #2996 · apple/swift-corelibs-foundation" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/apple/swift-corelibs-foundation/pull/2996" target="_blank" rel="noopener noreferrer">github.com</a></cite></p>

<p>その後リバートやリバート返しを経て、最近ようやく直りました。</p>

<p><a id="conclusion"></a></p>

<h2>まとめ</h2>

<p>Auto-linkingを維持するために多大な努力と時間が費やされていることが伝われば嬉しいです。
結局最初に問題に気がついてから修正まで半年くらいかかってます。大半はコミュニケーションですが。</p>

<p>すごく頑張ったのでLinuxでSwiftを静的リンクしてる人たちが救われてほしい。</p>]]></content><author><name></name></author><summary type="html"><![CDATA[前回のエントリでAuto-linkingについて解説しました。今回はSwiftコンパイラにおけるAuto-linkingの使われ方と、最近それを直した話をします。]]></summary></entry><entry><title type="html">Auto-linkingまとめ</title><link href="https://katei.dev/blog/2021/08/28/223951/" rel="alternate" type="text/html" title="Auto-linkingまとめ" /><published>2021-08-28T22:39:51+09:00</published><updated>2021-08-28T22:39:51+09:00</updated><id>https://katei.dev/blog/2021/08/28/2021-08-28-223951</id><content type="html" xml:base="https://katei.dev/blog/2021/08/28/223951/"><![CDATA[<h2>Auto-linkingとは</h2>

<p>Auto-linkingとは、コンパイラが出力したオブジェクトファイルからリンク対象のライブラリを自動的に決定する仕組みです。
通常、ユーザはリンカのコマンドライン引数に <code>-lm</code> のようにリンクするライブラリを指定しますが、Auto-linkingをサポートするコンパイラとリンカを使う場合、以下のようなC言語の <code>#pragma</code> コメントを記述することで、リンカオプションを指定をせずに、リンカにライブラリを伝えることができます。</p>

<pre class="code lang-c" data-lang="c" data-unlink><span class="synPreProc">#include </span><span class="synConstant">&lt;math.h&gt;</span>
<span class="synPreProc">#include </span><span class="synConstant">&lt;stdio.h&gt;</span>

<span class="synPreProc">#pragma comment(lib, </span><span class="synConstant">&quot;m&quot;</span><span class="synPreProc">)</span>

<span class="synType">int</span> main(<span class="synType">void</span>) {
  printf(<span class="synConstant">&quot;PI = </span><span class="synSpecial">%f\n</span><span class="synConstant">&quot;</span>, atan(<span class="synConstant">1</span>) * <span class="synConstant">4</span>);
  <span class="synStatement">return</span> <span class="synConstant">0</span>;
}
</pre>


<p>コンパイルの様子</p>

<pre class="code bash" data-lang="bash" data-unlink># -lmの指定無しでリンクが成功する
$ clang main.c -fuse-ld=lld
$ ./a.out
PI = 3.141593</pre>


<p><a href="https://en.wikipedia.org/wiki/Auto-linking" target="_blank" rel="noopener noreferrer">Auto-linking - Wikipedia</a></p>

<p>リンカオプションを指定する必要が無くなることで、ユーザの負担が減るだけでなく、ビルドシステム中のオプション伝播が単純化されます。嬉しいですね。</p>

<p>この記事ではオブジェクトファイル形式ごとのAuto-linkingの実装状況と、LLVMにおけるサポートについて解説します。</p>

<p>（完全に理解したがしばらくして忘れて調べ直す、を何回かやったのでいい加減文字に起こすことにした）</p>

<h2>オブジェクトファイル形式ごとの仕組み</h2>

<p>上で紹介した <code>#pragma comment(lib, "...")</code> はIBMコンパイラ、MSVC、Clangが提供しているディレクティブです。（他にもサポートしてるコンパイラはあるかも）
MSVCはCOFF、ClangはELF、Mach-O、COFF向けにこの機能を実装しています。</p>

<ul>
<li><a href="https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?redirectedfrom=MSDN&amp;view=msvc-160#lib" target="_blank" rel="noopener noreferrer">comment pragma | Microsoft Docs</a></li>
<li><a href="https://clang.llvm.org/docs/UsersManual.html#microsoft-extensions" target="_blank" rel="noopener noreferrer">Clang Compiler User’s Manual: Microsoft extensions</a></li>
</ul>


<h3>COFF</h3>

<p>MSVCが出力するオブジェクトファイル形式COFFには、リンカオプションを格納する<code>.drectve</code> セクションがあります。このセクションはオブジェクトファイルのみでサポートされており、通常のセクションとは異なり、最終的な実行可能ファイルには含まれません。</p>

<p>コンパイラは <code>#pragma comment(lib, "...")</code> からリンカオプションを生成し、オブジェクトファイルの<code>.drectve</code>セクションに埋め込むことで、link.exeコマンドにリンクするライブラリを伝えています。</p>

<p><a href="https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-drectve-section-object-only" target="_blank" rel="noopener noreferrer">PE Format - Win32 apps | Microsoft Docs: The .drectve Section (Object Only)</a></p>

<h3>ELF</h3>

<p>ELFにはCOFFのような仕様として定義されたリンカオプション用セクションはありません。
その代わりに、LLVMがClangとlldの間のコンベンションとして特殊なセクションを定義しています。
そのため、Clangで<code>#pragma comment(lib, "...")</code>をコンパイルしたとしても、goldやGNU ldでリンクする場合オプションが伝わりません。</p>

<p>LLVMの実際の実装については後述します。</p>

<h3>Mach-O</h3>

<p>Mach-Oオブジェクトファイルには、ヘッダの後ろにLoad Command呼ばれる構造体列が配置されており、セクションやセグメントなどのレイアウト、動作に必要なOSバージョンなど、リンカやプログラムローダに伝える情報が格納されています。このLoad Commandの一つに、 <code>LC_LINKER_OPTION</code> があり、その名の通りリンカオプションをリンカに伝えてくれます。</p>

<p>このあたりの情報は明確なドキュメントを見つけられておらず、実装を追って分かったことなので、Mach-Oの規約として定義されているものなのかは分かりません。（もしドキュメントの在り処をご存じの方がいれば教えて下さい）</p>

<p>リンカ（ld64）側の実装はこのあたりにあります。 <a href="https://opensource.apple.com/source/ld64/ld64-609/src/ld/parsers/macho_relocatable_file.cpp" target="_blank" rel="noopener noreferrer">macho_relocatable_file.cpp</a></p>

<h2>LLVMにおけるAuto-linking</h2>

<p>さて、LLVMにはAuto-linkingを実現するための機能が歴史的経緯により2つあります。どちらもLLVM IR上のモジュールメタデータとして表現されており、コンパイラがLLVM IRを生成する際に指定します。</p>

<p>1つ目は、<code>llvm.linker.options</code> です。</p>

<p>このメタデータは、COFFでは<code>.drectve</code>、Mach-Oでは<code>LC_LINKER_OPTION</code>に降下します。
一応ELFでも <code>SHT_LLVM_LINKER_OPTIONS</code> という特別なセクションにリンカオプションが埋め込まれるようにコード生成されますが、なんと肝心のlld側が対応していません。
他のオブジェクトファイルの形式と違い、任意のリンカオプションを受け付けるのではなく、オプションのセマンティクスを明示的にしたKey-Valueペアで表現するため、
コンパイラフロントエンドがELF向けに特別な処理を入れる必要があります。</p>

<p>SwiftのWindowsポートで有名なcompnerdさんが2018年に提案して、ClangフロントエンドとLLVMバックエンドの実装をしましたが、その後アップデートが無いようです。</p>

<ul>
<li><a href="https://llvm.org/docs/LangRef.html#automatic-linker-flags-named-metadata" target="_blank" rel="noopener noreferrer">LLVM Language Reference Manual: Automatic Linker Flags Named Metadata</a></li>
<li><a href="https://lists.llvm.org/pipermail/llvm-dev/2018-January/120101.html" target="_blank" rel="noopener noreferrer">[llvm-dev] Linker Option support for ELF</a></li>
</ul>


<p>2つ目は <code>llvm.dependent-libraries</code>です。</p>

<p><code>llvm.linker.options</code>のELFサポートが難航している状態に対して、SonyのPlay Station向けツールチェイン開発者の方が新しく導入したメタデータです。
これは、ELFのみをサポートしており、 リンクするライブラリ名の配列を受け付け、オブジェクトファイルの<code>SHT_LLVM_DEPENDENT_LIBRARIES</code> というセクションに埋め込みます。
こちらはClang、LLVMバックエンド、リンカの実装が完了しています。現在のClangは<code>#pragma comment(lib, "...")</code>をELFの場合のみ、<code>llvm.linker.options</code>を使う実装になっています。</p>

<ul>
<li><a href="https://llvm.org/docs/LangRef.html#dependent-libs-named-metadata" target="_blank" rel="noopener noreferrer">LLVM Language Reference Manual: Dependent Libs Named Metadata</a></li>
<li><a href="https://lists.llvm.org/pipermail/llvm-dev/2019-March/131004.html" target="_blank" rel="noopener noreferrer">[llvm-dev] RFC: ELF Autolinking</a></li>
</ul>


<h2>まとめ</h2>

<p>大変</p>

<h2>参考図書</h2>

<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4274064379/hatena-blog-22/" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51F8V0Y5N6L._SL500_.jpg" class="hatena-asin-detail-image" alt="Linkers &amp; Loaders" title="Linkers &amp; Loaders"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4274064379/hatena-blog-22/" target="_blank" rel="noopener">Linkers &amp; Loaders</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span>JohnR. Levine</li><li>オーム社</li></ul><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4274064379/hatena-blog-22/" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>]]></content><author><name></name></author><summary type="html"><![CDATA[Auto-linkingとは]]></summary></entry></feed>