LoginSignup
16
10

More than 5 years have passed since last update.

macOS Mojaveでgem install ffiに失敗したときのメモ

Last updated at Posted at 2018-12-26

TL; DR

PKG_CONFIG_PATH="/opt/brew/opt/libffi/lib/pkgconfig" gem install ffi

MacOS Mojaveで bundle install したらエラーが起きてインストールに失敗しました.
nokogiri のインストールに失敗したのかな...と思ってエラーを見てみると,
どうやらインストールに失敗しているのは ffi のようです.

エラーを抜粋します.

configure: error: C++ preprocessor "/lib/cpp" fails sanity check
See `config.log' for more details
make[1]: *** No targets specified and no makefile found.  Stop.

このエラーでグーグル検索をすると, C++ のコンパイラが入っていないのが原因だよ,
g++ を入れてあげれば直るよという記事が目に付きます.
なるほど?と思い手元の環境を確認するも, brew install gcc によって C++ のコンパイラは
正常にインストールされているようです.

ここで,困ったなぁと思いながら GitHub の issue
を眺めに行くと以下の issue が見つかりました.

Fails to install on OSX 10.14 (Mojave): https://github.com/ffi/ffi/issues/651

sudo ln -s /usr/lib/libSystem.B.dylib /usr/local/lib/libgcc_s.10.4.dylib

で直るよという書き込みがありますが,エラーは解消されませんでした.

更に issue を読み進めると, libffiのインストールしなおそう という書き込みが見つかります.
これに従い, brew reinstall libffi を実行してみます.
すると↓のようなログが出てきました.

libffi is keg-only, which means it was not symlinked into /opt/brew,
because some formulae require a newer version of libffi.

For compilers to find libffi you may need to set:
  export LDFLAGS="-L/opt/brew/opt/libffi/lib"

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

keg-only とは,インストールしたライブラリがシステム全体に影響を及ぼす可能性があるため,
homebrew の lib などにはリンクを張らないという挙動のことを言うそうです.
(参考: https://qiita.com/halo57/items/e7511f3befbcb9fedd6a)

ls 'brew --prefix'/lib| grep ffi (backtickをシングルクオートに変換しています) をしてみると,
確かに ffi に関係しそうな共有ライブラリや静的ライブラリが見当たりません.
一方, 'brew --prefix'/Cellar/libffi/x.x.x/lib` にはライブラリやヘッダファイルがありそうです.

というわけで,よしなにパスを通してあげる必要がありそうです.
さきほど示した issue を見ると,
PKG_CONFIG_PATHLDFLAGS に libffi の lib ディレクトリと pkg-config ファイルを
渡してビルドをしているようです.
実際には, pkg-config がよしなにパスの設定をしてくれるので, LDFLAGS の指定は不要です
pkg-config とは, .pc という拡張子に記述したヘッダやライブラリのパスに関する設定を読み込んで
必要に応じてフラグを出力してくれたりするツールです.

libffi の pkg-config ファイルを以下に示します.

prefix=/opt/brew/Cellar/libffi/3.2.1
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
toolexeclibdir=${exec_prefix}/lib
includedir=${libdir}/libffi-3.2.1/include

Name: libffi
Description: Library supporting Foreign Function Interfaces
Version: 3.2.1
Libs: -L${toolexeclibdir} -lffi
Cflags: -I${includedir}

libffi がインストールされているパスやライブラリ,ヘッダが置かれているパスが記述されています.
PKG_CONFIG_PATH に pkg-config ファイルへのパスを渡すと, configure などがそれを読み込み
ビルド時のフラグをよしなにしてくれます.
このため, PKG_CONFIG_PATH='brew --prefix'/Cellar/libffi/3.2.1/lib/pkgconfig gem install ffi としてやることでよしなにインストールが成功します(実際には PKG_CONFIG_PATH に渡しているのは pkg-config ファイルが存在するディレクトリであることに注意してください).
以上です,お疲れ様でした.


ちなみに, pkg-config はコマンドラインでも使えます.
例えば,ライブラリを使うためのフラグがほしいときには pkg-config libffi.pc --libs とします.

$ pkg-config libffi.pc --libs
-L/opt/brew/Cellar/libffi/3.2.1/lib -lffi

ヘッダを使いたいときは pkg-config libffi.pc --cflags

$ pkg-config libffi.pc --cflags
-I/opt/brew/Cellar/libffi/3.2.1/lib/libffi-3.2.1/include

両方いっぺんに使うときは↓

$ pkg-config libffi.pc --cflags --libs
-I/opt/brew/Cellar/libffi/3.2.1/lib/libffi-3.2.1/include -L/opt/brew/Cellar/libffi/3.2.1/lib -lffi

16
10
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
16
10