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
It’s about time to pack Ruby and Ruby scripts ...
Search
ahogappa
May 16, 2024
Programming
1
5.3k
It’s about time to pack Ruby and Ruby scripts in one binary
ahogappa
May 16, 2024
Tweet
Share
More Decks by ahogappa
See All by ahogappa
RubyKaigi 2024 followup
ahogappa
0
54
Other Decks in Programming
See All in Programming
推しメソッドsource_locationのしくみを探る - はじめてRubyのコードを読んでみた
nobu09
2
230
生成AIで加速するテスト実装 - ロリポップ for Gamersの事例と 生成AIエディタの活用
kinosuke01
0
110
15分で学ぶDuckDBの可愛い使い方 DuckDBの最近の更新
notrogue
3
490
密集、ドキュメントのコロケーション with AWS Lambda
satoshi256kbyte
1
210
Jasprが凄い話
hyshu
0
150
CSS Linter による Baseline サポートの仕組み
ryo_manba
1
150
もう僕は OpenAPI を書きたくない
sgash708
5
1.9k
CloudNativePGを布教したい
nnaka2992
0
110
Djangoにおける複数ユーザー種別認証の設計アプローチ@DjangoCongress JP 2025
delhi09
PRO
4
460
Go 1.24でジェネリックになった型エイリアスの紹介
syumai
2
280
Honoをフロントエンドで使う 3つのやり方
yusukebe
7
3.5k
1年目の私に伝えたい!テストコードを怖がらなくなるためのヒント/Tips for not being afraid of test code
push_gawa
1
510
Featured
See All Featured
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
100
18k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.5k
Into the Great Unknown - MozCon
thekraken
35
1.6k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
7
640
Writing Fast Ruby
sferik
628
61k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.5k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
21
2.5k
A Modern Web Designer's Workflow
chriscoyier
693
190k
The Language of Interfaces
destraynor
156
24k
Why Our Code Smells
bkeepers
PRO
336
57k
Transcript
It’s about time to pack Ruby and Ruby scripts in
one binary RubyKaigi 2024 ahogappa
About me • Sho Hirano(@ahogappa) • STORES, Inc. • #FFF613
2
What’s one binary? 3
What’s one binary? Works perfectly with just one file 4
Why one binary? 5
Why one binary in Ruby? 6
Why one binary in Ruby? e.g. distributing a Ruby project
7
Why one binary in Ruby? 💻 💻 developer user 8
Why one binary in Ruby? 💻 a.rb a.rb a.rb a.rb
💻 developer user 9
Why one binary in Ruby? 💻 a.rb a.rb a.rb a.rb
💻 Ruby 3.3.0 Sinatra 4.0.0 Sqlite3 2.0.1 developer user 10
Why one binary in Ruby? 💻 a.rb a.rb a.rb a.rb
💻🚫 Ruby 3.3.0 Sinatra 4.0.0 Sqlite3 2.0.1 Ruby 3.0.0 Sinatra 3.2.0 Sqlite3 Not installed developer user 11
Why one binary in Ruby? 💻 💻 Ruby 3.3.0 Sinatra
4.0.0 Sqlite3 2.0.1 developer user 12 Ruby 3.0.0 Sinatra 3.2.0 Sqlite3 Not installed
Why one binary in Ruby? 💻 💻 one binary developer
user Ruby 3.3.0 Sinatra 4.0.0 Sqlite3 2.0.1 13 Ruby 3.0.0 Sinatra 3.2.0 Sqlite3 Not installed
Why one binary in Ruby? 💻 💻✔ one binary Ruby
3.3.1 Sinatra 4.0.0 Sqlite3 2.0.1 a.rb a.rb a.rb a.rb developer user Ruby 3.3.1 Sinatra 4.0.0 Sqlite3 2.0.1 14 Ruby 3.0.0 Sinatra 3.2.0 Sqlite3 Not installed
Any existing tools? 15
Any existing tools? • ocra(ocran) • exerb • ruby2exe •
ruby-packer 16
🤔 Existing tools look good and useful 17
Existing tools look good and useful, but • No support
for 3.0+ • Patches Ruby • Windows only • Write temporary files 18
Time to make new one! 😄 19
Done 🔧 20
Kompo 📦 21
Kompo • 梱包(こんぽう) ◦ Means packaging, packing • A word
play on “compo” ◦ compose ◦ component ◦ composite ◦ etc… 22 https://github.com/ahogappa0613/kompo
Demo One binary with Sinatra and Sqlite3 23
Features 24
Features • Monkey patch only, not patching Ruby • No
write temporary files • Supports Gemfile • Reads local file as a fallback when failing to read from vfs 25
Demo Reads local file as a fallback when failing to
read from vfs 26
How kompo works 27
How kompo works • Ruby scripts are embedded • Patch
methods that read Ruby scripts ◦ Kernel#require ◦ Kernel#require_relative ◦ Kernel#load ◦ Kernel#autoload, Module#autoload • Native extensions are statically linked 28
29 libruby-static.a
30 libruby-static.a native extensions
main.c 31 libruby-static.a native extensions void Init_gems(void) { ruby_init_ext( "puma/puma_http11.so",
Init_puma_http11 ); ruby_init_ext( "sqlite3/sqlite3_native.so", Init_sqlite3_native ); } int main(int argc, char **argv) { ruby_sysinit(&argc, &argv); ruby_init(); Init_gems(); Init_kompo_fs(); … return ruby_run_node(node); }
main.c 32 kompofs.o +patches libruby-static.a native extensions
33 class Kompo def get_file(abs_path) # return the ruby script
from kompofs(.o) end … end main.c libruby-static.a native extensions kompofs.o +patches libkompo.a
main.c libkompo.a 34 libruby-static.a kompofs.o +patches native extensions one binary
compile and link libruby-static.a
Patches 35
Patches libruby-static.a main.rb b.rb d.rb a.rb Kernel#require Kernel#require_relative c.so 36
Patches libruby-static.a main.rb b.rb d.rb a.rb Kernel#require Kernel#require_relative c.so $
cd /workspace/sample $ kompo a.rb b.rb 37
Patches libruby-static.a main.rb b.rb Kernel#require Kernel#require_relative d.rb a.rb c.so 38
kompofs.o
Patches Ruby main.rb b.rb Kernel#require Kernel#require_relative c.o d.rb a.rb one
binary libkompo.a 39 main.c kompofs.o
Patches Ruby main.rb b.rb 🪡Kernel#require 🪡Kernel#require_relative c.o d.rb a.rb one
binary libkompo.a 40 module Kernel def require(path) eval(Kompo.get_file(path)) rescue => LoadError original_require(path) main.c kompofs.o
Patches Ruby main.rb b.rb 🪡Kernel#require 🪡Kernel#require_relative c.o d.rb a.rb one
binary require ‘a’ require_relative ‘./b’ require ‘c’ require ‘d’ libkompo.a 41 module Kernel def require(path) eval(Kompo.get_file(path)) rescue => LoadError original_require(path) main.c kompofs.o
Patches Ruby main.rb b.rb 🪡Kernel#require 🪡Kernel#require_relative c.o d.rb a.rb one
binary libkompo.a 42 module Kernel def require(path) eval(Kompo.get_file(path)) rescue => LoadError original_require(path) kompofs.o require ‘a’ require_relative ‘./b’ require ‘c’ require ‘d’ main.c
Future Works 43
Future Works • Support ways for users to access kompofs
freely • Cross-compilation • File compression 44
Let’s kompo Ruby! 45
Thank you!! 46