mac で (rails new した後の bundle install 時に) ffi 1.11.0 のインストールが失敗したのでバージョン固定で解決

バージョン

名前 | バージョン
----|----
macOS | 10.13.6
ruby  | 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin17]
rails | 5.2.3

[コメント](https://qiita.com/negito6/items/055d23bf26a92a6617f3#comment-54798d7301b8b4e3f0f8)でご指摘あったように、問題そのものは Rails とは関係ないです。

# 起きたエラー内容

```
 $ bundle exec rails new ../sample
      create  
      create  README.md
      create  Rakefile
      create  .ruby-version
      create  config.ru
      create  .gitignore
      create  Gemfile

(略)


Fetching gem metadata from https://rubygems.org/............
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Fetching rake 12.3.2


Your user account isn't allowed to install to the system RubyGems.
  You can cancel this installation and run:

      bundle install --path vendor/bundle

  to install the gems into ./vendor/bundle/, or you can enter your password
  and install the bundled gems to RubyGems using sudo.

  Password: 
Installing rake 12.3.2
Fetching concurrent-ruby 1.1.5
Installing concurrent-ruby 1.1.5

(略)

Fetching coffee-rails 4.2.2
Installing coffee-rails 4.2.2
Fetching ffi 1.11.0
Installing ffi 1.11.0 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby -r ./siteconf20190519-47252-1at7a63.rb extconf.rb
checking for ffi.h... no
checking for ffi.h in /usr/local/include,/usr/include/ffi... yes
checking for ffi_call() in -lffi... yes
checking for ffi_closure_alloc()... no
checking for shlwapi.h... no
checking for rb_thread_call_without_gvl()... yes
checking for ruby_native_thread_p()... yes
checking for ruby_thread_has_gvl_p()... yes
creating extconf.h
creating Makefile

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/extensions/universal-darwin-17/2.3.0/ffi-1.11.0/mkmf.log

current directory: /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c
make "DESTDIR=" clean

current directory: /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c
make "DESTDIR="
mkdir -p "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386; (if [ ! -f
"/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi"/configure ]; then echo "Running autoreconf for libffi"; cd
"/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi" && /bin/sh
/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi/autogen.sh > /dev/null; fi); (if [ ! -f
"/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386/Makefile ]; then echo "Configuring libffi for i386"; cd
"/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386 && env CC=" xcrun clang" CFLAGS="-arch i386 " LDFLAGS="-arch i386"
"/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi"/configure --disable-static --with-pic=yes --disable-dependency-tracking --disable-docs
--host=i386-apple-darwin > /dev/null; fi); env MACOSX_DEPLOYMENT_TARGET=10.4 /Applications/Xcode.app/Contents/Developer/usr/bin/make -C
"/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386

(略)

libtool: link: ranlib .libs/libffi_convenience.a
libtool: link: ( cd ".libs" && rm -f "libffi_convenience.la" && ln -s "../libffi_convenience.la" "libffi_convenience.la" )
/bin/sh ./libtool  --tag=CC   --mode=link xcrun clang  -arch i386  -Wall -fexceptions -no-undefined -version-info `grep -v '^#'
/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi/libtool-version`   '-arch' 'i386'  -arch i386 -o libffi.la -rpath /usr/local/lib src/prep_cif.lo
src/types.lo src/raw_api.lo src/java_raw_api.lo src/closures.lo  src/x86/ffi.lo src/x86/sysv.lo
libtool: link:  xcrun clang -dynamiclib  -o .libs/libffi.7.dylib  src/.libs/prep_cif.o src/.libs/types.o src/.libs/raw_api.o src/.libs/java_raw_api.o src/.libs/closures.o src/x86/.libs/ffi.o src/x86/.libs/sysv.o    -arch i386 -arch
i386 -arch i386   -install_name  /usr/local/lib/libffi.7.dylib -compatibility_version 9 -current_version 9.0 -Wl,-single_module
ld: warning: The i386 architecture is deprecated for macOS (remove from the Xcode build setting: ARCHS)
Undefined symbols for architecture i386:
  "___x86.get_pc_thunk.bx", referenced from:
      _ffi_call_i386 in sysv.o
      _ffi_closure_raw_SYSV in sysv.o
      _ffi_closure_raw_THISCALL in sysv.o
  "___x86.get_pc_thunk.dx", referenced from:
      _ffi_closure_i386 in sysv.o
      _ffi_closure_STDCALL in sysv.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [libffi.la] Error 1
make[2]: *** [all-recursive] Error 1
make[1]: *** [all] Error 2
make: *** ["/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386/.libs/libffi_convenience.a] Error 2

make failed, exit code 2

Gem files will remain installed in /var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0 for inspection.
Results logged to /var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/extensions/universal-darwin-17/2.3.0/ffi-1.11.0/gem_make.out

An error occurred while installing ffi (1.11.0), and Bundler cannot continue.
Make sure that `gem install ffi -v '1.11.0'` succeeds before bundling.

In Gemfile:
  spring-watcher-listen was resolved to 2.0.1, which depends on
    listen was resolved to 3.1.5, which depends on
      rb-inotify was resolved to 0.10.0, which depends on
        ffi
         run  bundle exec spring binstub --all
bundler: command not found: spring
Install missing gem executables with `bundle install`
$
```


~~macOS が 10.13.6 なのがきっといけないのだろうと思うが、そこじゃない場所で解決を試みる。~~ [コメント](https://qiita.com/negito6/items/055d23bf26a92a6617f3#comment-54798d7301b8b4e3f0f8)にて、OS も関係ないとのご指摘。 `ld: warning: The i386 architecture is deprecated for macOS (remove from the Xcode build setting: ARCHS)` の辺りを調べればいいかもしれないのですが、それはまたの機会に。

解決後に `Gemfile.lock` を見ると、 `ffi` の依存指定は一箇所のみで、こうなっていた。

```ruby                                                                     
    rb-inotify (0.10.0)                                                                                                
      ffi (~> 1.0)
```

`ffi (~> 1.0)` とあるので、 `ffi` の `1.x` の最新版（当時は `1.11.0` ）を取ろうとして、それがインストールできていない。

# 解決方法

`~> 1.0` ということは `1.11.0` が必要なわけじゃないはずので、 `Gemfile` を書き換えて、インストールできるバージョンに固定した。（ `1.9.21` は、あくまで例です）

```ruby
gem 'ffi', '= 1.9.21'
```

(これは要らないかもしれない) 事前にインストールしておく。

```
$ sudo gem install ffi -v '1.9.21'
Fetching: ffi-1.9.21.gem (100%)
Building native extensions.  This could take a while...
Successfully installed ffi-1.9.21
Parsing documentation for ffi-1.9.21
Installing ri documentation for ffi-1.9.21
Done installing documentation for ffi after 3 seconds
1 gem installed
$
```

で、改めて bundle install

```
$ bundle install --path vendor/bundle
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
Fetching gem metadata from https://rubygems.org/............
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Using rake 12.3.2
Using concurrent-ruby 1.1.5

(略)

Using railties 5.2.3
Using coffee-rails 4.2.2
Fetching ffi 1.9.21
Installing ffi 1.9.21 with native extensions
```

うまくいった

## バージョンの選び方

`ffi 1.9.21` を選ぶべきだというわけではないのですが、あらかじめ mac 側にインストールしてある可能性（他の ruby プログラムを動かすためにインストールしたことがあった、など）を考えれば、たとえば `gem list` で調べればインストール可能なバージョンがわかるはず

```
$ gem list ffi

*** LOCAL GEMS ***

ffi (1.9.21)
public_suffix (3.0.3)
```

それ以外では、 https://rubygems.org/gems/ffi/versions を見て、一つ前のバージョンの最新を選ぶと良いと思います。今回だと、失敗したのは `1.11.0` なので、 `1.10.x` の中での最新の `1.10.0` を試す、それでもダメなら `1.9.25` を試す、...を繰り返す、など。

時間がある人は、もちろん原因を特定してそれが解決できる最新のバージョンを選びましょう。