自作ライブラリのconfigure導入

configureは昔に導入したことがあったけど、もうやり方を忘れてしまった。
せっかくのgithubコードに追加するので、試しにconfigure化してみよう！




##configureとは？

自分でMakefileを書くと、毎回環境に合わせたライブラリパス、リンクを変更して、ヘッダパスも探して、、、
と**環境ごとにメンテナンスが大変。**
**→これを解決してくれるのがconfigure**

正しくconfigureの設定をしておけば、この辺を全部勝手に解決してくれます。

ってのがよく見かける説明ですね。


自分が思う特徴・感想を3行にまとめると以下。

- 標準ライブラリのリンクが凄い楽
- 自作buildオプションが./configure -helpで確認出来る。
- 勝手に解決してくれる分、何か問題があった場合の調査が大変かも。

最後に色々書いてます。


##基本的な手順


1. 必要パッケージをインストール(autotool, libtoolだったはず)
2. コードのトップディレクトリでautoscanを実行
3. configure.scanが出来るので、configure.acにrename
4. autoreconf --installを実行 ※1
5. Makefile.amを追加
6. automakeを実行 (最初だけautomake --add-missing)
7. 出てきたエラーに対してconfigure.ac、Makefile.amを修正
8. 4～7を繰り返し、コマンド実行時のエラーを修正する。

※1 autoreconfでは、aclocal, autoheader, automakeでそろえる必要な環境を一手にそろえてくれます。

で、エラーが出なくなって、./configure→makeが出来るようになれば完了です。


手順は決まってるんですが、configure.acとMakefile.amにとっかかるのが大変なのかな。
Makefile.amやconfigure.acは既存のコードやOSSを参考にするとよさそうですね。

次以降にやったことを記載していきます。


##Makefile.amについて

基本はこんな感じ

- srcのないフォルダにもSUBDIRSを指定したMakefile.amを置く
- srcフォルダはターゲット名を指定→ターゲット名_XXXXがよくあるMakefileのフラグ定義になる。

例

``````````````Makefile.am
SUBDIRS = lib include
``````````````

``````````````lib:Makefile.am:lib
#installいらない場合
noinst_LTLIBRARIES = libtimelog.la
#installする場合
#lib_LTLIBRARIES = libtimelog.la

#コードの指定
libtimelog_la_SOURCES = timetestlog.c
``````````````

ヘッダー、バイナリもインストールするかどうか選べます。インストールしない場合はnoinstで共通です。

`````````````Makefile.am
#installする場合
include_HEADERS= libtimelog.la

#installする場合
bin_PROGRAMS = test
``````````````

この辺の記載方法が色々癖があるみたいで、必要に応じて調べる必要アリです。

また、こんな風に共通定義をまとめることも出来るみたい

``````````````am.conf
#common header deifinition
#topにこのファイルを置いておく
AM_CPPFLAGS=-I$(top_srcdir)/include
INCLUDES_PATH=$(top_srcdir)/include
``````````````

``````````````lib:Makefile.am側
#includeでその設定を読み込み
include $(top_srcdir)/am.conf
``````````````

動的静的両方作れる記憶があったけどそれはまたの機会に。

2018/05/15 

動的静的両方作れる方法: LDFLAGSを付けるだけでよさそうです。例えば以下のようにrpathだけ通してあげればOK。
**-shared, -staticどちらかが付いてると片方が優先されるので、どちらもつけない**がポイントのようです。
Ubuntu18.04で動作確認

``````````````lib:Makefile.am:lib
libtimelog_la_SOURCES = timetestlog.c
libtimelog_la_LDFLAGS=-rpath $(libdir)
``````````````

##configure.acについて

やることとしては、
・コンパイル対象のフォルダ全てにXXX/Makefileの記載をAC_CONFIG_FILESに追加する。
・autoscanで出てこなかった必要オプションを追加する。

後者はautomake, autoreconf時にエラーが出るので順次つぶしていけばいいんだけど、これが慣れないと大変そう。

自分が今回出くわしたのは以下

・しょっぱなのautomake時に以下のエラー
>error: no proper invocation of AM_INIT_AUTOMAKE was found.

→configure.acに以下を追加して対処

``````````````configure.am
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
AM_PROG_AR
``````````````


・autoreconfでlibフォルダに対する以下エラー

>libtoolize: Consider adding `AC_CONFIG_MACRO_DIR([m4])' to configure.ac and
libtoolize: rerunning libtoolize, to keep the correct libtool macros in-tree.
libtoolize: Consider adding `-I m4' to ACLOCAL_AMFLAGS in Makefile.am.

→configure.acに以下を追加して対処

``````````````configure.am
LT_INIT
``````````````

自分はこれでうまく動くようになりました。

例えばpthreadのようなライブラリは、autoscan時に検知して勝手にconfigure.acに追加、リンクしてくれます。
なので、自分が作ったライブラリだけ意識すればいいのが楽ですね。


###唯一覚えていた便利機能


./configureのオプションって、自作出来るんですよね。
(しかもちゃんと./configure --helpで確認もできます。個人的にはこれが感動した)

例えば--enable-debugでデバッグの有効/無効を切り替えたいなら``AC_ARG_ENABLE``と``AC_DEFINE``を使います。

AC_ARG_ENABLEはenable-optionを認識する。
AC_ARG_ENABLE( option, ヘルプメッセージ, オプション指定時の実行シェル, デフォルト値)

AC_DEFINEは-DXXXのようなdefineを渡してあげる
AC_DEFINE(define名, define値, [説明])

みたいな感じ。

自分はこんな感じでtreadsafeオプションを追加しました。

```````````````````````configure.am
#AC_ARG_ENABLE( option, help message, script code for this option, default value)
AC_ARG_ENABLE(threadsafe,
[  --enable-threadsafe      enable to share handle between threads [[default=no]]],
[\
#
case "${enableval}" in
 yes) enable_threadsafe=yes ;;
 *)   AC_MSG_ERROR(bad value for --enable-) ;;
