31 December 2009

Mac OS X に Image::Magick (PerlMagick) をインストール

f:id:cou929_la:20091230152647j:image

perl の ImageMagick のラッパーである Image::Magick (PerlMagick) のインストールに非常に手間どったので, メモしておきます.

インストール方法

まずは結論から. cpan などは使わないで, ソースからビルドするとうまくいきました.

まずは macports から ImageMagick 本体をインストール.

% sudo port install ImageMagick

ImageMagickのバージョンをチェック. ここがポイントで, 対応したバージョンの PerlMagick じゃないとうまくいきません. ぼくの環境だと 6.5.2-9 でした.

% convert -version

または

% port info ImageMagick


Version: ImageMagick 6.5.2-9 2009-12-27 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2009 ImageMagick Studio LLC

次は, 適したバージョンの ImageMagick を以下からダウンロードします.

Download @ ImageMagick

展開して, PerlMagick ディレクトリに入る.

% tar -zxvf ImageMagick-6.5.2-9.tar.gz
% cd ImageMagick-6.5.2-9/PerlMagick

Makefile.PLを編集して, コンパイル時に /opt/local/lib と /opt/local/include を見に行くようにします. たぶんこの部分は port から ImageMagick を入れた場合のみ必要です.

# -I/opt/local/include を追加
'INC'     => '-I/opt/local/include -I../ -I.. -I/usr/include/freetype2 -I/usr/include/libxml2',

...

# -L/opt/local/lib を追加
'LIBS'  => [ '-L/opt/local/lib -L../magick/.libs -lMagickCore -L../wand/.libs -lMagickWand -lperl -lm' ],

ビルドしてみます.

% perl Makefile.PL
% make

ぼくの環境だとここで --as-needed というオプションに対応していないと怒られました. --as-needed はリンカ(ld)のオプションで, そのバイナリをつくるのに本当に必要なライブラリだけをリンクするという意味らしいです.

Project:Quality Assurance/As-needed - Gentoo Wiki

本当はこのオプションに対応しているバージョンの ld を入れた方がいいんですけど, 別にこのオプションをつけなくてもただ少しできあがるバイナリのサイズが大きくなるだけで, 機能的には問題ないと判断. Makefile からこのオプションを消すという手っ取り早い方法を取りました.

Makefile.PL の以下の行を修正. この2行から,

'LDFLAGS'    =>  "-L../magick/.libs -lMagickCore -L../wand/.libs -lMagickWand $Config{'ldflags'} -Wl,--as-needed -lfreetype",

'LDDLFLAGS'  => "-L../magick/.libs -lMagickCore -L../wand/.libs -lMagickWand $Config{'lddlflags'} -Wl,--as-needed -lfreetype",

", --as-needed" を削除.

'LDFLAGS'    =>  "-L../magick/.libs -lMagickCore -L../wand/.libs -lMagickWand $Config{'ldflags'} -Wl -lfreetype",

'LDDLFLAGS'  => "-L../magick/.libs -lMagickCore -L../wand/.libs -lMagickWand $Config{'lddlflags'} -Wl -lfreetype",

これでビルドする.

% perl Makefile.PL
% make
% sudo make install

うまくいきました.

参考サイト

410 Gone


試したこと

以下失敗した作業のログ. 当然ですけど最初は cpan からインストールを試みました.

% cpan -i Image::Magick

以下のエラーメッセージとともにmakeできないといわれました.

  • lmagickcore がない (harmless)
  • lperl がない (harmless)
  • gccに fopenmp というオプションが存在しない

上二つは harmless らしいけど, 一応対応しておきました.

ImageMagick は port で入れたので, ライブラリは /opt/local/lib に入っています. lperlの場所も調べておきます.

% locate libperl
/System/Library/Perl/5.8.8/darwin-thread-multi-2level/CORE/libperl.dylib
/System/Library/Perl/lib/5.8/libperl.dylib
...

環境変数にパスを追加することを試みたけど, いまいちうまくいかず, 面倒なのでアドホックだけど直接makefileを編集することにしました. cpanコマンドを実行すると, ~/.cpan/build/ モジュールが以下にDLされそこで展開, ビルド, インストールされます. よって~/.cpan/build/ImageMagick-*/ の中の Makefile.PL をいじれば良い. 適当に LDFLAGS_* のような変数にライブラリのパスを追加. 具体的にはこんな感じです.

my $INC_magick = '-I../ -I.. -I/usr/include/freetype2 -I/usr/include/libxml2 -I"' . $Config{'usrinc'} . '/ImageMagick"';
my $LIBS_magick = '-L/System/Library/Perl/5.8.8/darwin-thread-multi-2level/CORE/ -L/opt/local/lib -L../magick/.libs -lMagickCore -lperl -lm';
my $CCFLAGS_magick = "$Config{'ccflags'} -fopenmp -g -O2 -Wall -W -pthread";
my $LDFLAGS_magick   = "-L/opt/local/lib -L../magick/.libs -lMagickCore $Config{'ldflags'} ";
my $LDDLFLAGS_magick = "-L/opt/local/lib -L../magick/.libs -lMagickCore $Config{'lddlflags'} ";

ここでいったんビルドしてみる. ~/.cpan/build/ImageMagick-6.58/ で perl Makefile.PL -> make. うんうまくいった.

こちらがbefore

% perl Makefile.PL                                                                              
Note (probably harmless): No library found for -lMagickCore
Note (probably harmless): No library found for -lperl                                              
Writing Makefile for Image::Magick

こちらがafter

