自作ライブラリのconfigure導入から自作configure利用時に気付いたことや、過去の経験分の情報が溜まってきたので記載。何か出てきたら再度更新します。
確認は全てUbuntu18.04 (libtool 2.4.6)での確認です。
特にlibtoolが絡むライブラリ周りはversionで挙動が違う可能性がある為ご注意ください。
##共通
###インストールパスを変えたい
例えばOSSのインストールパスを変えて、複数のバージョンを管理したい or ローカルに一旦保存したい等に便利です。
基本configureのprefixが対応しています。(ものによってはinstall path用のオプションがあったりするので、その際は./configure --helpを確認ください。)
./configure prefix=`pwd`/../tmp
(フルパスでないと怒られるようです)
###オプションを確認したい
./configure --help
###CFLAG等のデフォルトオプションを変えたい
configureのオプションで指定できます。
./configure CFLAGS="-g -O0"
gdb/valgrind等を利用する為に"-g -O0"オプションを使いたい時などに便利
###作成したプログラムでvalgrind, gdbが実行できない
プログラムがconfigureパッケージ内で作成したライブラリをリンクしている場合、実体は.libs/内に存在することがあります。
実体を利用する際はLD_LIBRARY_PATHで利用しているライブラリのパスを通すことも忘れずに。こちらもビルドしたライブラリフォルダの.libs内にあります。
その際の直下にあるプログラムと同名のファイルは、唯のライブラリパスを通す為のスクリプトだったりします。
##自作パッケージ
###configureパッケージの導入方法について
こちらにまとめてあります。
###自作パッケージのインストール指定方法
基本: パス名_オプション
オプションについて:ビルドするプログラムの場合 PROGRAMS
sbin_PROGRAMS=lighttpd lighttpd-angel
オプションについて:ヘッダーの場合 HEADERS
include_HEADERS = event_threadpool_data.h event_threadpool.h
オプションについて:スクリプトの場合(このケースはsbinにインストール)
sbin_SCRIPTS=CommandClient.py CommandServer.py CommandService.py
インストールしない場合:パス名にno_instを指定
noinst_PROGRAMS = test
###configureパッケージ内で作成したライブラリをリンクしたい
実行プログラムへのリンク LDADDで.laファイルを指定します。
test_LDADD = $(LDPATH)/libpublisher.la
もしくは共通設定ファイルのam.confを作成し、AM_LDFLAGSに指定すればリンクできます。
AM_LDFLAGS+=$(top_srcdir)/flyweight/lib/libflyweight.la
include $(top_srcdir)/flyweight/flyweight_am.conf
作成ライブラリ内でライブラリリンク
ライブラリのMakefile.am内、ライブラリ_LDFLAGSで.laファイルを指定すればOKです。
libflyweight_la_LDFLAGS=-rpath $(libdir) $(top_srcdir)/design_pattern_util/lib/libdputil.la
注意:
- installを伴う利用方法の場合は、-sharedオプションを付けて共有ライブラリにする。じゃないとインストールに失敗します。
-
ライブラリの共有ライブラリリンク、
-Xlinker -rpath -Xlinker $(libdir)
でパスを通してあげないとinstall後にパスが解決しません。逆にXlinker を付ければ片方のライブラリだけリンクすればOK。謎過ぎるlibtool。 - ライブラリ内でのライブラリリンクコンパイル自体はAM_LDFLAGSでも可能ですが、どうもAM_LDFLAGSを利用すると共有ライブラリに静的ライブラリの関数が取り込まれないようです。そのため、実行プログラムは共有ライブラリと静的ライブラリの両方をリンクする必要が出てきてしまいます。
2に興味がある方は同パッケージ内でのライブラリのライブラリリンクに比較結果を記載しています。理由は未確認。
3に興味がある方は補足のconfigureパッケージ内で作成したライブラリをリンクについてに比較結果を記載しています。理由は未確認。
###共有、静的それぞれのライブラリ作成方法が知りたい
共有ライブラリの場合 ライブラリのMakefile.amに-shared
オプションを指定すればOK。
libflyweight_la_LDFLAGS=-shared -rpath $(libdir) $(top_srcdir)/design_pattern_util/lib/libdputil.la
静的ライブラリの場合 ライブラリのMakefile.amに-static
オプションを指定すればOKです。
libflyweight_la_LDFLAGS=-static -rpath $(libdir) $(top_srcdir)/design_pattern_util/lib/libdputil.la
また、XXX_la_LDFLAGSを指定しないと静的ライブラリ、XXX_la_LDFLAGSを指定して-static, -sharedをつけないと両方という不思議な仕様になっている模様。
###configure.acで使えるオプションが知りたい
こちらにわかる範囲で纏めました。
###自作configureパッケージのバージョン違い問題
正直configureのバージョン違いに対する問題は未だによくわかりません。ただ解決出来たケースだけを記載しておきます。
2018/05/20 補足
下記に出したような高→低のエラーconfigure.acのオプションについては、上位バージョンの下位互換がある程度効くようなので下位バージョンに合わせた方が安定しそうです。
例えばOpenSSLのような一般的なOSSのconfigure.acオプションを参考にすると、どちらのオプションを利用するかの判断基準になると思います。
2018/05/30 補足
pkg-configをインストールして解決することもあるようです。pkg-configとはその環境で利用されるヘッダーパス等の情報を取得するためのコマンドで、このコマンドを利用している場合があるためです。(完全自作の場合はないと思いますが)
####低→高に移動する場合
libtool、ltmain.shの実体を置いておけば動作する認識でしたが、高バージョンのlibtool環境で利用するとmakeで失敗するケースがありました。(Ubuntu 14.04で作成→Ubuntu18.04でのビルドに失敗)
この時は、libtool、ltmain.shを消して、autoreconfを実行すると解決しました。
rm libtool ltmain.sh
autoreconf
./configure
...
####高→低に移動する場合
以前の記事にも書いた、古い環境で環境編集→autoreconfを実行すると、以降一切buildもautoreconfも出来なくなりました。
(試したのはUbuntu18.04→Cent OS 5.1)
初期状態でのビルドは普通に通るんですが、例えばMakefile.amを編集するとこんな感じのエラーが出てしまい、何もできなくなります。
XXX/missing: line 81: automake-1.15: command not found
WARNING: 'automake-1.15' is missing on your system.
You should only need it if you modified 'Makefile.am' or
'configure.ac' or m4 files included by 'configure.ac'.
The 'automake' program is part of the GNU Automake package:
<http://www.gnu.org/software/automake>
It also requires GNU Autoconf, GNU m4 and Perl in order to run:
<http://www.gnu.org/software/autoconf>
<http://www.gnu.org/software/m4/>
<http://www.perl.org/>
make: *** [Makefile.in] Error 127
こちらも面倒ですが一応対処出来ました。やったことは
- XXX/missingを消す
- configure.acの
AC_PREREQ([2.XX])
のバージョンを環境のものに変更。自分は2.69=>2.59へ - autoreconf --installを実行。エラーをつぶす
- エラーがつぶれたら./configure->makeでビルド
エラーはこんなのがありました。
$autoreconf
aclocal:configure.ac:10: warning: macro `AM_PROG_AR' not found in library
configure.ac:10: error: possibly undefined macro: AM_PROG_AR
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
autoreconf: /usr/bin/autoconf failed with exit status: 1
AM_PROG_AR
が使えないのでコメントアウト
ChainOfResponsibility/lib/Makefile.am:4: Libtool library used but `LIBTOOL' is undefined
...
publisher/lib/Makefile.am:4: The usual way to define `LIBTOOL' is to add `AC_PROG_LIBTOOL'
publisher/lib/Makefile.am:4: to `configure.ac' and run `aclocal' and `autoconf' again.
autoreconf: automake failed with exit status: 1
LIBTOOL
のオプションがバージョンで違うらしいです。ログに倣いAC_PROG_LIBTOOL
を使います。
./configure: line 18615: LT_INIT: command not found
逆に元の環境で利用していたLIBTOOL
のオプションがLT_INIT
が利用できないのでコメントアウト。
これでビルド出来るようになりました。
CentOS 5.1なんて使う機会ないので、回避策だけここに残して放置させていただきます。
補足
ライブラリビルド時に出来る.laファイルについて
ファイルを開くとわかりますが、ライブラリのファイル名やリンクするライブラリ、インストールする場合のパス等が入っています。
これらの情報を元に、libtoolがライブラリリンクを張っているようです。
なのでリンクの必要な実体は.libs配下となっています。
configureパッケージ内で作成したライブラリをリンクについて
共有ライブラリに対してライブラリをAM_LDFLAGS指定でリンクした場合、.aでも未解決シンボルとして扱うようです。
以下はdputil_xxxという関数を持つ動的ライブラリをAM_LDFLAGS, ライブラリ_LDFLAGSそれぞれで取り込んだ場合のnmコマンドの比較です。
Uは未解決シンボル(別途リンクが必要な関数)、tはローカルシンボル(ライブラリ内部で取り込めた関数)となります。
$nm .libs/libpublisher.so.0.0.0
0000000000202088 b __bss_start
U calloc@@GLIBC_2.2.5
...
U dputil_list_pop
U dputil_list_pull
U dputil_list_push
U dputil_lock
U dputil_unlock
$nm .libs/libpublisher.so.0.0.0
0000000000202088 b __bss_start
U calloc@@GLIBC_2.2.5
...
...
0000000000000f90 t dputil_list_pop
0000000000000f50 t dputil_list_pull
0000000000000f20 t dputil_list_push
0000000000000ee0 t dputil_lock
0000000000000f00 t dputil_unlock
同パッケージ内でのライブラリのライブラリリンク
上記で記載したように、AM_LDFLAGSの静的リンクはうまくいきませんでした。
では動的リンクは?パッケージ内で動作させる分は.laが頑張ってくれるようですが、installするとそうはいかない模様。
libchainofresp.soがlibflyweight.soをリンクするようにしていたのですが、何故かlibflyweight.soだけどこのパスも通らない。LD_LIBRARY_PATHを通せば行けるけど、何故だ。
$ ./test
./test: error while loading shared libraries: libflyweight.so.0: cannot open shared object file: No such file or directory
$ldd test
linux-vdso.so.1 (0x00007ffd5cbdf000)
libchainofresp.so.0 => /usr/local/lib/libchainofresp.so.0 (0x00007f4a3327d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4a32e8c000)
libflyweight.so.0 => not found
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f4a32c6d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4a33683000)
$ ldd /usr/local/lib/libchainofresp.so.0.0.0
linux-vdso.so.1 (0x00007ffe041ca000)
libflyweight.so.0 => not found
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff563de7000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff5639f6000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff564209000)
libchainofrespのMakefile.amに以下のように-Xlinker -rpath -Xlinker $(libdir)
を追加してみます。
...
libchainofresp_la_LDFLAGS=-shared $(top_srcdir)/design_pattern_util/lib/libdputil.la $(top_srcdir)/flyweight/lib/libflyweight.la -Xlinker -rpath -Xlinker $(libdir)
するとlibchainofresp.soがlibflyweight.soをリンクするようになります。
本当にlibtoolは謎。でもこれでlibchainofresp.soだけリンクすればlibflyweight.soもついてくる!
$ldd libchainofresp.so.0.0.0
linux-vdso.so.1 (0x00007ffca6dfe000)
libflyweight.so.0 => /usr/local/lib/libflyweight.so.0 (0x00007f5cad328000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f5cad109000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5cacd18000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5cad72e000)