はじめに
HEASoft 6.37 を Linux に source からインストールしてみたところ、従来の HEASoft の更新よりも、いくつか事前に知っておいた方がよい点があった。
特に重要だったのは、次の3点である。
- HEASoft 6.37 から XSPEC の spectral model data が本体とは別配布になった
-
ftgetmodeldataを利用するためには、単なるcurlではなく開発用 curl library が必要になる - PyXspec に Anaconda/Conda の Python を使う場合、Anaconda の共有ライブラリと system library が衝突することがある
HEASARC の公式ドキュメントでも、HEASoft 6.37 から spectral model data files は HEASoft distribution に同梱されず、インストール後に ftgetmodeldata などで取得する方式になったと説明されている。(HEASARC)
本記事では、
- Linux 上で HEASoft 6.37 を source build する
- PyXspec を使いたい
- Python は system Python ではなく Anaconda/Conda の環境を使いたい
- 複数の HEASoft version を共存させたい
という場合に、インストール前に確認しておくとよさそうな点をまとめる。
以下のパスはすべて説明用の例である。実際のホスト名、ユーザー名、サーバー構成、内部ディレクトリは記載していない。
まず結論
今回の経験から、source build の場合はおおむね次のように役割を分けると安定した。
C compiler -> system gcc
C++ compiler -> system g++
Fortran compiler -> system gfortran
Perl -> system perl
curl -> system curl
curl-config -> system curl-config
libcurl -> system libcurl
Python executable -> Anaconda/Conda Python
Python headers -> Anaconda/Conda
NumPy headers -> Anaconda/Conda
libpython -> 専用ディレクトリに隔離
libstdc++
ncurses / tinfo
nghttp2
その他の system libraries
-> system libraries
ポイントは、 Anaconda の Python は使うが、Anaconda の lib/ 全体を HEASoft の linker に見せない ことである。
HEASARC 公式ドキュメントでも、PyXspec に使用する Python は PYTHON 環境変数でフルパスを指定できる。(HEASARC)
HEASoft 6.37 で大きく変わった model data
spectral model data が HEASoft 本体から分離された
HEASoft 6.37 では、XSPEC の一部の model が使用する spectral model data が HEASoft distribution に含まれなくなった。
その代わり、新しく
ftgetmodeldata
を使って必要な model data を取得する。
例えば APEC なら、
ftgetmodeldata modelname=apec modelversion=latest
である。
全 model の current release 用 data を取得したい場合は、
ftgetmodeldata modelname=all modelversion=latest
となる。
modelversion=all は obsolete version まで含める指定であり、HEASARC も通常の利用者には不要としている。したがって、特別な再現解析などがなければ latest でよいと思われる。(HEASARC)
最初に dry run した方がよい
全部取得する場合、いきなり download を始めるより、
ftgetmodeldata modelname=all modelversion=latest dryrun=yes
として、対象ファイルと総容量を確認した方がよい。
ある実行例では、
Will download total size: 19389199962 bytes
となった。
これは約 19.4 GB である。
さらに海外サイトから多数の FITS file を取得するため、回線によってはかなり時間がかかる。
例えば実効速度が
0.72 MB/s
程度の場合、19.4 GB の取得には単純計算で7時間以上かかる。
したがって、
ftgetmodeldata modelname=all modelversion=latest
は「少し待てば終わる download」というより、場合によっては夜間に走らせておく程度の処理と考えた方がよい。
HEASARC は ftgetmodeldata のほか、tarball や wget による manual download も案内している。(HEASARC)
download 速度を簡単に測る
ftgetmodeldata の実効速度を知りたい場合は、別 terminal から model data directory の増加速度を測ればよい。
例えば次の script を使える。
#!/usr/bin/env bash
dir="$HEADAS/../spectral/modelData"
prev_size=$(du -sb "$dir" | awk '{print $1}')
prev_time=$(date +%s)
while sleep 10; do
size=$(du -sb "$dir" | awk '{print $1}')
now=$(date +%s)
ds=$((size - prev_size))
dt=$((now - prev_time))
awk -v ds="$ds" -v dt="$dt" \
'BEGIN {
printf "%s %.2f MB/s (%.2f Mbps)\n",
strftime("%H:%M:%S"),
ds/dt/1e6,
ds/dt*8/1e6
}'
prev_size=$size
prev_time=$now
done
例えば、
17:48:07 0.72 MB/s (5.78 Mbps)
17:48:17 0.72 MB/s (5.78 Mbps)
17:48:27 0.73 MB/s (5.81 Mbps)
のように表示される。
ftgetmodeldata のために curl development library が必要
ここは少し注意が必要だった。
単に
which curl
で
/usr/bin/curl
が出ても十分ではない。
HEASoft 6.37 の ftgetmodeldata は curl library を使用し、build 時には curl/curl.h が必要になる。HEASARC も、開発用 curl が入っているかを確認する方法として
which curl-config
を案内している。(HEASARC)
例えば、
/usr/bin/curl
/usr/bin/curl-config
となっている状態が望ましい。
開発用 library がなければ、build 中に例えば、
fatal error: curl/curl.h: No such file or directory
で止まることがある。
Ubuntu 系では curl の development package を導入する。
利用している SSL backend や既存 package との関係があるので、共有計算機では実際に install する前に、
apt-get -s install <curl-development-package>
などで既存 package の削除や置換が発生しないことを確認した方が安全である。
Anaconda の curl-config を拾わせない
さらに注意したいのが Anaconda/Conda である。
例えば通常の shell が、
$HOME/anaconda3/bin
を PATH の前方に持っていると、
which curl-config
が、
$HOME/anaconda3/bin/curl-config
を指すことがある。
すると HEASoft configure が、
-L$HOME/anaconda3/lib -lcurl
のような linker option を生成する場合がある。
これによって、curl だけでなく Anaconda の
libstdc++.so
libtinfo.so
libncurses.so
libnghttp2.so
などまで system compiler から見えるようになり、ABI の混在につながる可能性がある。
そこで build 時だけ PATH を system command に限定した。
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
Python は PATH から探させず、絶対パスで指定する。
export PYTHON=/path/to/conda/environment/bin/python
これなら、
gcc -> /usr/bin/gcc
g++ -> /usr/bin/g++
gfortran -> /usr/bin/gfortran
curl-config -> /usr/bin/curl-config
Python -> 指定した Conda Python
と分離できる。
configure 前に build environment を掃除する
通常の login shell には、過去の HEASoft や CUDA、Conda などさまざまな設定が残っていることがある。
source build では、少なくとも一度 build 専用の clean environment を作った方がよかった。
例えば、
export CC=/usr/bin/gcc
export CXX=/usr/bin/g++
export FC=/usr/bin/gfortran
export PERL=/usr/bin/perl
export PYTHON=/path/to/conda/environment/bin/python
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
unset HEADAS
unset LD_LIBRARY_PATH
unset LIBRARY_PATH
unset CPATH
unset C_INCLUDE_PATH
unset CPLUS_INCLUDE_PATH
unset PKG_CONFIG_PATH
unset CMAKE_PREFIX_PATH
unset CFLAGS
unset CXXFLAGS
unset FFLAGS
unset FCFLAGS
unset CPPFLAGS
unset LDFLAGS
unset PYTHONPATH
unset PYTHONHOME
とした。
HEASARC の Linux install guide でも、別の Python environment を使用する場合は PYTHON に使用する executable を明示できる。(HEASARC)
configure
source tree の BUILD_DIR から、
cd /path/to/heasoft-6.37/BUILD_DIR
./configure > config.out 2>&1
を実行する。
終了後、
tail -30 config.out
などで、
Finished
まで到達していることを確認する。
PyXspec と Anaconda の library conflict
Python を指定するだけでは安全とは限らない
PyXspec は HEASoft 全体の build process に組み込まれており、PYTHON を指定すれば対象 Python に対して build される。HEASARC 公式にもこの方法が記載されている。(HEASARC)
しかし Anaconda の場合、
PYTHON_LIB="-L/path/to/anaconda/lib"
が生成されることがある。
これは libpython だけを指定しているように見えるが、実際には linker に
/path/to/anaconda/lib
という directory 全体を見せる。
そこに古い
libstdc++.so
libtinfo.so
libncurses.so
libnghttp2.so
などが存在すると、system GCC と組み合わせた際に問題になることがある。
実際に遭遇しやすい症状
例えば、
undefined reference to ...@GLIBCXX_3.4.32
や、
undefined reference to ...@NCURSES6_TINFO...
あるいは、
undefined reference to nghttp2_...
などが同時に現れる場合は、複数の独立した bug ではなく、library search path の混在を疑った方がよい。
確認には、
ls -l /path/to/anaconda/lib/libstdc++.so*
ls -l /path/to/anaconda/lib/libtinfo*
ls -l /path/to/anaconda/lib/libnghttp2*
などが使える。
さらに、
strings /path/to/anaconda/lib/libstdc++.so.6 | grep GLIBCXX
と system library を比較すると、ABI version の違いを確認できる。
libpython だけを隔離する
これは HEASARC 公式の標準手順そのものではなく、今回のように Anaconda の lib/ 全体が system build に干渉する環境で採用した回避策である。
通常の環境で問題なく build できている場合、この操作を行う必要はない。Anaconda と system libraries の衝突が確認できた場合の workaround として考える。
考え方は単純で、
Anaconda lib/
libpython3.x.so <- 必要
libstdc++.so <- build には見せたくない
libtinfo.so <- build には見せたくない
libnghttp2.so <- build には見せたくない
なので、libpython だけ別 directory にコピーする。
例えば、
mkdir -p "$HOME/local/heasoft-python-lib/python-3.10"
cp -p \
/path/to/anaconda/lib/libpython3.10.so.1.0 \
"$HOME/local/heasoft-python-lib/python-3.10/"
cd "$HOME/local/heasoft-python-lib/python-3.10"
ln -sfn libpython3.10.so.1.0 libpython3.10.so
として、
libpython3.10.so -> libpython3.10.so.1.0
libpython3.10.so.1.0
だけの directory を作る。
libpython 自身の依存関係は、
ldd libpython3.10.so.1.0
で確認しておく。
hmakerc の PYTHON_LIB を変更する
HEASARC の PyXspec documentation では、Python distribution を変更する場合に Xspec/BUILD_DIR/hmakerc の PYTHON_INC と PYTHON_LIB を編集できることが説明されている。(HEASARC)
例えば configure 後に、
PYTHON_INC="-I/path/to/anaconda/include/python3.10"
PYTHON_LIB="-L/path/to/anaconda/lib"
となっていた場合、
PYTHON_INC="-I/path/to/anaconda/include/python3.10"
PYTHON_LIB="-L$HOME/local/heasoft-python-lib/python-3.10"
とする。
今回の環境では heacore/BUILD_DIR/hmakerc にも同じ PYTHON_LIB が生成されたため、両方を同じ isolated directory に変更した。
重要なのは、
LHEAPYTHON -> Anaconda Python
PYTHON_INC -> Anaconda Python header
NUMPY_INC -> Anaconda NumPy
はそのまま残し、
PYTHON_LIB
だけを isolated directory に変更することである。
make
configure と同じ clean environment を保ったまま、
cd /path/to/heasoft-6.37/BUILD_DIR
make > build.log 2>&1
を実行する。
エラー時には、
grep -nEi \
'error:|undefined reference|collect2|make.*\*\*\*|gmake.*\*\*\*' \
build.log | tail -100
程度でもかなり原因を絞れる。
成功時には最後に、
Finished make all
が表示される。
make install
同様に clean environment のまま、
make install > install.log 2>&1
を実行する。
終了 code も確認する。
echo $?
が、
0
なら正常終了である。
install 後に library を確認する
XSPEC binary がどの C++ library を使用しているか確認しておくと安心である。
ldd "$HEADAS/bin/xspec" | grep -E 'stdc\+\+|python|tinfo|ncurses|nghttp2|curl'
例えば、
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6
のように system library を参照していれば、Anaconda の古い libstdc++ を誤って使用していないことを確認できる。
RPATH / RUNPATH も、
readelf -d "$HEADAS/bin/xspec" | grep -E 'RPATH|RUNPATH'
で確認できる。
HEASoft の version を切り替える
複数 version を共存させる場合、単に別 version の headas-init.sh を source するだけではなく、先に HEADAS を変更する。
例えば、
export HEADAS=/path/to/heasoft-6.37/platform-directory
source "$HEADAS/headas-init.sh"
hash -r
とする。
hash -r は bash が記憶している command path の cache を消すためのものである。
例えば .bashrc に、
heasoft636 () {
unset LD_PRELOAD
export HEADAS=/path/to/heasoft-6.36/platform-directory
source "$HEADAS/headas-init.sh"
hash -r
ftversion
}
heasoft637 () {
unset LD_PRELOAD
export HEADAS=/path/to/heasoft-6.37/platform-directory
source "$HEADAS/headas-init.sh"
hash -r
ftversion
}
としておくと切り替えやすい。
PyXspec の import が runtime で失敗する場合
build と install が成功しても、
python -c 'import xspec'
で失敗する場合がある。
今回遭遇したのは、
ImportError:
libcurl-gnutls.so.4:
undefined symbol:
nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation
という error だった。
調べると Python executable 自体に、
RPATH = $ORIGIN/../lib
が設定されており、Anaconda の古い libnghttp2.so が system のものより先にロードされていた。
確認には、
readelf -d /path/to/anaconda/bin/python \
| grep -E 'RPATH|RUNPATH'
が使える。
さらに必要な symbol がどちらに存在するか、
strings /path/to/anaconda/lib/libnghttp2.so.14 \
| grep <symbol-name>
strings /usr/lib/x86_64-linux-gnu/libnghttp2.so.14 \
| grep <symbol-name>
で比較できる。
LD_PRELOAD で診断する
system の libnghttp2 を一時的に先読みさせ、
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libnghttp2.so.14 \
python -c 'import xspec; print(xspec.Xset.version)'
として正常に import できれば、runtime library の衝突だったと判断できる。
LD_PRELOAD を .bashrc で常時 export するのは避けた方がよい。ほかの Conda program まで system library を強制的に preload するためである。
必要な shell だけ、
pyxspec37_init () {
export HEADAS=/path/to/heasoft-6.37/platform-directory
source "$HEADAS/headas-init.sh"
export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libnghttp2.so.14
hash -r
ftversion
}
として使う方が影響範囲を限定できる。
なお、この libnghttp2 問題は Anaconda の version や package 構成に依存するため、すべての PyXspec 環境で必要になる処置ではない。
PyXspec の最終確認
HEASoft environment を読み込んだあと、
/path/to/conda/python -c \
'import xspec; print(xspec.Xset.version)'
を実行する。
正常なら PyXspec と XSPEC の version が表示される。
PyXspec は通常の XSPEC command interpreter の Python 版ではなく、Python から
import xspec
して使用する interface である。HEASARC の quick tutorial でもこの利用方法が説明されている。(HEASARC)
APEC が動かなければ model data を疑う
HEASoft 自体が正常に動いていても、
XSPEC> model apec
で、
Cannot find any APEC files corresponding to ...
となる場合がある。
これは HEASoft 6.37 では model data が別 download になったことと関係している可能性が高い。
まず、
ftgetmodeldata modelname=apec modelversion=latest
を実行する。
全 model を用意するなら、
ftgetmodeldata modelname=all modelversion=latest
である。(HEASARC)
通常の source installation では model data の default directory は、
$HEADAS/../spectral/modelData
である。(HEASARC)
古い Xspec.init にも注意する
$HOME/.xspec/Xspec.init は HEASoft を更新しても毎回自動置換されるわけではない。
そのため、過去の version の設定が残っている場合がある。(HEASARC)
現在の HEASARC documentation では、
ATOMDB_VERSION: latest
SPEX_VERSION: latest
NEI_VERSION: latest
を使用する設定が案内されている。(HEASARC)
あるいは、下記の記事でも解説されてます。
確認は、
grep -E \
'ATOMDB_VERSION|SPEX_VERSION|NEI_VERSION' \
"$HOME/.xspec/Xspec.init"
でよい。
インストール前チェックリスト
HEASoft 6.37 を source build して PyXspec まで使う場合、まず次を確認したい。
[ ] system gcc / g++ / gfortran を使っている
[ ] system curl-config が存在する
[ ] Anaconda curl-config を拾っていない
[ ] PYTHON は使用したい Python の絶対パスで指定した
[ ] LD_LIBRARY_PATH に古い HEASoft が残っていない
[ ] configure 後の PYTHON_LIB を確認した
[ ] Anaconda/lib 全体が linker に入っていないか確認した
[ ] make 後に xspec の ldd を確認した
[ ] make install 後に ftversion を確認した
[ ] import xspec を確認した
[ ] spectral model data を別途取得した
[ ] Xspec.init の古い version 指定を確認した
まとめ
HEASoft 6.37 の install で最も重要だったのは、「compile command を知っていること」よりも、 どの software stack がどの library を使っているのかを分離して考えること だった。
特に、
system compiler
system curl
Conda Python
XSPEC
spectral model data
を一つの巨大な環境として扱わず、それぞれの役割を分けて考えると troubleshooting がかなり楽になる。
また HEASoft 6.37 では spectral model data が本体から分離されたため、
./configure
make
make install
がすべて成功しても、それだけで APEC などすべての model が使用可能になるわけではない。これはインストールを始める前に知っておいた方がよい変更点だと思う。(HEASARC)
Anaconda/Conda との衝突については環境依存性が高いため、
Anaconda は HEASoft と相性が悪い
と一般化するのではなく、
Anaconda の
lib/が system linker/runtime に混ざった場合には、ABI の不整合が起こり得る
ということなんでしょう。
参考資料
- HEASARC: Installing HEASoft on Linux
- HEASARC: Spectral Model Data Files
- HEASARC: ftgetmodeldata
- HEASARC: Build and Install PyXspec
- HEASARC: PyXspec Quick Tutorial