rubyhackchallenge
rubyhackchallenge copied to clipboard
ビルドしたRubyでのGemのテスト
取り組んだ課題
https://github.com/ko1/rubyhackchallenge/blob/master/tasks.md#ビルドした-ruby-での-gem-のテスト
現在、ビルドした Ruby で Gem など、外部ライブラリを、ビルドした Ruby で、他の影響を与えないで適切にテストする方法がありません。 というのも、Gem の場合、Gem のテストのために他の Gem を利用したりする必要があるためです。 区切られた環境(サンドボックス)を用いることで
成果
- https://gist.github.com/nownabe/b09db191e34206882b66b2e6ae2c7658
-
make install
した先でGemをテストするスクリプト - テストの流れ
- Gemを指定するとYAMLの定義に従ってGemのレポジトリをクローン
- Gemの依存Gemを
make install
先にインストール - YAMLの定義に従ってテストを実行
-
- https://github.com/nownabe/docker-rubygems-test (未完成)
- 前半、CI用にDockerイメージを作ろうとして、やっぱりRubyをHackしてる感がなくてやめたやつ
今後
- サンドボックス要件が完全には満たせていないので、ビルドディレクトリにのみ閉じて(
make install
不要)Gemのテストを実行できるように修正する -
/tool
にスクリプトを作り、make testgem
のような形で実行できるようにする - ある程度、レポジトリやテストコマンドを自動検知できるようにする
土日で続きをやってみました。 https://github.com/nownabe/ruby/commit/fafe53e43badaa55eff8541484359328627e8039
現在はまだいろいろ制限がありますが、make testgem
で環境を汚さずにGemがテストできるようになりました。
Usage:
$ mkdir build
$ cd build
$ ../ruby/configure --prefix=`pwd`/../install --enable-shared
$ make -j
# YAMLに定義されているGemすべてのテストを実行
$ make testgem
# 特定のGemのテストを実行
$ make testgem GEMS=benchmark_driver
制限:
-
--enable-shared
必須 - Linuxnのみ (Fedora 25でしか確認できていない)
課題
-
--enable-shared
なしでのテスト (必要?) - 他の環境でのテスト
- Mac対応
make testgem
を通すために必要な環境構築
Debian 9 (Stretch)
sudo apt-get install \
g++ \
ncurses-dev \
ragel \
libxml2-dev \
default-libmysqlclient-dev \
libpq-dev \
libsqlite3-dev \
libfcgi-dev
CentOS 7
sudo yum install -y epel-release
sudo yum install -y \
git \
autoconf \
ruby \
gcc \
bison \
bzip2 \
openssl-devel \
libyaml-devel \
libffi-devel \
readline-devel \
zlib-devel \
gdbm-devel \
ncurses-devel \
gcc-c++ \
libxml2-devel \
mysql-devel \
postgresql-devel \
sqlite-devel \
fcgi-devel
Fedora 25
sudo dnf install -y \
cmake \
pandoc
テスト状況
v2_4_2 / --enable-sharedなし
- [ ] Debian 8
- [ ] Debian 9
- [ ] CentOS 6
- [ ] CentOS 7
- [ ] Ubuntu 14.04
- [ ] Ubuntu 16.04
- [ ] Ubuntu 17.04
- [ ] macOS Sierra
v2_4_2 / --enable-sharedあり
- [ ] Debian 8
- [ ] Debian 9
- [ ] CentOS 6
- [ ] CentOS 7
- [ ] Ubuntu 14.04
- [ ] Ubuntu 16.04
- [ ] Ubuntu 17.04
- [ ] macOS Sierra
trunk / --enable-sharedなし
- [ ] Debian 8
- [ ] Debian 9
- [ ] CentOS 6
- [ ] CentOS 7
- [ ] Ubuntu 14.04
- [ ] Ubuntu 16.04
- [ ] Ubuntu 17.04
- [ ] macOS Sierra
trunk / --enable-sharedあり
- [ ] Debian 8
- [ ] Debian 9
- [ ] CentOS 6
- [ ] CentOS 7
- [ ] Ubuntu 14.04
- [ ] Ubuntu 16.04
- [ ] Ubuntu 17.04
- [ ] macOS Sierra
@nownabe こんにちは、 @ko1 さんから紹介いただきました。Bundled Gems 全般を僕がみているので、レビューのち本体にマージできそうならマージしたいと思います。
すげーどうでも良い話なんですが、test-all とか test-spec という既存の名前に合わせて、test-gem もしくは test-gems が良さそうに思いました。
@hsbt ありがとうございます!ruby/rubyにPull Request投げる形でよろしいでしょうか?
@ko1 それもそうですね。test-gems
にします 🙌
@nownabe pull request でお願いします!
macOSはEl CapitanからDYLD_LIBRARY_PATHやDYLD_INSERT_LIBRARIESが継承できなくなっているらしい。。。 http://paulbeachsblog.blogspot.jp/2016/03/dyldlibrarypath-and-el-capitan.html
Mac対応は一旦保留 😞
そのために、Mac だと ruby-runner というものを作っているようです。
@ko1 なるほど…!そういえばrunrubyでみました。確認してみます!:pray:
Gem::Ext::Builderが実行するコマンドをなんらかのパッチで差し替える感じかな
https://gist.github.com/nownabe/5d50e0d988d1f6593b91efd0a28a9045
--enable-shared
なしでうまくいかなかったときのログ:
==============================
Current Directory: /home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/gems/gems/stackprof-0.2.10/ext/stackprof
ENV:
{"GEM_HOME"=>
"/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/gems",
"GEM_PATH"=>
"/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/gems",
"LD_LIBRARY_PATH"=>
"/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled:/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled",
"PATH"=>
"/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/bin:/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/gems/bin:/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-
enabled/bin:/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/gems/bin:/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled:/home/nownabe/.cargo/bin:/home/nownabe/tmp/sdk/appengi
ne-java-sdk-1.9.51/bin:/home/nownabe/tmp/google-cloud-sdk/bin:/home/nownabe/bin:/home/nownabe/.anyenv/envs/rbenv/shims:/home/nownabe/.anyenv/envs/rbenv/bin:/home/nownabe/.anyenv/envs/pyenv/shims:/home/nownabe/
.anyenv/envs/pyenv/bin:/home/nownabe/.anyenv/envs/ndenv/bin:/home/nownabe/.anyenv/bin:/home/nownabe/.cargo/bin:/home/nownabe/tmp/sdk/appengine-java-sdk-1.9.51/bin:/home/nownabe/tmp/google-cloud-sdk/bin:/home/n
ownabe/.sdkman/candidates/gradle/current/bin:/home/nownabe/bin:/home/nownabe/.anyenv/envs/rbenv/shims:/home/nownabe/.anyenv/envs/rbenv/bin:/home/nownabe/.anyenv/envs/pyenv/shims:/home/nownabe/.anyenv/envs/pyen
v/bin:/home/nownabe/.anyenv/envs/ndenv/shims:/home/nownabe/.anyenv/envs/ndenv/bin:/home/nownabe/.anyenv/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",
"PWD"=>
"/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/gems/gems/stackprof-0.2.10/ext/stackprof",
"RUBY"=>
"/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/bin/ruby",
"RUBYLIB"=>
"/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/lib:/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/.ext/common:/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-
no-enabled/.ext/x86_64-linux:/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib:/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled",
"RUBYOPT"=>"-EUTF-8",
"SHLVL"=>"1",
"_"=>
"/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/bin/ruby"}
==============================
#### begin: try_link(src, opt = "", *opts, &b) ####
#### begin: try_link0(src, opts = "", *opts, &b) ####
#### begin: try_do(src, command, *opts, &b) ####
#### begin: have_devel? ####
$hava_devel is not defined.
MAIN_DOES_NOTHING: int main(int argc, char **argv)
{
return 0;
}
#### begin: try_link(src, opt = "", *opts, &b) ####
#### begin: try_link0(src, opts = "", *opts, &b) ####
#### begin: try_do(src, command, *opts, &b) ####
#### begin: have_devel? ####
#### end: have_devel? ####
#### begin: xsystem(command, opts = nil) ####
libpath_env: {"LD_LIBRARY_PATH"=>".:/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/lib:/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled:/ho
me/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled"}
command: gcc -o conftest -I/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/include/ruby-2.5.0/x86_64-linux -I/home/nownabe/tmp/rubyhackchallenge/gemtest/build
-trunk-no-enabled/include/ruby-2.5.0/ruby/backward -I/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/include/ruby-2.5.0 -I. -O3 -fno-fast-math -ggdb3 -DRUBY_DEVEL=1 -Wall -Wextra -Wno-unu
sed-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wno-tautological-compare -Wno-parentheses-equality -Wno-constant-logical-operand -Wno-self-assign -Wunused-variable -Wimplicit-int
-Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat -Wsuggest-attribute=noreturn -Wsuggest-attribute=format -Wno
-maybe-uninitialized conftest.c -L. -L/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/lib -Wl,-rpath,/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/lib -L. -fstack-prote
ctor -rdynamic -Wl,-export-dynamic -Wl,-rpath,/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/lib -L/home/nownabe/tmp/rubyhackchallenge/gemtest/build-trunk-no-enabled/lib -lruby-static
-lpthread -ldl -lcrypt -lm -lc
Stdout:
Stderr: /usr/bin/ld: cannot find -lruby-static
collect2: error: ld returned 1 exit status
Result: pid 2962 exit 1
#### end: xsystem(command, opts = nil) ####
#### end: try_do(src, command, *opts, &b) ####
#### end: try_link0(src, opts = "", *opts, &b) ####
exe:
#### end: try_link(src, opt = "", *opts, &b) ####
$have_devel = false
#### end: have_devel? ####
RuntimeError
The compiler failed to generate an executable file.
You have to install development tools first.
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:541:in `try_do'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:632:in `try_link0'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:652:in `try_link'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:878:in `try_func'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:1165:in `block in have_func'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:1055:in `block in checking_for'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:406:in `block (2 levels) in postpone'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:376:in `open'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:406:in `block in postpone'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:376:in `open'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:402:in `postpone'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:1054:in `checking_for'
/home/nownabe/tmp/rubyhackchallenge/gemtest/ruby/lib/mkmf.rb:1164:in `have_func'
extconf.rb:2:in `<main>'
#### end: try_do(src, command, *opts, &b) ####
#### end: try_link0(src, opts = "", *opts, &b) ####
#### end: try_link(src, opt = "", *opts, &b) ####
==============================
ruby-static
がないらしい?
CONFIG["LIBRUBYARG_STATIC"] = "-Wl,-rpath,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static"
$ ar x libruby-static.a
$ ls
addr2line.o compile.o dln_find.o enum.o hash.o loadpath.o numeric.o process.o regenc.o ruby.o strftime.o thread.o util.o vm_trace.o
array.o complex.o dln.o error.o inits.o localeinit.o object.o proc.o regerror.o safe.o string.o time.o variable.o
ascii.o cont.o dmyenc.o eval.o io.o marshal.o pack.o random.o regexec.o setproctitle.o strlcat.o transcode.o version.o
bignum.o debug_counter.o dmyext.o explicit_bzero.o iseq.o math.o parse.o range.o regparse.o signal.o strlcpy.o unicode.o vm_backtrace.o
class.o debug.o encoding.o file.o libruby-static.a newline.o prelude.o rational.o regsyntax.o sprintf.o struct.o us_ascii.o vm_dump.o
compar.o dir.o enumerator.o gc.o load.o node.o probes.o regcomp.o re.o st.o symbol.o utf_8.o vm.o
--enable-shared
がないとeventmachineがビルドできない。
extconf.rbから生成されたMakefileのCPPFLAGSに-DHAVE_RB_WAIT_FOR_SINGLE_FD -DHAVE_RB_THREAD_FD_SELECT
を追加するとビルドできる。
https://github.com/eventmachine/eventmachine/blob/master/ext/em.h#L25
https://github.com/eventmachine/eventmachine/blob/master/ext/em.cpp#L623
--enable-shared
ありの場合のMakefileは-DHAVE_RB_WAIT_FOR_SINGLE_FD -DHAVE_RB_THREAD_FD_SELECT
が定義されている。
このへんおっかける https://github.com/ruby/ruby/blob/trunk/lib/mkmf.rb#L1056 https://github.com/eventmachine/eventmachine/blob/master/ext/extconf.rb#L109
--enable-shared
なしとMacでも動くようになったので、Gemを増やしていきたい
http://bestgems.org/total このへんみつつ
RubyKaigi にいらっしゃいます?
@ko1 すみません今年は参加していません :sob::pray:
BestGemsのTop100のGemを試して、trunkでテストが通らないGemの傾向 (2.4ではまだできていない)
- 本当にテストが通っていない感じのもの (C拡張ライブラリ系が多い感じ) => 2.4.1をビルドして試す
- RSpecのバグ?(trunkで動かない?)に引きずられている感じのもの => 2.4.1をビルドして試す
- Rakefileがないもの => テストコマンド調べる
- 特殊な環境でしかテストできないもの (activerecord, net-scpなど) => 無視
- インストール済みの2.4.1でもテストが失敗するもの => CIなどをみてみる
- テスト方法がわからないもの => 調べる
- 依存関係がうまく解決できないもの (railsファミリーに多い) => --preとか?
- 何かが足りないもの => 追加してみる
今の所test-gemsの環境でのみテストが通らないのは3つ
- [ ] bundler
- [x] pry
- [x] rspec-core
rspecは、erb.rb
をソースディレクトリに置いたままRUBYLIBで参照させていたのが原因っぽい
RSpecのbacktraceをフィルタリングする箇所でtest-gems環境だとパスがlib/ruby
にマッチしないのでフィルタリングできていなかった。
https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/backtrace_formatter.rb#L11
そういえば、これを進めて http://www.ruby.or.jp/ja/news/20170804 に出しません?
@ko1 出してみたいです!こんなのあるんですね
@ko1 応募メールに記載する担当者は笹田さんでよろしいでしょうか?
TODO
- [x] trunkで
ruby-runner
=>exe/ruby
の変更があったので追従する必要がありそう- https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?revision=59937&view=revision
- [ ] rbconfig.rbにパッチあててるのでロックする
- [ ]
if: { platform: "mac" }
のような形でテストを実行する条件を指定できるようにする - [ ] Resultをskippedという状態も持てるようにする
- [x] オプションで
--depth 1
- [x] CI
- [x] Rubyアソシエーション 開発助成金2017 応募
メンターですかね? 私で結構です。
承知しました!
ブログに簡単に使い方をまとめました。
https://blog.nownabe.com/2017/09/22/1133.html
bundlerは一旦保留
- パス周り細かく見てたりしてEXTOUTとか参照させてるとfailする
- ruby本体に取り込まれる予定
- インストール済みの2.4.2でもfailする
テスト用のスクリプト: https://github.com/nownabe/gem_tester/tree/master/scripts CIで回したい…
TODO
- [ ] コピーしてるファイルの変更に追随する (変更日時)
- [ ] WindowsはSymlink動かない (Windowsではサポートしない? / 動かないGemも多そう)
- [ ] https://github.com/ruby/chkbuild に対応する
- [ ] オプションでYAMLも指定できるようにすれば柔軟になる
- [ ] ~~オプションでGemレポジトリのディレクトリを指定できるようにする (CIでキャッシュできるように)~~