configure利用TIPS

[自作ライブラリのconfigure導入](https://qiita.com/developer-kikikaikai/items/433d69c4bcbf52b249a1)から自作configure利用時に気付いたことや、過去の経験分の情報が溜まってきたので記載。何か出てきたら再度更新します。

確認は全てUbuntu18.04 (libtool 2.4.6)での確認です。
特に**libtoolが絡むライブラリ周りはversionで挙動が違う可能性がある**為ご注意ください。

##**共通**

###**インストールパスを変えたい**

例えばOSSのインストールパスを変えて、複数のバージョンを管理したい or ローカルに一旦保存したい等に便利です。
基本configureのprefixが対応しています。(ものによってはinstall path用のオプションがあったりするので、その際は./configure --helpを確認ください。)

```command
./configure prefix=`pwd`/../tmp
```

(フルパスでないと怒られるようです)

###**オプションを確認したい**

```command
./configure --help
```

###**CFLAG等のデフォルトオプションを変えたい**

configureのオプションで指定できます。

```command
./configure CFLAGS="-g -O0"
```

gdb/valgrind等を利用する為に"-g -O0"オプションを使いたい時などに便利

###**作成したプログラムでvalgrind, gdbが実行できない**

プログラムがconfigureパッケージ内で作成したライブラリをリンクしている場合、**実体は.libs/内に存在することがあります。**
実体を利用する際は**LD_LIBRARY_PATHで利用しているライブラリのパスを通すこと**も忘れずに。こちらもビルドしたライブラリフォルダの.libs内にあります。

その際の直下にあるプログラムと同名のファイルは、唯のライブラリパスを通す為のスクリプトだったりします。

##**自作パッケージ**

###**configureパッケージの導入方法について**

[こちら](https://qiita.com/developer-kikikaikai/items/433d69c4bcbf52b249a1)にまとめてあります。

###**自作パッケージのインストール指定方法**

基本: パス名_オプション

オプションについて:ビルドするプログラムの場合 PROGRAMS

```Makefile.am
sbin_PROGRAMS=lighttpd lighttpd-angel
```

オプションについて:ヘッダーの場合 HEADERS

```Makefile.am
include_HEADERS = event_threadpool_data.h  event_threadpool.h
```

オプションについて:スクリプトの場合(このケースはsbinにインストール)

```Makefile.am
sbin_SCRIPTS=CommandClient.py  CommandServer.py  CommandService.py
```

インストールしない場合:パス名にno_instを指定

```Makefile.am
noinst_PROGRAMS = test
```

###**configureパッケージ内で作成したライブラリをリンクしたい**

**実行プログラムへのリンク** LDADDで.laファイルを指定します。

```Makefile.am
test_LDADD = $(LDPATH)/libpublisher.la
```

もしくは共通設定ファイルのam.confを作成し、AM_LDFLAGSに指定すればリンクできます。

```am.conf
AM_LDFLAGS+=$(top_srcdir)/flyweight/lib/libflyweight.la
```

```shell:Makefile.am
include $(top_srcdir)/flyweight/flyweight_am.conf
```

**作成ライブラリ内でライブラリリンク**
ライブラリのMakefile.am内、ライブラリ_LDFLAGSで.laファイルを指定すればOKです。

```Makefile.am
libflyweight_la_LDFLAGS=-rpath $(libdir) $(top_srcdir)/design_pattern_util/lib/libdputil.la
```

**注意:**
1. **installを伴う利用方法の場合は、-sharedオプションを付けて共有ライブラリにする**。じゃないとインストールに失敗します。
2. **ライブラリの共有ライブラリリンク、`-Xlinker -rpath -Xlinker $(libdir)`でパスを通してあげないとinstall後にパスが解決しません**。逆に**Xlinker を付ければ片方のライブラリだけリンクすればOK**。謎過ぎるlibtool。
3. ライブラリ内でのライブラリリンクコンパイル自体はAM_LDFLAGSでも可能ですが、どうも**AM_LDFLAGSを利用すると共有ライブラリに静的ライブラリの関数が取り込まれないようです**。そのため、実行プログラムは共有ライブラリと静的ライブラリの両方をリンクする必要が出てきてしまいます。

2に興味がある方は[同パッケージ内でのライブラリのライブラリリンク](https://qiita.com/developer-kikikaikai/items/c3546cede0184f311d0e#%E5%90%8C%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E5%86%85%E3%81%A7%E3%81%AE%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%83%AA%E3%83%B3%E3%82%AF)に比較結果を記載しています。理由は未確認。

3に興味がある方は[補足のconfigureパッケージ内で作成したライブラリをリンクについて](https://qiita.com/developer-kikikaikai/items/c3546cede0184f311d0e#configure%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E5%86%85%E3%81%A7%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%82%92%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)に比較結果を記載しています。理由は未確認。

###**共有、静的それぞれのライブラリ作成方法が知りたい**

**共有ライブラリの場合** ライブラリのMakefile.amに`-shared`オプションを指定すればOK。

```Makefile.am
libflyweight_la_LDFLAGS=-shared -rpath $(libdir) $(top_srcdir)/design_pattern_util/lib/libdputil.la
```

**静的ライブラリの場合** ライブラリのMakefile.amに`-static`オプションを指定すればOKです。

```Makefile.am
libflyweight_la_LDFLAGS=-static -rpath $(libdir) $(top_srcdir)/design_pattern_util/lib/libdputil.la
```

また、**XXX_la_LDFLAGSを指定しないと静的ライブラリ**、**XXX_la_LDFLAGSを指定して-static, -sharedをつけないと両方**という不思議な仕様になっている模様。

###**configure.acで使えるオプションが知りたい**

[こちら](https://qiita.com/developer-kikikaikai/items/323081ba04c48930dbc0)にわかる範囲で纏めました。

###**自作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
```

こちらも面倒ですが一応対処出来ました。やったことは
1. XXX/missingを消す
2. configure.acの`AC_PREREQ([2.XX])`のバージョンを環境のものに変更。自分は2.69=>2.59へ
3. autoreconf --installを実行。エラーをつぶす
4. エラーがつぶれたら./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はローカルシンボル**(ライブラリ内部で取り込めた関数)となります。

```:AM_LDFLAGSで取り込み
$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
```

```:libpublisher_la_LDFLAGSで取り込み
$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)`を追加してみます。

```Makefile.am
...
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)
```