Mac OS X 環境で Memcached::libmemcached が入らない場合の対処法


`cpanm` で [Cache::Memcached::libmemcached](http://search.cpan.org/dist/Cache-Memcached-libmemcached) モジュールを入れようとしたら入らなかったので、build.log を見ていたら、それが依存している [Memcached::libmemcached](http://search.cpan.org/dist/Memcached-libmemcached) モジュールのインストールに失敗しているので色々試行錯誤してみました。

__2014年4月の情報__です。環境は以下。

* Mac OS X Mavericks
* Perl 5.18 on plenv and/or perlbrew
* このときのMemcached::libmemcachedのバージョンは 1.001702

この辺りの情報はすぐ陳腐化するので、1年以上前の場合はあまりアテにしないほうがいいかもしれません(この記事をみる未来のみなさんへのメッセージでもあります)。また各種モジュールのバージョンの詳細は各種Changelogも参照ください。

##前提条件

memcached にアクセスするモジュールには色々あって、 __今の時代であればあえてCache::Memcached::libmemcached (つまるところ Memcached::libmemcached) を使う必要は無い__ と各所から言われました。今であれば

* [Cache::Memcached](http://search.cpan.org/dist/Cache-Memcached) Pure Perlで遅いと言われるかもしれないけど、それゆえインストールでハマりどころが少ない
* [Cache::Memcached::Fast](http://search.cpan.org/dist/Cache-Memcached-Fast) XS実装だけど自前で書かれているし多くの採用事例があるので情報が多い

を使うべきでしょう。

私の場合、以前からある業務アプリケーションの改修のため、Cache::Memcached::libmemcached を入れる必要がありました。

##結果的に

今回は 1.001702 が Mac OS X 環境 (Xcode 5.2) でダメだという結論に至ったので、一つ古いバージョンをインストールすることでお茶を濁しています。なので以下の多くのトラブルシューティングは、もしかしたら 1.001702 で問題解決にたどり着こうという人のヒントにしかなっていません。

一つ古いバージョンの Memcached::libmemcached のインストール方法は下の方にスクロールしてみてください。

##普通にcpanmしてみる

とりあえず普通に`cpanm`してみます。

```shell
$ cpanm Memcached::libmemcached 
--> Working on Memcached::libmemcached
Fetching http://www.cpan.org/authors/id/W/WO/WOLFSAGE/Memcached-libmemcached-1.001702.tar.gz ... OK
Configuring Memcached-libmemcached-1.001702 ... N/A
! Configure failed for Memcached-libmemcached-1.001702. See /Users/ogata/.cpanm/build.log for details.
```

失敗しました。

build.log を見てみると最後のほうにエラーの内容が書かれています。私の場合は以下のようなものでした。

    ./libmemcached-1.0/memcached.h:46:12: fatal error: 'tr1/cinttypes' file not foun
    d
    #  include <tr1/cinttypes>
               ^
      CXX      libhashkit/libhashkit_libhashkitinc_la-has.lo
      CXX      libhashkit/libhashkit_libhashkitinc_la-hashkit.lo
    1 error generated.
    make[1]: *** [libtest/dream.o] Error 1
    make[1]: *** Waiting for unfinished jobs....
    make: *** [install] Error 2
    Unable to build libmemcached: Error running cd src/libmemcached && make install
    
    Aborted.
    -> N/A
    -> FAIL Configure failed for Memcached-libmemcached-1.001702. See /Users/ogata/.
    cpanm/build.log for details.
    Expiring 3 work directories.


tr1/cinnttypes がないと言われています。

Perl の Memcached::libmemcached 自体の問題というよりも libmemcached 自体の問題であることが以下のようにしてわかります。

    $ pwd
    /Users/ogata/.cpanm/latest-build/Memcached-libmemcached-1.001702/src/libmemcached


Memcached::libmemcached は libmemcached 自体のソースコードを同梱しているようです。

##libmemacached自体を単体でビルドしてみる

おもむろにこのディレクトリ内で `./configure` してみると特に問題なく Makefile ができます。

この状態で `make` してみると

```shell
$ make
(中略)
In file included from libmemcached/csl/context.cc:38:
In file included from ./libmemcached/csl/common.h:50:
In file included from ./libmemcached/common.h:114:
./libmemcached-1.0/memcached.h:46:12: fatal error: 'tr1/cinttypes' file not
      found
#  include <tr1/cinttypes>
           ^
1 error generated.
  CXX      libmemcached/csl/libmemcached_libmemcached_la-parser.lo
make[1]: *** [libmemcached/csl/libmemcached_libmemcached_la-context.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
In file included from libmemcached/csl/parser.yy:39:
In file included from ./libmemcached/csl/common.h:50:
In file included from ./libmemcached/common.h:114:
./libmemcached-1.0/memcached.h:46:12: fatal error: 'tr1/cinttypes' file not
      found
#  include <tr1/cinttypes>
           ^
1 error generated.
make[1]: *** [libmemcached/csl/libmemcached_libmemcached_la-parser.lo] Error 1
make: *** [all] Error 2
```

tr1/cinttypes がないと言っているのは libmemcached のビルドです。

libmemcached のビルドについて調べていると、このgistにヒントがありました。

* https://gist.github.com/potiuk/6332854

Homebrew の formula のようですが、環境変数を設定している部分があります。

```Ruby
    if MacOS.version > :mountain_lion
      ENV.append 'CXXFLAGS', "-I#{MacOS.sdk_path}/usr/include/c++/4.2.1"
      ENV.append 'LIBS', "#{MacOS.sdk_path}/usr/lib/libstdc++.dylib"
    end
```

真似てみましょう。対象ファイルやディレクトリがどこにあるかは、Spotlightのコマンドラインインターフェース `mdfind` を使うことでなんとなくわかります。

```shell
$ mdfind -name 4.2.1 
/Library/Developer/CommandLineTools/usr/lib/llvm-gcc/4.2.1
/usr/include/c++/4.2.1
```

自分の環境の沿った場所を見つけたら、それを環境変数として設定します。

```shell
$ export CXXFLAGS=-I/usr/include/c++/4.2.1
$ export LIBS=/usr/lib/libstdc++.6.0.9.dylib
```

さて、libmemcached のビルド結果は変わるでしょうか。

```shell
$ ./configure
(略)
$ make
(中略)
ld: file not found: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/5.1/lib/darwin/libclang_rt.ubsan_osx.a
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [libtest/abort] Error 1
make[1]: *** Waiting for unfinished jobs....
1 warning generated.
1 warning generated.
1 warning generated.
make: *** [all] Error 2
```

色々とwarningラッシュになりますが、とりあえずさっきよりは`make`コマンドの実行が長くなります。とはいえ、私の環境ではエラーが出てビルドは途中で停止してしまいました。

内容は `ld` コマンドが、長大なディレクトリパスの中に `libclang_rt.ubsan_osx.a` が見つからなかったというもの。

確かに確認してみると、私のXcode (5.2) 環境にはありませんでした。

```shell
$ ls -l /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/5.1/lib/darwin/
total 304
-rw-r--r--  1 root  wheel    7832  3 11 09:16 libclang_rt.10.4.a
-rw-r--r--  1 root  wheel  272468  3 11 09:16 libclang_rt.cc_kext.a
-rw-r--r--  1 root  wheel  131548  3 11 09:16 libclang_rt.cc_kext_ios5.a
-rw-r--r--  1 root  wheel    1824  3 11 09:16 libclang_rt.eprintf.a
-rw-r--r--  1 root  wheel   20812  3 11 09:16 libclang_rt.ios.a
-rw-r--r--  1 root  wheel    6000  3 11 09:16 libclang_rt.osx.a
-rw-r--r--  1 root  wheel   81420  3 11 09:16 libclang_rt.profile_ios.a
-rw-r--r--  1 root  wheel   38448  3 11 09:16 libclang_rt.profile_osx.a
```

libclang_rt.ubsan_osx.a が存在してどこかにあれば、それのシンボリックリンクをここに作るなどして対応できるとは思いますが、私の環境では見つかりませんでした。また、これで検索してみたものの、clang関連の英語の資料が見つかったくらいで、思ったような手がかりが見つからなかったので、結局ここで諦めてしまいました。

##古いバージョンのMemcached::libmemcachedを試す

検索してもこういった情報が見つからなかったので、Xcode か Memcached::libmemcached (libmemcached) の以前のバージョンであればこういった問題がなかったんじゃないかと推察して、古いバージョンを試してみることにしました。CPANで見つかる[一つ前のバージョンは 0.4406](http://search.cpan.org/~timb/Memcached-libmemcached-0.4406/)。番号が1より小さくなりました。

CPANから [Memcached-libmemcached-0.4406.tar.gz をダウンロード](http://search.cpan.org/CPAN/authors/id/T/TI/TIMB/Memcached-libmemcached-0.4406.tar.gz)してきます。

(`cpanm` コマンドには `cpanm Module@version` という指定があるのですが、ここでは *.tar.gz をダウンロードすることにします。詳細は `perldoc cpanm` を参照)

おもむろに `cpanm` でこの .tar.gz ファイルを指定します。

```shell
$ cpanm Downloads/Memcached-libmemcached-0.4406.tar.gz 
$ cpanm Downloads/Memcached-libmemcached-0.4406.tar.gz 
--> Working on Downloads/Memcached-libmemcached-0.4406.tar.gz
Fetching file:///Users/ogata/Downloads/Memcached-libmemcached-0.4406.tar.gz ... OK
Configuring Memcached-libmemcached-0.4406 ... N/A
! Configure failed for Memcached-libmemcached-0.4406. See /Users/ogata/.cpanm/build.log for details.
```

失敗したので build.log を見てみます。

    Wide character in printf at /Users/ogata/perl5/perlbrew/perls/perl-5.18/lib/5.18
    .0/Pod/Simple.pm line 539.
    memslap.pop around line 78: Non-ASCII character seen before =encoding in 'don’t'
    . Assuming UTF-8
    POD document had syntax errors at /Users/ogata/perl5/perlbrew/perls/perl-5.18/bi
    n/pod2man line 71.
    make[3]: *** [memslap.1] Error 255
    make[2]: *** [install] Error 2
    make[1]: *** [install-recursive] Error 1
    make: *** [install] Error 2
    Unable to build libmemcached: Error running cd src/libmemcached && make install
    
    Aborted.
    -> N/A
    -> FAIL Configure failed for Memcached-libmemcached-0.4406. See /Users/ogata/.cp
    anm/build.log for details.


読んでみると、PODの中にASCIIじゃない文字があるのにencoding指定がなかったという些細なもの。

伸長して直してみましょう。

```shell
$ find Memcached-libmemcached-0.4406 -name memslap\* 
Memcached-libmemcached-0.4406/src/libmemcached/clients/memslap.c
Memcached-libmemcached-0.4406/src/libmemcached/docs/memslap.pod
```

memslap.pop の元ネタは memslap.pod だとあたりをつけて直します。Vim か何かで開いて、冒頭に `=encoding utf8` と加えるだけの簡単な仕事です。

```shell
$ head -n 5 Memcached-libmemcached-0.4406/src/libmemcached/docs/memslap.pod 
=encoding utf8

=head1 NAME

memslap - Load testing and benchmarking tool for memcached
```

こうなるようにします。

再びこれを `tar` で戻して `cpanm` します。

```shell
$ tar zcf Memcached-libmemcached-0.4406.tar.gz Memcached-libmemcached-0.4406/
$ cpanm Memcached-libmemcached-0.4406.tar.gz 
--> Working on Memcached-libmemcached-0.4406.tar.gz
Fetching file:///Users/ogata/Memcached-libmemcached-0.4406.tar.gz ... OK
! Bad archive: Memcached-libmemcached-0.4406.tar.gz
! Failed to unpack Memcached-libmemcached-0.4406.tar.gz: no directory
! Failed to fetch distribution 
```

Bad archive って言われる場合。Mac OS X の `tar` コマンド、伸長は問題無いのですが、圧縮をすると `cpanm` にとって Bad archive になってしまうようですね。このMacの`tar`の問題は割とよく知られているようです。Homebrew で gnu-tar を入れて使っている人は問題無いかもしれません。Linux 環境で作業を行うことでも回避できます。

```shell
$ cpanm Memcached-libmemcached-0.4406.tar.gz 
--> Working on Memcached-libmemcached-0.4406.tar.gz
Fetching file:///Users/ogata/Memcached-libmemcached-0.4406.tar.gz ... OK
Configuring Memcached-libmemcached-0.4406 ... FAIL
! Timed out (> 60s). Use --verbose to retry.
! Configure failed for Memcached-libmemcached-0.4406. See /Users/ogata/.cpanm/build.log for details.
```

こんなことを言われた場合には素直に `--verbose` を付けてみます。

```shell
$ cpanm Memcached-libmemcached-0.4406.tar.gz
(中略)
Successfully installed Memcached-libmemcached-0.4406
1 distribution installed
```

無事入りました。

Cache::Memcached::libmemcache の __2014年4月現在__ の最新バージョン [0.04001](http://search.cpan.org/~timb/Cache-Memcached-libmemcached-0.04001/) の Makefile.PL を見ると、問題と格闘した Memcached::libmemcached のバージョンを要求しています。

```Perl
use strict;
use inc::Module::Install;
 
name('Cache-Memcached-libmemcached');
all_from('lib/Cache/Memcached/libmemcached.pm');

requires('Memcached::libmemcached', '1.001701');
requires('Storable');
requires('Carp');
requires('Task::Weaken');

recommends('Compress::Zlib');

build_requires('Test::More', 0.80);

auto_include;
WriteAll;
```

なのでこれもまた、一つ前の古いバージョン [0.02011](http://search.cpan.org/~dmaki/Cache-Memcached-libmemcached-0.02011/) の *.tar.gz をダウンロードしてインストールをすることになります。

```shell
$ cpanm Downloads/Cache-Memcached-libmemcached-0.02011.tar.gz 
--> Working on Downloads/Cache-Memcached-libmemcached-0.02011.tar.gz
Fetching file:///Users/ogata/Downloads/Cache-Memcached-libmemcached-0.02011.tar.gz ... OK
Configuring Cache-Memcached-libmemcached-0.02010 ... OK
Building and testing Cache-Memcached-libmemcached-0.02010 ... OK
Successfully installed Cache-Memcached-libmemcached-0.02010
1 distribution installed
```

特に問題なく入りました。こちらは `cpanm Cache::Memcached::libmemcached@0.02011` でもよいかもしれません。

インストールできて安堵したので、現時点で重点的に動作確認はしていません。ご了承下さい。

XcodeかPerlモジュール、どちらかのバージョンが上がってすんなり入るようになってくれると嬉しいなと感じます。

----

前述ですが、PerlでMemcachedにアクセスしたいのであれば、今使うのであれば __Cache::Memcached::Fast__ や、それに依存したモジュールを使いましょう。

----

* この件に関して tokuhiromu さんがブログを書いてくださいました。 [How do I install Memcached::libmemcached on OSX. - blog.64p.org](http://blog.64p.org/entry/2014/04/06/183859)