Amazon Linux 2 で Remi Repository の php を使って php-imagick を動かす

# はじめに

Amazon Linux 2 で PHP を使うとなると `amazon-linux-extras` で php をインストールするのが簡単だが、今回は（現時点で） PHP 7.4 を使いたかったので remi リポジトリから PHP をインストールした。
この時に php-imagick を入れようとして四苦八苦したので忘れないようにメモ。


# 作業手順

まずは remi リポジトリを yum で利用可能にしていく。 

```bash
# remi には epel が必要
sudo amazon-linux-extras install -y epel
# remi repository を追加
sudo rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
sudo rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi
```

続いて PHP 7.4 のインストール

```bash
# 必要なライブラリを先に入れる
sudo yum -y install ncurses-compat-libs
# amzn2-core を無効にしないと amzn2-core の php が選択されてしまう
# 依存関係の解決を手動で実施するため、必要なライブラリは先に入れる
sudo yum -y install php --enablerepo=remi-php74 --disablerepo=amzn2-core
```

これで php 7.4 がインストールされたことを確認

```
$ php -v
PHP 7.4.1 (cli) (built: Dec 17 2019 16:35:58) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
```

そして、PHP で ImageMagick の機能を使うために `php-imagick` をインストールすると、残念ながら依存関係が足りない。

```bash
$ sudo yum -y install php-imagick --enablerepo=remi-php74 
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
(中略)
---> Package mesa-libglapi.x86_64 0:17.2.3-8.20171019.amzn2.0.4 will be installed
--> Finished Dependency Resolution
Error: Package: ImageMagick6-libs-6.9.10.79-1.el7.remi.x86_64 (remi-safe)
           Requires: libraw_r.so.19()(64bit)
 You could try using --skip-broken to work around the problem
```

