M1 Macでの開発環境構築(rosetta 無し)

はじめに

この記事では、M1 Macでの開発環境構築でハマったところを共有するために、記載して行きます。今後、随時新しいハマりどころが発生した場合は、情報を追加していきます。

環境構築の前提

筆者の環境では、環境構築の検証もかねているので、Rosetta 2をインストールしていません。Rosetta 2をインストール済みの場合は前提が異なってくるため、ご注意ください。

また、以下のものはインストール済みとします。

  • rbenv

  • Docker Desktop(4.3.0以上)

  • postgresql(実行用ではなく、gem pgのビルド時に利用する想定。brewでインストールする)

※Docker Desktopは、バージョン4.3.0以降でもRosetta 2に依存している部分は残っているようですが、依存度は以前と比べて低くなっているようです

rbenvでの古いRubyのインストール

% rbenv install 2.6.5

のように、古めのRubyのバージョンをインストールすると、以下のようなエラーが発生しました。

Last 10 log lines:
compiling fiber.c
linking shared-object fiber.bundle
compiling closure.c
closure.c:263:14: error: implicit declaration of function 'ffi_prep_closure' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
    result = ffi_prep_closure(pcl, cif, callback, (void *)self);
             ^
1 error generated.
make[2]: *** [closure.o] Error 1
make[1]: *** [ext/fiddle/all] Error 2
make: *** [build-ext] Error 2

gem ffiの公式リポジトリのissueによると、以下2つの対処法があるようです。

1. 環境変数RUBY_CFLAGSを指定してRubyをインストールする

以下のように、RUBY_CFLAGSを指定して、rbenvのインストールコマンドを実行すると上手く行きます。

RUBY_CFLAGS=-DUSE_FFI_CLOSURE_ALLOC rbenv install 2.6.5

筆者もこの方法を先に試して上手く行ったため、この後の2つめの方法を試せていません。

2. brew info libffiコマンドのガイドにしたがって、環境変数を指定する

brew info libffiコマンドを実行すると、以下のようなCaveatsが表示されます。

==> Caveats
libffi is keg-only, which means it was not symlinked into /opt/homebrew,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

For compilers to find libffi you may need to set:
  export LDFLAGS="-L/opt/homebrew/opt/libffi/lib"
  export CPPFLAGS="-I/opt/homebrew/opt/libffi/include"

For pkg-config to find libffi you may need to set:
  export PKG_CONFIG_PATH="/opt/homebrew/opt/libffi/lib/pkgconfig"

これにしたがって、環境変数LDFLAGSCPPFLAGSPKG_CONFIG_PATHを指定して、以下のように実行すると良いとのことです(筆者は、試せていませんが掲載しておきます)。

% export LDFLAGS="-L/opt/homebrew/opt/libffi/lib"
% export CPPFLAGS="-I/opt/homebrew/opt/libffi/include"
% export PKG_CONFIG_PATH="/opt/homebrew/opt/libffi/lib/pkgconfig"
% rbenv install 2.6.5

※記事のみやすさのために、環境変数ごとにexportをしていますが、一気に複数の環境変数を指定しても良いと思います。

docker-composeコマンドを使わずに、docker compose コマンドを使う

Docker公式サイトで説明されているように、docker-compose コマンドはv1のdocker-composeが使われるためRosetta 2のインストールが必要です。、これまでdocker-composeコマンドを使用していた場合は、以下のように、docker compose コマンドを使います。

% docker compose up -d

bundle installでネイティブ拡張が含まれるgemをビルドする

bundle install時にネイティブ拡張が含まれるいくつかのgemでインストールに失敗したのでgemごとの対処法を記載しておきます。

gem ffi

このgemのインストールに失敗する原因は、古いRubyをインストールしたときに出たエラーとと同じです。筆者は、gemのインストール時に発生したエラーに対しては、以下のように、brew info コマンド実行時に表示されるCaveatsの内容にしたがって対処しました。

% export LDFLAGS="-L/opt/homebrew/opt/libffi/lib"
% export CPPFLAGS="-I/opt/homebrew/opt/libffi/include"
% export PKG_CONFIG_PATH="/opt/homebrew/opt/libffi/lib/pkgconfig"
% bundle install

gem pg

pgは、M1 Mac特有のエラーというよりかは、Intel Macでもよく発生する、Ruby開発者ならよく見たことあるエラーですが、以下のエラーが発生します。

checking for pg_config... no
No pg_config... trying anyway. If building fails, please try again with
 --with-pg-config=/path/to/pg_config
