概要
- libc++を動かすにはlibc++abiが必要。
- CentOS7向けのlibc++abiパッケージは出回っていない
- libc++abiのgcc互換実装としてlibsupc++が存在する。
- clangのコンパイルオプションに
stdlib=libc++ -lc++ -lsupc++
をつければ動く
モチベーション
昨日書いた記事ある環境でstd::chronoが遅いで、CentOS7+devtoolsetの環境でstd::chrono
が遅いというのを取り扱った。原因は何となくlibstdc++
の問題(というより配布されているdevtoolsetのビルドの問題)ということが分かった。その時のコメントでlibc++
ならどうかというものがあって試したいが、どうやらCentOS7ではclang + libc++を動かすのはかなり大変な様子。
試行錯誤したら動いたのでレポート。
手順
前提として、CentOS7にdevtoolset-9がインストール済みであるとする。
ここから、は以下の手順でclang, llvm, libc++(libcxx)をインスコ。末尾の--disableplugin=show-leaves
は私の環境ではrpmがぶっ壊れているのか必須1。
rpm -i https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install clang llvm-devel libcxx libcxx-devel --disableplugin=show-leaves
ここでclangでコンパイルを試みてもリンクエラーになる。
clang -O2 -std=c++17 -stdlib=libc++ test_timer_stdonly.cpp
/opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/../../../../bin/ld: /tmp/test_timer_stdonly-d0d52b.o: in function `main':
test_timer_stdonly.cpp:(.text+0x11): undefined reference to `std::__1::chrono::steady_clock::now()'
/opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/../../../../bin/ld: test_timer_stdonly.cpp:(.text+0x19): undefined reference to `std::__1::chrono::steady_clock::now()'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
webではいろいろな情報が出回っているが、libc++を動かすにはlibc++abiが必要ということ。しかし、コンパイルオプションに-lc++abi
を入れるなどの処方箋は殆どがUbuntu環境のもの。CentOS7にはそもそもlibc++abiがパッケージとして出回っていない。
しかし、本の虫2によればlibc++abiのgcc実装としてlibsupc++が存在するそうだ。これはdevtoolset-9に入っている。試行錯誤の結果、次のようにコンパイル時に-lc++ -lsupc++
の二つをつければ動いた。
clang -O2 -std=c++17 -stdlib=libc++ -lc++ -lsupc++ test_timer_stdonly.cpp
Intel icpxとlibc++の併用
OneAPIとなった最近のIntel コンパイラの場合は、gccだけでなくclang相当の実装もある。
- icpc : g++ 相当
- icpx : clang++相当
なので、icpxでもlibc++が動かせる。その場合には-lc++ -lsupc++
ではごまかせないが、シンボリックリンクでごまかせる。
# 管理者権限で
cd /opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/;
ln -s libsupc++.a libc++abi.a
# 以下は一般ユーザで
icpx -O2 -std=c++17 -stdlib=libc++ test_timer_stdonly.cpp
さいごに
それで結局CentOS7環境でのlibc++のstd::chronoは速いのか遅いのかというと、、、こちら