背景
Ruby3.0.6とRails6.1.7.7で開発したアプリを運用します。デプロイ先はheroku(heroku-20)で特に問題なくアプリは動いていました。
しかしながら、Ruby3.0系はheroku-20と互換性はありますが、heroku-22と互換性がなく、Ruby3.0系でherokuにデプロイしようとすると以下のエラーが発生しました。
remote: This app is using the Heroku-20 stack, which is deprecated:
remote: https://devcenter.heroku.com/changelog-items/2895
remote:
remote: From April 30th 2025, Heroku-20 will be end-of-life, and apps using it
remote: will no longer receive security updates, and be run at your own risk.
remote:
remote: From May 1st 2025, builds will no longer be allowed for Heroku-20 apps.
remote:
remote: Please upgrade to a newer stack as soon as possible:
そこで、Ruby3.0.6からRuby3.1.0へのバージョンアップを試みました。
マイナーバージョンアップにも関わらずエラーが頻繁に発生しました。
みなさんの参考になれば嬉しいです。
現在のバージョン
Ruby:3.6.0
Rails:6.1.7.7
bundler:2.5.3、2.4.13(default:2.4.13)
node:16.20.0
npm:8.19.4
yarn:1.22.19
webpack:4.46.0
※開発環境は、macOS Monterey バージョン12.1です。
※エディターは、VSCodeを使用しています。
※デプロイ先は、herokuです。
今回のアップデート
ruby:3.0.6⇨3.1.0
最初に試したこと
#rubyを3.1.0へのバージョンアップ
rvm install 3.1.0 --with-openssl-dir=$(brew --prefix openssl@1.1)
#「.ruby-version」ファイルへの追記
ruby '3.1.0'
#「Gemfile」ファイルへの追記
ruby '3.1.0'
#「bundle install」の実行
bundle install
発生したエラー
warning: a function declaration
without a prototype is deprecated
in all versions of C and is not
supported in C2x
[-Wdeprecated-non-prototype]
mysql2_mysql_enc_name_to_rb_hash
(str, len)
^
./mysql_enc_name_to_ruby.h:86:1:
warning: a function declaration
without a prototype is deprecated
in all versions of C and is not
supported in C2x
[-Wdeprecated-non-prototype]
mysql2_mysql_enc_name_to_rb (str,
len)
^
client.c:1438:3: error: call to
undeclared function
'mysql_ssl_set'; ISO C99 and later
do not support implicit function
declarations
[-Wimplicit-function-declaration]
mysql_ssl_set(wrapper->client,
^
client.c:1438:3: note: did you
mean 'mysql_close'?
/opt/homebrew/Cellar/mysql/8.3.0_1/include/mysql/mysql.h:797:14:
note: 'mysql_close' declared here
void STDCALL mysql_close(MYSQL
*sock);
^
2 warnings and 1 error generated.
make: *** [client.o] Error 1
make failed, exit code 2
(省略)
An error occurred while
installing mysql2 (0.5.5), and
Bundler cannot continue.
In Gemfile:
mysql2
対処方法
まずはMy SQLとopenssl@1.1をインストールし直しました。
brew install mysql
brew install openssl@1.1
次いで、mysql2 の gemをインストールしました。
gem install mysql2 -- --with-mysql-config=$(brew --prefix mysql)/bin/mysql_config --with-openssl-dir=$(brew --prefix openssl@1.1)
mysql2 の gemをインストールした際には、以下のエラーが発生しました。
1 warning generated.
compiling statement.c
linking shared-object mysql2/mysql2.bundle
ld: library not found for -lzstd
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1
make failed, exit code 2
「zstd」が見つからないとのことですので、以下のコードでzstdライブラリをインストールします。
brew install zstd
必要な環境変数を設定します。
export LIBRARY_PATH=$LIBRARY_PATH:$(brew --prefix zstd)/lib/
export LDFLAGS="-L$(brew --prefix zstd)/lib"
export CPPFLAGS="-I$(brew --prefix zstd)/include"
「brew link --force openssl@1.1」を実行した際に、以下のエラーが発生しました。
Linking /opt/homebrew/Cellar/openssl@1.1/1.1.1w...
Error: Could not symlink bin/c_rehash
Target /opt/homebrew/bin/c_rehash
is a symlink belonging to openssl@3. You can unlink it:
brew unlink openssl@3
To force the link and overwrite all conflicting files:
brew link --overwrite openssl@1.1
To list all files that would be deleted:
brew link --overwrite openssl@1.1 --dry-run
エラー発生の原因は、openssl@1.1とopenssl@3の競合です。以下のコードで、openssl@3のリンクを強制的に解除、openssl@1.1のリンクを強制的に作成します。
brew unlink openssl@3
brew link --force openssl@1.1
永続的に環境設定を保持するために、以下のコードを実行します。
echo 'export LIBRARY_PATH=$LIBRARY_PATH:$(brew --prefix zstd)/lib/' >> ~/.zshrc
echo 'export LDFLAGS="-L$(brew --prefix zstd)/lib"' >> ~/.zshrc
echo 'export CPPFLAGS="-I$(brew --prefix zstd)/include"' >> ~/.zshrc
source ~/.zshrc
再度、mysql2 の gemをインストールしました。
gem install mysql2 -- --with-mysql-config=$(brew --prefix mysql)/bin/mysql_config --with-openssl-dir=$(brew --prefix openssl@1.1)
以下のようなログが発生すれば、mysql2 の gemのインストールは完了です。
Building native extensions with: '--with-mysql-config=/opt/homebrew/opt/mysql/bin/mysql_config --with-openssl-dir=/opt/homebrew/opt/openssl@1.1'
This could take a while...
Successfully installed mysql2-0.5.6
Parsing documentation for mysql2-0.5.6
Done installing documentation for mysql2 after 0 seconds
1 gem installed
「bundle install」を実行します。
bundle install
「bundle install」を実行した後に、以下のエラーが発生します。
warning: a function declaration
without a prototype is deprecated
in all versions of C and is not
supported in C2x
[-Wdeprecated-non-prototype]
mysql2_mysql_enc_name_to_rb_hash
(str, len)
^
./mysql_enc_name_to_ruby.h:86:1:
warning: a function declaration
without a prototype is deprecated
in all versions of C and is not
supported in C2x
[-Wdeprecated-non-prototype]
mysql2_mysql_enc_name_to_rb (str,
len)
^
client.c:1438:3: error: call to
undeclared function
'mysql_ssl_set'; ISO C99 and later
do not support implicit function
declarations
[-Wimplicit-function-declaration]
mysql_ssl_set(wrapper->client,
^
client.c:1438:3: note: did you
mean 'mysql_close'?
/opt/homebrew/opt/mysql-client/include/mysql/mysql.h:797:14:
note: 'mysql_close' declared here
void STDCALL mysql_close(MYSQL
*sock);
^
2 warnings and 1 error generated.
make: *** [client.o] Error 1
make failed, exit code 2
(省略)
An error occurred while
installing mysql2 (0.5.5), and
Bundler cannot continue.
In Gemfile:
mysql2
上記のエラーの原因は、Gemfileに指定されたmysql2のバージョンが0.5.5であり、現在の環境と互換性がないことです。以下のコードで、mysqlのバージョンを0.5.5から0.5.6にアップデートします。
#Gemfileの修正
gem 'mysql2', '~> 0.5.6'
#bundle configの設定
bundle config build.mysql2 "--with-mysql-config=$(brew --prefix mysql)/bin/mysql_config --with-openssl-dir=$(brew --prefix openssl@1.1)"
再度「bundle install」を実行します。
bundle install
rmvで仕様するRubyのバージョンを指定します。
rvm use 3.1.0
#まとめ
以前、Ruby2.7からRuby3.0へのメジャーアップデート方法をまとめました。
https://qiita.com/kamakura2008/items/f9526a31fb98218ba12e
今回はRuby3.0.6からRuby3.1.0へのマイナーアップデートなので、サクッと完了するかと思いましたが、多くのエラーが発生しました。
エラーを全て取り除いた後は、以下のコードですんなりとバージョンアップが可能になります。
(Ruby 3.2.5までのバージョンアップできるのを確認できています)
##rubyを3.x.xへのバージョンアップ
rvm install 3.x.x --with-openssl-dir=$(brew --prefix openssl@1.1)
#「.ruby-version」ファイルへの追記
ruby '3.x.x'
#「Gemfile」ファイルへの追記
ruby '3.x.x'
#「bundle install」の実行
bundle install
#rvmの切り替え
rvm use 3.x.x
Rubyのバージョンアップで参考になれば嬉しいです。