archlinuxに異なるバージョンのパッケージを同居させたい

# はじめに
本記事は、archlinuxで異なるバージョンのパッケージを同居させる手順（備忘録）です。
※元作業の関係上、基本的にルートユーザーで作業を行っています。

# 背景・やったこと
- archlinuxを使う中で古いバージョンのパッケージを使う必要が出てきた（nodejs）
- それにあたって関連パッケージもバージョンを落とす必要が出た（npm, icu）
- しかし最新版がないと動かないモジュールもあった（→ icuは最新版も必要）

本記事では nodejs, npm, icu の3つのパッケージが登場しますが、やったこととしては以下の通りです。
- **icuの複数バージョンを同居させた** ←タイトルの件
- nodejs, npmは古いバージョンにした

# バージョンを落とすためのモジュールを導入
archlinuxでは「基本的にパッケージは最新版を使う」という思想があるらしく、`pacman`などではバージョンを落とすことができません。
そのため、`downgrade`というモジュールをgit経由でインストールします。

#### gitのインストール
```sh
pacman -S --noconfirm git
```

#### downgradeのインストール
```sh
# 作業用ディレクトリの作成
mkdir /work
chmod 777 /work

# 後続のmakepkgコマンドがrootで実行できないため、一般ユーザーにスイッチ
su - arch
# git clone
cd /work
git clone https://aur.archlinux.org/downgrade.git

# downgradeパッケージのインストール
cd /work/downgrade
makepkg -si
（ユーザーのパスワードを入力したり、Yの入力をする）

# ルートユーザーに戻る
exit
```

# ダウングレードと複数バージョンの同居
#### nodejs, npmの最新版をインストール
```sh
# nodejsのインストール
pacman -S --noconfirm nodejs npm
```

#### nodejs, npmをダウングレード
先ほどインストールした`downgrade`を使ってパッケージのバージョンを落とします。

```sh
# nodejsをダウングレード
downgrade nodejs
16.6.1
（Proceed with installation? [Y/n] には Yとしておき、
  add nodejs to IgnorePkg? [y/N] にも yとしておく）

# npmをダウングレード（nodejs16.6.1に対応するのが7.20.3だった）
downgrade npm
7.20.3
（Proceed with installation? [Y/n] には Yとしておき、
  add nodejs to IgnorePkg? [y/N] にも yとしておく）

# nodeのバージョン確認を行うと、libicui18n.so.69 がないというエラーが出る
node --version
node: error while loading shared libraries: libicui18n.so.69: cannot open shared object file: No such file or directory
```

#### libicuiをダウングレードする
最終的に最新版も入れますが、一旦`downgrade`を使って同居させたいバージョンまで落とします。

```sh
# icuをダウングレード
downgrade icu
69.1
（Proceed with installation? [Y/n] には Yとしておき、
  add nodejs to IgnorePkg? [y/N] には Nとしておく）
```

#### 古いバージョンのファイルを退避
このままではバージョン更新で上書きされてしまうので、古いパッケージの置き場を作り移動します。
```sh
# 古いパッケージが入ったことを確認し、old用のフォルダへ移動する
## 69.1のバージョンが入っていることを確認する
ls -l /usr/lib/libicu*

# 古いバージョンを退避するディレクトリ作成
mkdir -p /usr/lib_old

# libicuから始まるパッケージを退避する
ls -l /usr/lib/libicu* | grep '^-' | while read line; do
   org_path=$(echo $line | awk '{print $9}')
   file_name=$(echo $org_path | awk -F '/' '{print $NF}')
   cp -p $org_path /usr/lib_old/$file_name
   echo "copy $file_name"
done

# 退避したファイルの確認
ls -l /usr/lib_old
```

#### libicuiを最新化する

```sh
# ダウングレード＆ignoreの設定の解除
# downgradeした際に、icuが自動更新をしない設定になっている場合は解除する
grep 'IgnorePkg =' /etc/pacman.conf

# pacman.confの変更
vim /etc/pacman.conf
>>> vim変更内容 >>>
# IgnorePkg の設定からicuを削除（ある場合）
<修正後サンプル>
IgnorePkg = nodejs npm
<<< vim変更内容 <<<

# icuを最新化
pacman -Syu --noconfirm icu
```

#### 退避した古いバージョンのicuファイルにリンクを貼る
archlinuxのライブラリの使用上、`/usr/lib/`配下にリンクが貼ってあれば動く様なので先ほど退避したファイルへのリンクを貼ります。
```sh
# 現在のlibicuのリンク確認
ls -l /usr/lib/libicu*

# 退避した古いicuファイル
ls -l /usr/lib_old/libicu*

# リンクを貼る
ls -l /usr/lib_old/libicu* | grep '^-' | while read line; do
   old_path=$(echo $line | awk '{print $9}')
   file_name=$(echo $old_path | awk -F '/' '{print $NF}')
   ln -s $old_path /usr/lib/$file_name
   echo "create link to $file_name"
done

# 貼ったリンクの確認
ls -l /usr/lib/libicu*

# パスの読み込み直し
ldconfig
```

#### nodeコマンドが実行できることを確認する
```sh
node --version
```


本記事のやり方が正解かは分かりませんが、目的は達成できたので良しとします。

以上

# 関連記事
- [NASNEを自作してみた](https://qiita.com/hirmr/items/cde0baf51d82ca9de791)