Ubuntuをはじめとして、まぁGCCはどのLinuxディストリビューションに入っているんだけど、クラスター計算機等のユーザー/ファイルの共有環境では、サーバーとクライアントでビルド環境をそろえたいだろう ということで、特定のバージョンのGCCを/opt_share
下に準備する(このフォルダがNFSで共有されている)ための方法をまとめた。
NFSでマウントした/opt_share
下の内容は全ユーザーから見えるように設置したいので、基本的にはsudo
コマンドですべての作業は行った。
参考にしたページ: GNU GCCのビルド(ソースから) #Linux - Qiita
準備
ファイルをミラーサーバーからダウンロードする。
GCC mirror sites - GNU Project
今回はUbuntu 22.04で使われているのと同じGCC 11.4を使う。
wget https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-11.4.0/gcc-11.4.0.tar.gz
でダウンロード(Proxy必要な場合は-e HTTP_PROXY=proxy-hoge.co.jp:8080
を忘れずに)。
sudo tar -zxvf gcc-11.4.0.tar.gz
で展開。
ビルド
GCC 11.4のビルド
GCC 11.4では${GCC_ROOT}
で./configure & make & make install
ではビルドできず./contrib/download_prerequisites
の実行が必要。
この作業の中でwget
でのダウンロードが入っているので、proxy等が必要な場合は考慮に入れる必要がある。一般ユーザーは.bashrc
等ですでにproxy通していることもあるけれど、sudo
の方にそれを設定していないことがあるので、以下のようなコマンドで環境変数http_proxy
とhttps_proxy
にproxyサーバーを設定する(port番号は8080だとした):
sudo http_proxy=http://proxy-hoge.co.jp:8080 https_proxy=https://proxy-hoge.co.jp:8080 ./contrib/download_prerequisites
sudo mkdir build
でcd build
に移動したのち(こうやってビルドするのが推奨されていることを最近知った)に
sudo ../configure --enable-languages=c,c++,fortran --prefix=/opt_share/compiler/gcc/11.4.0 --disable-bootstrap --disable-multilib
--disable-bootstrap
と--disable-multilib
のオプションにについてはよくわかってないけれど、参考にしたページにあったので適当につけておいた。fortran
は必須(みんな大好きFortran)。
sudo make -j8
sudo make check #ここでエラーで止まる場合は`apt install autogen`が必要かも
sudo make install
でインストール完了。
make checkでFAILあったけど気にしないことにする
============================================================================
Testsuite summary for package-unused version-unused
============================================================================
# TOTAL: 36
# PASS: 34
# SKIP: 0
# XFAIL: 0
# FAIL: 2
# XPASS: 0
# ERROR: 0
package-unused version-unused: ./test-suite.log
=====================================================
# TOTAL: 36
# PASS: 34
# SKIP: 0
# XFAIL: 0
# FAIL: 2
# XPASS: 0
# ERROR: 0
.. contents:: :depth: 2
FAIL: b2test_buildid
====================
test1: [0]: missing file name or function name
test2: [0]: missing file name or function name
test3: [0]: missing file name or function name
test4: [0]: missing file name or function name
FAIL: backtrace_full noinline
FAIL: backtrace_full inline
FAIL: backtrace_simple noinline
FAIL: backtrace_simple inline
PASS: backtrace_syminfo variable
FAIL b2test_buildid (exit status: 1)
FAIL: b3test_dwz_buildid
========================
test1: [0]: missing file name or function name
test2: [0]: missing file name or function name
test3: [0]: missing file name or function name
test4: [0]: missing file name or function name
FAIL: backtrace_full noinline
FAIL: backtrace_full inline
FAIL: backtrace_simple noinline
FAIL: backtrace_simple inline
PASS: backtrace_syminfo variable
FAIL b2test_buildid (exit status: 1)
FAIL: b3test_dwz_buildid
========================
test1: [0]: missing file name or function name
test2: [0]: missing file name or function name
test3: [0]: missing file name or function name
test4: [0]: missing file name or function name
FAIL: backtrace_full noinline
FAIL: backtrace_full inline
FAIL: backtrace_simple noinline
FAIL: backtrace_simple inline
PASS: backtrace_syminfo variable
FAIL b3test_dwz_buildid (exit status: 1)
事後の設定とか
Environmental moduleの記述
当然Environmental moduleで利用するコンパイラ等は管理したい。
#%Module -*- tcl -*-
##
## gcc modulefile
##
proc ModulesHelp { } {
puts stderr "\tAdds GCC-11.4.0 replacing the OS GCC. \n"
}
module-whatis "adds GCC-11.4.0 replacing the OS GCC."
set version "11.4.0"
set root /opt_share/compiler/gcc/11.4.0
conflict compiler/gcc-11.4.0
conflict compiler/gcc/9.4.0
prepend-path PATH $root/bin
prepend-path PATH $root/sbin
prepend-path MANPATH $root/share/man
prepend-path LD_LAIBRARY_PATH $root/lib
setenv COMPNAME gcc
setenv COMPVER $version
上記くらい書いておけば、ライブラリ用のPATHとかもきちんと通っているはず。
一応OSデフォルトで入っているGCC 11.4、それと別で入れたGCC 9.4と排他的になるように、conflict compiler/gcc-11.4.0
, conflict compiler/gcc/9.4.0
のの文を入れている。
OpenMPIも入れよう
sudoは普通Environmental moduleの設定を読み込んでいないのと、実行するたびに環境がリセットされるので、その点で結構面倒。
この問題点を解決するために「Environmental moduleのセットアップ」「GCC 11.4のmodule読み込み」「configure」を一回のsudoで行うために、これらを単一の命令としてbashの引数に渡すことにする。
一気に実行してうまくいく気がしないので、まずは「Environmental moduleのセットアップ」「GCC 11.4のmodule読み込み」のテスト
sudo bash -c "source /etc/profile.d/modules.sh; module load compiler/gcc/11.4.0; module list; gcc -v"
の実行で、確かに所望のGCC 11.4の環境が準備されていることがわかる。以下が出力:
Currently Loaded Modulefiles:
1) compiler/gcc/11.4.0
組み込み spec を使用しています。
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/opt_share/compiler/gcc/11.4.0/libexec/gcc/x86_64-pc-linux-gnu/11.4.0/lto-wrapper
ターゲット: x86_64-pc-linux-gnu
configure 設定: ../configure --enable-languages=c,c++,fortran --prefix=/opt_share/compiler/gcc/11.4.0 --disable-bootstrap --disable-multilib
スレッドモデル: posix
サポートされている LTO 圧縮アルゴリズム: zlib
gcc バージョン 11.4.0 (GCC)
というわけで、晴れてconfigure
までもっていく。
適当なOpenMPIのtarballをとってきて、展開。そのルートフォルダにbuildフォルダを作って、そこに入って以下のコマンドでconfigure
sudo bash -c "source /etc/profile.d/modules.sh; module load compiler/gcc/11.4.0; ../configure --prefix=/opt_share/openmpi/5.0.3/gcc-11.4.0 --with-tm=/opt/openpbs/23.06.06"
Open MPI configuration:
-----------------------
Version: 5.0.3
MPI Standard Version: 3.1
Build MPI C bindings: yes
Build MPI Fortran bindings: mpif.h, use mpi, use mpi_f08
Build MPI Java bindings (experimental): no
Build Open SHMEM support: false (no spml)
Debug build: no
Platform file: (none)
Miscellaneous
-----------------------
Atomics: GCC built-in style atomics
Fault Tolerance support: mpi
HTML docs and man pages: installing packaged docs
hwloc: external
libevent: external
Open UCC: no
pmix: internal
PRRTE: internal
Threading Package: pthreads
Transports
-----------------------
Cisco usNIC: no
Cray uGNI (Gemini/Aries): no
Intel Omnipath (PSM2): no (not found)
Open UCX: no
OpenFabrics OFI Libfabric: no (not found)
Portals4: no (not found)
Shared memory/copy in+copy out: yes
Shared memory/Linux CMA: yes
Shared memory/Linux KNEM: no
Shared memory/XPMEM: no
TCP: yes
Accelerators
-----------------------
CUDA support: no
ROCm support: no
OMPIO File Systems
-----------------------
DDN Infinite Memory Engine: no
Generic Unix FS: yes
IBM Spectrum Scale/GPFS: no (not found)
Lustre: no (not found)
PVFS2/OrangeFS: no
まぁ大丈夫じゃない?
make
するときにはやっぱりコンパイラ等環境の情報使うので上の技を再度使う:
sudo bash -c "source /etc/profile.d/modules.sh; module load compiler/gcc/11.4.0; sudo make -j8
"
以下は毎回sudo使えばよいだけ:
sudo make check
sudo make install
で終了。
確認のため
module load compiler/gcc/11.4.0
/opt_share/openmpi/5.0.3/gcc-11.4.0/bin/mpif90 -v
を実行すると
組み込み spec を使用しています。
COLLECT_GCC=/opt_share/compiler/gcc/11.4.0/bin/gfortran
COLLECT_LTO_WRAPPER=/opt_share/compiler/gcc/11.4.0/libexec/gcc/x86_64-pc-linux-gnu/11.4.0/lto-wrapper
ターゲット: x86_64-pc-linux-gnu
configure 設定: ../configure --enable-languages=c,c++,fortran --prefix=/opt_share/compiler/gcc/11.4.0 --disable-bootstrap --disable-multilib
スレッドモデル: posix
サポートされている LTO 圧縮アルゴリズム: zlib
gcc バージョン 11.4.0 (GCC)
と確かに11.4.0がリンクされているのが確認できる。
この環境を読み込むためのenvironmental module設定ファイルは以下の通り:
#%Module -*- tcl -*-
##
## dot modulefile
##
proc ModulesHelp { } {
global moduleversion
puts stderr "\tAdds openmpi to your environment variables,"
}
module-whatis "adds openmpi to your environment variables"
set moduleversion 5.0.3
set root /opt_share/openmpi/5.0.3/gcc-11.4.0
conflict openmpi/5.0.3/gcc-9.4.0
module load compiler/gcc/11.4.0
prepend-path PATH $root/bin
prepend-path MANPATH $root/share/man
setenv MPI_HOME $root
setenv MPI_RUN $root/bin/mpirun
prepend-path LD_RUN_PATH $root/lib
prepend-path LD_LIBRARY_PATH $root/lib
prepend-path LIBRARY_PATH $root/lib
conflict openmpi/5.0.3/gcc-9.4.0
で類似のGCC 9.4.0用に作ったopenmpiと排他的に呼ばれるように指定している。
トラブルシューティング: モジュールで指定されたコンパイラがリンクされていない
確認した範囲ではmoduleでGCC 11.4をロードしていないと、/opt_share/openmpi/5.0.3/gcc-11.4.0/bin/mpif90 -v
を実行すると
Using built-in specs.
COLLECT_GCC=/usr/bin/gfortran
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2)
が得られてOSデフォルトのGCC 9.4.0が呼び出されているのがわかる。つまり、このビルド方法だとコンパイラのリンクはstaticなものではなくてdynamicなものになっていて、環境に応じて変わっている部分があることを示している。
なので、必ずmodule load compiler/gcc/11.4.0
を事前に呼び出す必要がある。
sudo使わない場合。
module load compiler/gcc/11.4.0
../configure --prefix=/opt_share/openmpi/5.0.3/gcc-11.4.0 --with-tm=/opt/openpbs/23.06.06
で通るはず。