% perl Makefile.PL                                                                              
Writing Makefile for Image::Magick                                                                 
% make                                                                                          
cc -c  -I../ -I.. -I/usr/include/freetype2 -I/usr/include/libxml2 -I"/usr/include/ImageMagick" -arch ppc -arch i386 -g -pipe -fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -Wdeclaration-after-statement -I/usr/local/include -fopenmp -g -O2 -Wall -W -pthread -O3   -DVERSION=\"6.5.8\" -
DXS_VERSION=\"6.5.8\"  "-I/System/Library/Perl/5.8.8/darwin-thread-multi-2level/CORE"  -D_LARGE_FILE
S=1 -DHAVE_CONFIG_H Magick.c                                                                       
cc1: error: unrecognized command line option "-fopenmp"                                            
cc1: error: unrecognized command line option "-fopenmp"                                            
lipo: can't open input file: /var/folders/2h/2h4VcD2qEhC-TFlW-u4iiE+++TI/-Tmp-//cc4Xc4jX.out (No suc
h file or directory)                                                                               
make: *** [Magick.o] Error 1   

lMagickCore 問題とlperl 問題は解決. あとは fopenmp というオプションです.

てきとうにググって以下の記述を発見.

Advanced Unix Source Installation @ ImageMagick

Certain ImageMagick algorithms, for example convolution, can achieve a significant speed-up with the assistance of the OpenMP API when running on modern dual and quad-core processors.

"ImageMagick の一部のアルゴリズム(コンボリューションなど)はOpenMP APIを使用しています. これにより, マルチコア環境では著しくスピードアップします." なるほど. OpenMPとはなんだろう.

403 Forbidden

The OpenMP API supports multi-platform shared-memory parallel programming in C/C++ and Fortran. OpenMP is a portable, scalable model with a simple and flexible interface for developing parallel applications on platforms from the desktop to the supercomputer.

"共有メモリ並列プログラミング(?)のためのAPI. C/C++/Fortranに対応. プラットフォームの違いを吸収". なるほど. gcc4.4 以降が OpenMP v3.0 という規格に対応しているらしい.

手元のmacのgccは4.0.1. これが原因のようです.

mac% gcc --version
i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5490)

port に gcc44 があったのでインストール.

% port search gcc
...
gcc33 @3.3.6 (lang)                                                                                
    The GNU compiler collection                                                                                                                                                                         
gcc34 @3.4.6 (lang)                                                                                
    The GNU compiler collection                                                                                                                                                                      
gcc40 @4.0.4 (lang)                                                                                
    The GNU compiler collection                                                                                                                                                                       
gcc41 @4.1.2 (lang)                                                                                
    The GNU compiler collection                                                                    
gcc42 @4.2.4 (lang)                                                                                
    The GNU compiler collection                                                                                                                                                                       
gcc43 @4.3.3 (lang)                                                                                
    The GNU compiler collection                                                                                                                                                                       
gcc44 @4.4.0 (lang)                                                                                
    The GNU compiler collection                                                                                                                                                                    
gcc45 @4.5-20090611 (lang)                                                                         
    The GNU compiler collection, prerelease BETA  
...

% sudo port install gcc44

gcc44のビルドにものすごく時間がかかりました. /usr/bin/gcc と /usr/bin/cc のシンボリックリンクを gcc-mp-4.4 にはりなおして再make.

% make                                                                                          
cc -c  -I../ -I.. -I/usr/include/freetype2 -I/usr/include/libxml2 -I"/usr/include/ImageMagick" -arch ppc -arch i386 -g -pipe -fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -Wdeclaration-after-statement -I/usr/local/include -fopenmp -g -O2 -Wall -W -pthread -O3   -DVERSION=\"6.5.8\" -DXS_VERSION=\"6.5.8\"  "-I/System/Library/Perl/5.8.8/darwin-thread-multi-2level/CORE"  -D_LARGE_FILES=1 -DHAVE_CONFIG_H Magick.c                                                                       
cc: unrecognized option '-no-cpp-precomp'                                                          
cc1: error: unrecognized command line option "-arch"                                               
cc1: error: unrecognized command line option "-arch"                                               
make: *** [Magick.o] Error 1 

'-no-cpp-precomp' と '-arch' というオプションを認識していないません. /usr/bin を調べたら, gcc4.0 の他に gcc4.2 が入っていることを発見. 調べると gcc4.2 は '-no-cpp-precomp', '-arch', '-fopenmp' のすべてのオプションを認識しました. これを使えば良さそうです. わざわざ時間をかけて4.4をビルドする必要なかった…. 4.2 でコンパイルしてみます.

Magick.xs:64:31: error: magick/MagickCore.h: No such file or directory

ヘッダを見つけられていません. 捜索したところ, /opt/local/include/ImageMagick/magick/ にimagemagickのヘッダがありました. また Makefile.PL を編集して, このディレクトリにパスを通し, 再make.

Magick.xs:1515: error: 'CacheView' undeclared (first use in this function)
Magick.xs:1515: error: (Each undeclared identifier is reported only once
Magick.xs:1515: error: for each function it appears in.)
Magick.xs:1516: error: 'image_view' undeclared (first use in this function)
Magick.xs:2012: error: 'TimeResource' undeclared (first use in this function)
Magick.xs:7671: error: 'DrawInfo' has no member named 'interline_spacing'
Magick.xs:7767: error: 'composite_view' undeclared (first use in this function)
Magick.xs:7870: error: 'DistortCompositeOp' undeclared (first use in this function)

xs のコードの中でエラーが出ています. magick/cache-view.h というヘッダがあったので, 'CacheVIew' などは ImageMagick 側の typedef か何かの模様. しかし cachview*() という名前の関数はあったけど, CacheView という名前の何かは定義されていません. ここで ImageMagick のバージョン違いが原因じゃないかと推測し, このアプローチを捨てました.