checking for libpq-fe.h... no
Can't find the 'libpq-fe.h header
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
        --with-opt-dir
        --without-opt-dir
        --with-opt-include
        --without-opt-include=${opt-dir}/include
        --with-opt-lib
        --without-opt-lib=${opt-dir}/lib
        --with-make-prog
        --without-make-prog
        --srcdir=.
        --curdir
        --ruby=/home/vagrant/.rbenv/versions/2.5.1/bin/$(RUBY_BASE_NAME)
        --with-pg
        --without-pg
        --enable-windows-cross
        --disable-windows-cross
        --with-pg-config
        --without-pg-config
        --with-pg_config
        --without-pg_config
        --with-pg-dir
        --without-pg-dir
        --with-pg-include
        --without-pg-include=${pg-dir}/include
        --with-pg-lib
        --without-pg-lib=${pg-dir}/lib

対処法もいつもどおりで、やり方はいくつかありますが、筆者は以下のようにbundleのbuild時のconfigを指定したのち、bundle install を実行しました。

% bundle config build.pg --with-pg-config=$(brew --prefix postgresql@13)/bin/pg_config

なお、このコマンドを実行すると設定が~/.bundle/configに書き込まれます。

gem rmagick

rmagickもM1固有の問題ではなく、毎回遭遇する以下のエラーが発生します。

./siteconf20220118-1858-ly2is3.rb extconf.rb
checking for clang... yes
checking for Magick-config... yes
checking for outdated ImageMagick version (<= 6.4.9)... no
checking for presence of MagickWand API (ImageMagick version >= 6.9.0)... no
Package MagickWand-6.Q16 was not found in the pkg-config search path.
Perhaps you should add the directory containing `MagickWand-6.Q16.pc'
to the PKG_CONFIG_PATH environment variable
No package 'MagickWand-6.Q16' found
Package MagickWand-6.Q16 was not found in the pkg-config search path.
Perhaps you should add the directory containing `MagickWand-6.Q16.pc'
to the PKG_CONFIG_PATH environment variable
No package 'MagickWand-6.Q16' found
Package MagickWand-6.Q16 was not found in the pkg-config search path.
Perhaps you should add the directory containing `MagickWand-6.Q16.pc'
to the PKG_CONFIG_PATH environment variable
No package 'MagickWand-6.Q16' found
Package MagickWand-6.Q16 was not found in the pkg-config search path.
Perhaps you should add the directory containing `MagickWand-6.Q16.pc'
to the PKG_CONFIG_PATH environment variable
No package 'MagickWand-6.Q16' found
checking for Ruby version >= 1.8.5... yes
Package MagickCore was not found in the pkg-config search path.
Perhaps you should add the directory containing `MagickCore.pc'
to the PKG_CONFIG_PATH environment variable
No package 'MagickCore' found
Can't install RMagick 2.16.0. Can't find the ImageMagick library or one of the dependent libraries. Check the mkmf.log file
for more detailed information.

これは、まず、imagemagickがインストールされていないことが原因で、もしインストール済でこのエラーが発生しているなら、convertコマンドへのPATHが未設定であったり、ビルドに必要なファイルが指定されていなかったりすることが原因です。

以下のように対処します。

まずは、必要なImageMagickをインストールします。Rmagickが対応しているバージョン6を、必ずインストールしてください。

% brew install imagemagick@6

次に、brew info imagemagick@6 コマンドを実行して表示される以下にしたがって、

==> Caveats
imagemagick@6 is keg-only, which means it was not symlinked into /opt/homebrew,
because this is an alternate version of another formula.

If you need to have imagemagick@6 first in your PATH, run:
  echo 'export PATH="/opt/homebrew/opt/imagemagick@6/bin:$PATH"' >> ~/.zshrc

For compilers to find imagemagick@6 you may need to set:
  export LDFLAGS="-L/opt/homebrew/opt/imagemagick@6/lib"
  export CPPFLAGS="-I/opt/homebrew/opt/imagemagick@6/include"

For pkg-config to find imagemagick@6 you may need to set:
  export PKG_CONFIG_PATH="/opt/homebrew/opt/imagemagick@6/lib/pkgconfig"

まず、実行時に必要と思われるconvertコマンドへのPATHを通しておきます。

% echo 'export PATH="/opt/homebrew/opt/imagemagick@6/bin:$PATH"' >> ~/.zshrc

念の為、以下のようにconvertコマンドが使えるかを確認しておくとよいでしょう。

% convert --version

次に、rmagickのビルドに必要な環境変数を指定してから、bundle installを実行します。

% export LDFLAGS="-L/opt/homebrew/opt/imagemagick@6/lib"
% export CPPFLAGS="-I/opt/homebrew/opt/imagemagick@6/include"
% export PKG_CONFIG_PATH="/opt/homebrew/opt/imagemagick@6/lib/pkgconfig"
% bundle install

ここまでで、gemのインストールまで出来ました。

さいごに

なお、2022年1月17日現在、筆者の環境では、この後、古いnodeをインストールしようとしてエラーが発生して失敗し、対応方法が調べきれず、まだRailsアプリケーションを実行するところまでたどり着いておりません。ただ、今後、nodeをバージョンアップさせる予定なので、新しいバージョンのnodeを利用することで、エラーを回避できる可能性があります。

上記については、後日、この記事をアップデートして共有しようと思います。

最終更新