@s4na_penguin
https://github.com/ko1/rubyhackchallenge
"Ruby Hack Challenge" (RHC) とは、MRI (Matz Ruby Interpreter) の内部をハックするためのガイドです。
MRI: Matz Ruby Interpreter (要するに ruby コマンド)
つまり、Rubyというプログラミング言語でプログラムを書くのではなく、
Rubyというプログラミング言語を、ハックするためのガイドです
- RubyとC言語の関わりがわかる!!
- Rubyのより深いところに近づける!!
- Rubyへのコントリビュートに近づける!!
Rubyのコミッター達が資料を用意してくださっているので、難しくないんです!
今回、「準備のための環境構築と演習を一つ」ご紹介します!
https://github.com/ko1/rubyhackchallenge
- ダウンロード・環境構築
- 作業用ディレクトリ作成
- Rubyのソースコードをclone
- C言語の実行環境をインストール
- ビルド・インストール
- autoconfでconfigure作成
- ビルド
- makeでビルドしてインストール
- 実行
- minirubyで実行しよう
-
ビルド
- ソースコードから動作する状態に変換すること
- 実行時には必要ない中間ファイルを含む
-
インストール
- ビルドしたファイルを実行ときに必要なファイルだけ存在する状態に変換すること
- 👉みなさんのパソコンに入っているソフトはだいたいこの状態
- workdir/
- ruby/ #=> git cloneしたソースコードが入るディレクトリ
- build/ #=> ruby/からコンパイルされた結果が入る
- install/ #=> buildしたものをインストール
- bin/ruby/ #=> ここにインストールされたRubyが入る
$ git clone https://github.com/ruby/ruby.git
$ sudo apt-get install git ruby autoconf bison gcc make zlib1g-dev libffi-dev
libreadline-dev libgdbm-dev libssl-dev
# homebrewも同様のライブラリが必要
※configureは実行環境にあったmakefileを生成してくれる
$ cd ./workdir/ruby/
$ autoconf
$ cd ../
# スライド非表示のコメント
- autoconfでconfigure作成
- > configureは実行すると実行した環境に合ったmakefileを生成してくれるシェルスクリプト
- https://nullnull.hatenablog.com/entry/20120711/1342014234
- autoconf
- https://www.gnu.org/software/autoconf/
- configure
- `--enable-shared`
- 動的リンクとして外に出すもの
- 共有ライブラリを作成する
- どうして?
$ mkdir build
$ cd build
$ ../ruby/configure --prefix=$PWD/../install --enable-shared
# home brewならオプションを追加
# --with-openssl-dir=`brew --prefix openssl` --with-readline-dir=`brew --prefix readline` --disable-libedit
$ make -j # ビルド(Rubyとminiruby)
$ make install # インストール
$ ../install/bin/ruby -v # バージョンチェック&実行できるか確認
- minirubyとは?
- 簡易版Ruby。Rubyの拡張ライブラリのコンパイルにRubyが必要。
- つまり、RubyをインストールするにはRubyがインストールなので、簡易版のminirubyがその役割を果たしている。
- Ruby Hack Challengeで触れる分にはminirubyの方がわかりやすいので、minirubyを使っている
make miniruby
./miniruby <任意のScript> # 結果確認
make install
../install/bin/ruby <任意のScript> # 結果確認
では一つだけ Ruby Hack Challengeの紹介!!
Rubyのバージョン出力結果を変えたい
$ ruby -v
バージョン表記は version.c
で行われているので、ソースコードを確認
void
ruby_show_version(void)
{
if (MJIT_OPTS_ON) {
PRINT(description_with_jit);
}
else {
PRINT(description);
}
#ifdef RUBY_LAST_COMMIT_TITLE
fputs("last_commit=" RUBY_LAST_COMMIT_TITLE, stdout);
#endif
#ifdef HAVE_MALLOC_CONF
if (malloc_conf) printf("malloc_conf=%s\n", malloc_conf);
#endif
fflush(stdout);
}
最終行の fflush
で出力を確定している
fflush(stdout);
とりあえず私はこう修正して
fputs("s4na custom version\n", stdout);
fflush(stdout);
ビルドして・・・
$ make miniruby
$ make install
$ ../install/bin/ruby -v
s4na custom version