esac],
enable_threadsahe=no)

#check flag and set defile
if test x"${enable_threadsafe}" = x"yes"; then
  AC_DEFINE(THREAD_SAFE, 1, [Define to 1 if you want to ensure thread safe])
else
echo "libnotify is disabled"
fi
```````````````````````````````````

ヘルプはこんな感じに見えます。

```````````````````````````````````
./configure --help
...
  --enable-threadsafe      enable to share handle between threads [default=no]
```````````````````````````````````

一気にそれっぽくなる！
デバッグオプションなどの管理も楽なので、ここも便利なところですね。

オプションについてのまとめを作りました。
[こちら](https://qiita.com/developer-kikikaikai/items/323081ba04c48930dbc0)です。

##個人的感想

####良い点
- 標準ライブラリのリンクを勝手に張ってくれるのが凄い楽  (rtとか高確率で追加するの忘れます)
- 少ない記載で作れるのがうれしい
- **コンパイルオプションをconfigureのオプション化。しかもhelpで確認できる**

個人の趣味ですが、最後だけでも導入する価値はあると思います。
コンパイルオプション、便利だけど作り手の趣味が出るから共有しにくいんですよね。自分で作っても忘れちゃう。
これが**ドキュメントのメンテせずとも./configure --helpで確認出来る。**
実装好きな人って、ドキュメントは書かないけどhelpとかusageを書くってなるとちゃんと書くんですよね。

####気になる点
- 導入時のお任せ部分でのエラーが追いにくい

お任せツール全般に言えることですが、中の動作を把握していないものがうまく動作しなかった場合の原因調査って大変ですよね。
昔本格的に色々導入しようとした時は、configureスクリプトの中をガツガツデバッグして、
原因か所を見つけるのに凄い苦労した覚えがあります。

config.logにログは出てるので、ちゃんとしたOSSならこれだけでも十分原因を追う足掛かりになりますが、
自作だと色んなことを疑っちゃいますしね。

- libtoolにバージョン差分があった場合の挙動がよくわからない。

libtoolはほんとよくわからない。

出会ったケース その1. 
libtool、ltmain.shの実体を置いておけば動作する認識だったが、高バージョンのlibtool環境で利用するとmakeで失敗してしまいました。
(Ubuntu 14.04で作成→Ubuntu18.04でのビルドに失敗)
→この場合はlibtool、ltmain.shを消して、autoreconfを実行すると解決しました。

その2. 
逆に古いlibtoolの環境にコードを持ってきた際、./configure->makeは出来ましたが、
configure.acを編集→autoreconfを実行すると、以降一切buildもautoreconfも出来なくなりました。
(試したのはUbuntu18.04→Cent OS 5.1)

何もしなければ./configure, makeはいけるからいいけど、う～ん、このあたりよくわからない。

この辺ちゃんとしたOSSだとちゃんと作られているので問題も追いやすいのですが、
自作だと色んなことを疑っちゃうのでちょっと敷居が高い点の一つかなと思います。

導入も機能も便利だけど、お任せな分でハマると辛いところもあるので好みが分かれそうですね。
世の中のOSSはどうやってるんだろう。バージョンチェックしてるのは見たけど

困ったことがあったらこちらに記載するようにしています。
[configure利用TIPS](https://qiita.com/developer-kikikaikai/items/c3546cede0184f311d0e)
(ゴミ箱化してますが)

##サンプルコード

https://github.com/developer-kikikaikai/speedtest

以下で紹介したライブラリをconfigure化しました。
https://qiita.com/developer-kikikaikai/items/d8839eae7f4491e01671



##参考
http://nopipi.hatenablog.com/entry/2013/01/14/025509
https://qiita.com/impepc/items/1bfdfe8ad741def10948
http://capm-network.com/?tag=autotools%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E6%A7%8B%E6%88%90%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB
https://stackoverflow.com/questions/28972112/autotools-setup-for-static-and-shared-libraries?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
http://d.hatena.ne.jp/kakurasan/20090512/p1