LoginSignup
12
13

More than 5 years have passed since last update.

Chefを使ってCentOS6.5でruby-1.8.7をrbenvからインストールしようとすると失敗するが、インストール出来るようにした

Last updated at Posted at 2014-10-04

Chefを使ってCentOS6.5でruby-1.8.7をrbenvからインストールしようとすると失敗するが、インストール出来るようにした

問題の概要

CentOS6.5でruby-1.8.7をコンパイルすると、opensslの部分でコンパイルエラーになる。

ossl_pkey_ec.c: In function 'ossl_ec_group_initialize':
ossl_pkey_ec.c:761: warning: assignment makes pointer from integer without a cast
ossl_pkey_ec.c:815: error: 'EC_GROUP_new_curve_GF2m' undeclared (first use in this function)
ossl_pkey_ec.c:815: error: (Each undeclared identifier is reported only once
ossl_pkey_ec.c:815: error: for each function it appears in.)

CentOSのopensslパッケージがruby-1.8.7が作成された頃より新しくなったのだが、そのためにミスマッチが生じているらしい。
これの対処法をググると、2つ出てくる。

  1. そのうちopensslの新しいパッケージが出るだろうから、その時に yum install すれば直るだろうから、しばし待て
  2. rubyのossl_pkey_ec.c にパッチを当てろ → https://gist.github.com/hyoshida/11241844

当然2で対応する訳だが、rbenv install にてコンパイルするので、どこでパッチを当てるかという問題になる。
chefからrubyソースにパッチを当てるのか、chefがruby-buildにパッチを当て、ruby-buildがrubyソースにパッチを当てるのか?

最初は、パッチを当てたrubyソースをgithubに置いておきそれをダウンロードするようにして、またruby-buildに専用のバージョン定義ファイルを入れたものを作ってこれもgithubに置いておくようにしていた。
これだとcookbook以外に外部ファイルを2つも置くことになり情報が分散していてよろしくないので、cookbookだけで何とかする方法を探していたが、やり方がわかった。

ruby-buildバージョン定義ファイル中でパッチを当てる

ruby-buildのバージョン定義ファイル内で、rubyソースにパッチを当てる方法がわかった。
定義ファイルはシェルスクリプトであり、その中で before_install_package() 関数を定義してやれば、インストール直前に呼び出される。
この関数の中でパッチを当ててやればいい。

出来た定義ファイルがこれ。

ruby_build/share/ruby-build/1.8.7-p374-centos_openssl
before_install_package() {
  if [ "$1" != "ruby-1.8.7-p374" ]; then
    return 0
  fi
  patch -d ${BUILD_PATH}/ruby-1.8.7-p374 -p1 <<PATCH_END
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index cbdad3f..d517b58 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -757,8 +757,10 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
                 method = EC_GFp_mont_method();
             } else if (id == s_GFp_nist) {
                 method = EC_GFp_nist_method();
+#if !defined(OPENSSL_NO_EC2M)
             } else if (id == s_GF2m_simple) {
                 method = EC_GF2m_simple_method();
+#endif
             }

             if (method) {
@@ -811,8 +813,10 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)

             if (id == s_GFp) {
                 new_curve = EC_GROUP_new_curve_GFp;
+#if !defined(OPENSSL_NO_EC2M)
             } else if (id == s_GF2m) {
                 new_curve = EC_GROUP_new_curve_GF2m;
+#endif
             } else {
                 rb_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
             }
PATCH_END
  echo "openssl patch applied" >&2
}
require_gcc
install_package "ruby-1.8.7-p374" "http://cache.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p374.tar.gz#876eeeaaeeab10cbf4767833547d66d86d6717ef48fd3d89e27db8926a65276c" auto_tcltk standard
install_package "rubygems-1.6.2" "http://production.cf.rubygems.org/rubygems/rubygems-1.6.2.tgz#cb5261818b931b5ea2cb54bc1d583c47823543fcf9682f0d6298849091c1cea7" ruby

これをcookbookの file/ の下に置いておき、レシピ中でruby_buildのダウンロード後に転送してやればいい。

クックブック rbenv を呼び出すので、Berksfile に入れ、metadataにもdependsを記述する。

Berksfile
cookbook 'rbenv'
metadata.rb
depends          'rbenv'

これがレシピ。

recipes/default.rb
include_recipe "rbenv::default"
include_recipe "rbenv::rbenv_vars"
include_recipe "rbenv::ruby_build"

cookbook_file "#{node[:ruby_build][:prefix]}/share/ruby-build/1.8.7-p374-centos_openssl" do
  source "1.8.7-p374-centos_openssl"
  mode '0644'
  owner node[:rbenv][:user]
  group node[:rbenv][:group]
end

rbenv_ruby "1.8.7-p374-centos_openssl" do
  ruby_version "1.8.7-p374-centos_openssl"
end

cookbookだけで完結してすっきり。

12
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
13