これは [LibRaw](https://github.com/LibRaw/LibRaw) というライブラリの version 0.19 が必要なのだが、残念ながら amzn2-core では version 0.14 しか提供されていない（※記事執筆現在）。
そのため、依存関係が解決できずにエラーとなる。

ここでは、外部から RPM を取得・インストールすることで必要なバージョンを解決する。

```bash
$ sudo rpm -ivh http://mirror.centos.org/centos/7/os/x86_64/Packages/LibRaw-0.19.2-1.el7.x86_64.rpm
Retrieving http://mirror.centos.org/centos/7/os/x86_64/Packages/LibRaw-0.19.2-1.el7.x86_64.rpm
warning: /var/tmp/rpm-tmp.iP7cfm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:LibRaw-0.19.2-1.el7              ################################# [100%]
```

この後、もう一度インストールを実施すると、うまくいったように見える。

```bash
$ sudo yum -y install php-imagick --enablerepo=remi-php74 
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
(中略)
 Installing : fribidi-0.19.4-6.amzn2.0.2.x86_64
(中略)
Installed:
  php-pecl-imagick.x86_64 0:3.4.4-6.el7.remi.7.4                                                                                                                           

Dependency Installed:
  ImageMagick6-libs.x86_64 0:6.9.10.79-1.el7.remi         OpenEXR-libs.x86_64 0:1.7.1-7.amzn2.0.2                   atk.x86_64 0:2.22.0-3.amzn2.0.2                       
  avahi-libs.x86_64 0:0.6.31-19.amzn2                     cairo.x86_64 0:1.14.8-2.amzn2.0.2                         cups-libs.x86_64 1:1.6.3-35.amzn2                     
  fftw-libs-double.x86_64 0:3.3.3-8.amzn2.0.2             fontconfig.x86_64 0:2.10.95-11.amzn2.0.2                  fontpackages-filesystem.noarch 0:1.44-8.amzn2         
  fribidi.x86_64 0:0.19.4-6.amzn2.0.2                     gd.x86_64 0:2.0.35-26.amzn2.0.2                           gdk-pixbuf2.x86_64 0:2.36.5-1.amzn2.0.2               
  ghostscript.x86_64 0:9.06-8.amzn2.0.5                   ghostscript-fonts.noarch 0:5.50-32.amzn2                  graphite2.x86_64 0:1.3.10-1.amzn2.0.2                 
  graphviz.x86_64 0:2.30.1-21.amzn2.0.1                   gtk-update-icon-cache.x86_64 0:3.22.26-4.amzn2            gtk2.x86_64 0:2.24.31-1.amzn2.0.2                     
  harfbuzz.x86_64 0:1.3.2-1.amzn2.0.2                     hicolor-icon-theme.noarch 0:0.12-7.amzn2                  ilmbase.x86_64 0:1.0.3-7.amzn2.0.2                    
  libICE.x86_64 0:1.0.9-9.amzn2.0.2                       libSM.x86_64 0:1.2.2-2.amzn2.0.2                          libX11.x86_64 0:1.6.5-2.amzn2.0.2                     
  libX11-common.noarch 0:1.6.5-2.amzn2.0.2                libXau.x86_64 0:1.0.8-2.1.amzn2.0.2                       libXaw.x86_64 0:1.0.13-4.amzn2.0.2                    
  libXcomposite.x86_64 0:0.4.4-4.1.amzn2.0.2              libXcursor.x86_64 0:1.1.15-1.amzn2                        libXdamage.x86_64 0:1.1.4-4.1.amzn2.0.2               
  libXext.x86_64 0:1.3.3-3.amzn2.0.2                      libXfixes.x86_64 0:5.0.3-1.amzn2.0.2                      libXfont.x86_64 0:1.5.2-1.amzn2.0.2                   
  libXft.x86_64 0:2.3.2-2.amzn2.0.2                       libXi.x86_64 0:1.7.9-1.amzn2.0.2                          libXinerama.x86_64 0:1.1.3-2.1.amzn2.0.2              
  libXmu.x86_64 0:1.1.2-2.amzn2.0.2                       libXpm.x86_64 0:3.5.12-1.amzn2.0.2                        libXrandr.x86_64 0:1.5.1-2.amzn2.0.2                  
  libXrender.x86_64 0:0.9.10-1.amzn2.0.2                  libXt.x86_64 0:1.1.5-3.amzn2.0.2                          libXxf86vm.x86_64 0:1.1.4-1.amzn2.0.2                 
  libfontenc.x86_64 0:1.1.3-3.amzn2.0.2                   libglvnd.x86_64 1:1.0.0-1.amzn2.0.2                       libglvnd-egl.x86_64 1:1.0.0-1.amzn2.0.2               
  libglvnd-glx.x86_64 1:1.0.0-1.amzn2.0.2                 libpng.x86_64 2:1.5.13-7.amzn2.0.2                        libraqm.x86_64 0:0.7.0-1.el7                          
  librsvg2.x86_64 0:2.40.16-1.amzn2.0.2                   libthai.x86_64 0:0.1.14-9.amzn2.0.2                       libtool-ltdl.x86_64 0:2.4.2-22.2.amzn2.0.2            
  libwayland-client.x86_64 0:1.14.0-2.amzn2.0.1           libwayland-server.x86_64 0:1.14.0-2.amzn2.0.1             libwebp7.x86_64 0:1.0.2-1.el7.remi                    
  libwmf-lite.x86_64 0:0.2.8.4-41.amzn2.0.3               libxcb.x86_64 0:1.12-1.amzn2.0.2                          libxshmfence.x86_64 0:1.2-1.amzn2.0.2                 
  lyx-fonts.noarch 0:2.2.3-1.el7                          mesa-libEGL.x86_64 0:17.2.3-8.20171019.amzn2.0.4          mesa-libGL.x86_64 0:17.2.3-8.20171019.amzn2.0.4       
  mesa-libgbm.x86_64 0:17.2.3-8.20171019.amzn2.0.4        mesa-libglapi.x86_64 0:17.2.3-8.20171019.amzn2.0.4        pango.x86_64 0:1.40.4-1.amzn2.0.2                     
  pixman.x86_64 0:0.34.0-1.amzn2.0.2                      poppler-data.noarch 0:0.4.6-3.amzn2.0.1                   urw-fonts.noarch 0:2.4-16.amzn2                       
  xorg-x11-font-utils.x86_64 1:7.5-20.amzn2.0.2          

Complete!
```

しかし、この状態で `php -m` として利用可能なモジュールを確認するとエラーが出ており、正常に使える状態になっていない。

```bash
$ php -m
PHP Warning:  PHP Startup: Unable to load dynamic library 'imagick.so' (tried: /usr/lib64/php/modules/imagick.so (/lib64/libraqm.so.0: undefined symbol: fribidi_get_bracket_types), /usr/lib64/php/modules/imagick.so.so (/usr/lib64/php/modules/imagick.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
[PHP Modules]
bz2
calendar
Core
ctype
curl
date
exif
fileinfo
filter
ftp
gettext
hash
iconv
json
libxml
openssl
pcntl
pcre
Phar
readline
Reflection
session
sockets
SPL
standard
tokenizer
zlib

[Zend Modules]
```

エラーメッセージである `/lib64/libraqm.so.0: undefined symbol: fribidi_get_bracket_types` について調べると、これは [fribidi](https://github.com/fribidi/fribidi) のバージョンが 1.0 未満の場合に発生する問題であるらしい。
上記のインストールメッセージのなかにわざとらしく残しているが、amzn2-core でインストールできるバージョンは 1.0 未満なので、こちらも同様に rpm で解決する。

```bash
$ sudo rpm -ivh http://mirror.centos.org/centos/7/os/x86_64/Packages/fribidi-1.0.2-1.el7.x86_64.rpm
Retrieving http://mirror.centos.org/centos/7/os/x86_64/Packages/fribidi-1.0.2-1.el7.x86_64.rpm
warning: /var/tmp/rpm-tmp.plm1q2: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
Preparing...                          ################################# [100%]
        file /usr/bin/fribidi from install of fribidi-1.0.2-1.el7.x86_64 conflicts with file from package fribidi-0.19.4-6.amzn2.0.2.x86_64
        file /usr/lib64/libfribidi.so.0 from install of fribidi-1.0.2-1.el7.x86_64 conflicts with file from package fribidi-0.19.4-6.amzn2.0.2.x86_64

# コンフリクトするので既存パッケージを remove する
$ sudo yum -y remove fribidi
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
(中略)
Dependency Removed:
  ImageMagick6-libs.x86_64 0:6.9.10.79-1.el7.remi                libraqm.x86_64 0:0.7.0-1.el7                php-pecl-imagick.x86_64 0:3.4.4-6.el7.remi.7.4               

Complete!

# 改めてインストールし、上記の削除時に依存関係で削除された部分を再インストールする
$ sudo rpm -ivh http://mirror.centos.org/centos/7/os/x86_64/Packages/fribidi-1.0.2-1.el7.x86_64.rpm
Retrieving http://mirror.centos.org/centos/7/os/x86_64/Packages/fribidi-1.0.2-1.el7.x86_64.rpm
warning: /var/tmp/rpm-tmp.AIsn76: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:fribidi-1.0.2-1.el7              ################################# [100%]
$ sudo yum -y install php-imagick --enablerepo=remi-php74 
(中略)
Installed:
  php-pecl-imagick.x86_64 0:3.4.4-6.el7.remi.7.4                                                                                                                           

Dependency Installed:
  ImageMagick6-libs.x86_64 0:6.9.10.79-1.el7.remi                                               libraqm.x86_64 0:0.7.0-1.el7                                              

Complete!
```

改めて `php -m` をすると、エラーメッセージは表示されずにモジュール一覧の中に imagick が表示される。

```
$ php -m
[PHP Modules]
bz2
calendar
Core
ctype
curl
date
exif
fileinfo
filter
ftp
gettext
hash
iconv
imagick
json
libxml
openssl
pcntl
pcre
Phar
readline
Reflection
session
sockets
SPL
standard
tokenizer
zlib

[Zend Modules]
```

あとは簡単なコードを書いてうまく動くかを確認。

```php:test.php
<?php
    # 画像の型を変更
    $image = new Imagick('input.png');
    $image->writeImage("output.jpg");
```

```bash
$ php test.php
$ ls -al 
...
-rw-rw-r-- 1 ec2-user ec2-user  6953 Dec 18 16:49 input.png
-rw-rw-r-- 1 ec2-user ec2-user 33240 Dec 18 16:49 output.jpg
-rw-rw-r-- 1 ec2-user ec2-user    84 Dec 18 16:47 test.php
...
```

というわけで、うまく動きました。
なお、本当は yum のみで解決したかったけれど、今回は手っ取り早く rpm を使っています。

# オマケ

これだけだとコマンドラインの ImageMagick は入っていないので、これを入れたい場合は remi リポジトリから以下のようにインストールする。
amzn2-core の場合、6.7.8.9 というやや古いバージョンが入ってくるので、7系などのより新しいバージョンを入れたい場合に。

```bash
$ sudo yum -y install ImageMagick6 --enablerepo=remi
$ convert 
```