拾い物のアプリケーションをコンパイルしようとして依存関係を解決できない時のメモ。
1. 依存しているライブラリを列挙する
- ドキュメントにある場合はそれを見る
- include宣言だけ見ておけば良いのではないかと思ったので、拾ってきたファイルの一番上の階層で
grep -r "#include <" | cat > dependencies.txt
する。- 大きいライブラリならxargsを使う
- できたファイルから重複を除く
#python include_libs = [] with open( "./dependencies.txt", "r" ) as f: for line in f: lib = line.split(' ')[1].rstrip('\n')[1:-1] include_libs.append(lib) include_libs = list(set(include_libs)) include_libs.sort() with open("./dependencies2.txt", "w") as f: for i in include_libs: f.write(i + "\n")
- 上の手順は多分コマンド一発でできるはずだが...
- 標準ライブラリ以外はインストールが必要なライブラリ由来のヘッダファイル
2. 必要なパッケージのインストール
apt-file search hoge.h
して必要なものを探す。hoge-devみたいなものが使えることが多い- arch linuxなら
yay -Fs hoge.h
として探せる(Pacman比較表) - ある場合: aptを使ってレポジトリからインストールする
- ない場合: ソースコードからインストールする。インストールする依存ライブラリの依存関係を調べるため1に戻る
- arch linuxなら
- 参考サイト
3. コンパイル
パスの指定
- ヘッダは普通
/usr/include
か/usr/local/include
にある →-I
オプションに渡す - ライブラリは普通
/usr/lib
か/usr/local/lib
にある →-L
オプションに渡す - .soファイルは
apt-file list LIBRARY_NAME
を実行して探す。それでダメなら諦めて元のレポジトリのMakefileを読む(.hと.a、.soは同名とは限らない)
- ヘッダは普通
参考
- 静的ライブラリはlibxxxx.a
- 動的ライブラリはlibxxxx.so
- API design for C++によれば、動的ライブラリは依存関係の依存関係も含めて配布する必要がある
- /usr/libの.soファイルにlddコマンドを使えばたくさん見つかる
- 実際にはOSが管理してくれる便利な方法がある(参考サイト1、参考サイト2(1を眺めてから読むと分かりやすい)、参考サイト3)
- linuxではld.soリンカ、ローダというものが/lib、/usr/libを検索する
- ldconfigを使って登録する方法(
-n
でカレントディレクトリを登録)- ubuntuでは/etc/ld.so.conf.d/libc.confに/usr/local/libを登録してあるが、ディストリビューションによっては/usr/local/libは検索されないので先にld.so.confを編集する
- 環境変数LD_LIBRARY_PATHを用いて、
export LD_LIBRARY_PATH=/home/..
とする方法(デバッグ向け) -rpath
(実行時に検索するディレクトリを指定)、-rpath-link
(ビルド時に検索するディレクトリを指定)を用いる方法
- ldconfigを使って登録する方法(
- linuxではld.soリンカ、ローダというものが/lib、/usr/libを検索する
- API design for C++によれば、動的ライブラリは依存関係の依存関係も含めて配布する必要がある
libhoge.hpp
なら-lhoge
とする
pkg-config、.acファイルがあるならpkg-configメモ - tak0kadaの何でもノートを利用することもできる
- libtoolを使えば簡単になりそう
# 静的ライブラリのコンパイル g++ -c hoge.cpp ar -crs libhoge.a hoge.o # 動的ライブラリのコンパイル(.oファイルを残す) g++ -c -fPIC hoge.cpp g++ -shared -o libhoge.so -fPIC hoge.o # .oファイルを残さない g++ -shared -fPIC -o libhoge.so hoge.cpp # 複数ファイルのコンパイル(main -> foo -> bar) g++ -Wl,-no-as-needed -L. -lfoo -lbar main.cpp g++ -L. main.cpp -lfoo -lbar # 依存関係を考慮してコンパイル(mainのコンパイルの時にfooしかリンクしなくていい) # -Wl,optionでオプションをリンカに渡す g++ -shared -fPIC -o libbar.so bar.cpp g++ -shared -fPIC -Wl,-no-as-needed -L. -lbar -o libfoo.so foo.cpp g++ -Wl,-no-as-needed -Wl,-rpath,$PWD -Wl,-rpath-link,$PWD -L. -lfoo main.cpp # 動的ライブラリのバージョンも管理したい場合 # sonameが実際のリンクに使われる g++ -shared -fPIC -Wl,-soname=libbar.so bar.cpp -o libbar.so.1.0
- 上のコマンド例はコンパイル時に依存ファイルを参照する様子を表している。-rpath-link以外は実行時のためにldconfigなどを実行しておく必要がある。
- 参考サイト
- これ以上ややこしくなったら間違いを防ぐために項目4に進む
4. ビルドの自動化
- TODO
4.1 make
hoge: hoge.o g++
- makeに関しては、Amazon CAPTCHA)を借りてきた
4.2 cmake
- その他automake、autoconfというものがあるらしい
- ビルドを自動化するツールは山ほどあるらしい