qtpmでOSごとに必要なファイルやライブラリを細く設定

http://qiita.com/shibukawa/items/171391922af2f49159c2

qtpmは基本思想としては以下の様なものを持って作っています

* ポンっと配布できる実行ファイルを作る
* 開発時に必要なライブラリは自前で用意する(apt-getやport installに頼らない)

後者はnpmのローカルインストールのようなものです。配布物に使う開発ライブラリでシステムを汚さない、複数の開発が並行で行われてもお互いに邪魔しないのを目指しています。別にローカル環境の作業効率アップのツール群はMacPortsだろうがHomebrewを使おうが、ChocolateyだろうがNuGetだろうが何でも使えばいいと思うのですが、デプロイするバイナリがどこに由来して来たのか把握できないのは良くないですよね。明示的に「ここから落としてきた」と言えるのが大事。

libgit2をqtpmパッケージとしてビルドしてみたので、その備忘録も兼ねて、このビルドで使った/このビルドのために追加した機能の紹介をします。

* [libgit2](https://github.com/qtpm/libgit2)
zlibはOS

OSごとに必要なファイルやライブラリを細く設定
===========================================

zlibはMacOS Xには最初から入っています。Linuxはdevパッケージを入れないと、もしかしたらライブラリはあるけどヘッダーがなくてリンクできないかもしれません。

Goと同様ですが、アンダースコア(``_``)から始まるファイルはビルド対象から外しています。 ``_windows.cpp`` などのサフィックスでビルド対象指定だとやりにくい(2つ以上の環境でのみ使う)時には今のところこの方法しかありません。zlibのコードは基本的にビルドしないこともあるので、すべてにアンダースコアを付けています。

``CMakeExtra.txt``というファイルがパッケージの初期化時に作られますが、これは自動生成される``CMakeLists.txt``から毎回読み込まれます。``CMakeLists.txt``は書き換えても消えてしまうので、細かい環境ごとの追加設定はここにかきます。

```cmake:CMakeExtra.txt
include_directories("src/private")
if(WIN32)
    include_directories("src/private/deps/winhttp")
    add_defines(-DGIT_WIN32)
else()
    include_directories("src/private/deps/http-parser")
endif()
if(APPLE)
    set(ZLIB_DIR "/usr")
    find_package(ZLIB)
    include_directories(${ZLIB_INCLUDE_DIRS})
    link_libraries(${ZLIB_LIBRARIES})
else()
    add_definitions(-DNO_VIZ -DSTDC -DNO_GZIP)
    file(GLOB zlibfiles src/private/deps/zlib/*.c)
    foreach(path IN LISTS zlibfiles)
        list(APPEND sources ${path}) 
    endforeach()
endif()
```

まず、最初はWindowsかどうかで参照するディレクトリを変えています。

次のif(APPLE)がzlibのための設定です。zlibの場合はOSのzlibを使いますが、この[cmakeのfind_packageで解説されている順序](http://qiita.com/osamu0329/items/bd3d1e50edf37c277fa9)でライブラリを探しに行くと、OSのライブラリではなくて、MacPortsのライブラリが優先されてしまうため、``/usr``以下を優先して探すように設定しています。それ以外の環境ではglobを使って除外したファイルを再びビルド対象に追加しています。

本家との動機を取りやすくするために
==================================

必要なファイルのコピーを手作業で行ってもいいのですが、そうするとバージョンアップが多いライブラリだと更新が大変です。今回はファイルの配置をqtpmに合わせてコピーするシェルスクリプトを用意しました。基本的にはsrc以下に配置していくのですが、場合によってはsedコマンドでincludeのパスを修正したりしています。また、Windowsでしか使わないファイルにサフィックスを付けたりしています。

```sh:update.sh
#!/bin/sh

if [ ! -e libgit2 ]; then
    git clone git@github.com:libgit2/libgit2.git
else 
    pushd libgit2
    git pull
    popd
fi

echo "copying src"
rm -rf src
mkdir -p src/private/deps/regex
cp libgit2/deps/regex/*.h src/private/deps/regex
cp libgit2/deps/regex/regex.c src/private/deps/regex/regex_windows.c
cp -r libgit2/deps/http-parser src/private/deps/http-parser
cp -r libgit2/deps/winhttp src/private/deps/winhttp
cp -r libgit2/deps/zlib src/private/deps/zlib
sed -i -e 's/src\///g' src/private/deps/zlib/zconf.h
cp -r libgit2/src/* src/private/
pushd src/private/deps/zlib > /dev/null
for f in *.c; do
  mv $f _$f
done
popd > /dev/null
for f in src/private/win32/*.c; do
  mv $f ${f%.c}_windows.c;
done
for f in src/private/unix/*.c; do
  mv $f ${f%.c}_unix.c;
done
mv src/private/hash/hash_win32.c src/private/hash/hash_windows.c
echo "copying headers"
cp -r libgit2/include/git2 src/
cp libgit2/include/git2.h src/
echo "copying examples"
cp -r libgit2/examples/* examples/
```

追加でインストールするヘッダのフォルダを登録
=============================================

今回のライブラリは、トップフォルダのヘッダーだけではなく、トップ下のフォルダのヘッダも間接的に外部から使われる設計になっています。これもvendor以下のコピーしたいので、``extra_install_dirs``という設定を用意しました。srcのトップフォルダ以外のヘッダはデフォルトではインストールされないのですが、ここのリストにディレクトリ名を書けば外部から使えるようにします。

```toml:qtpackage.toml
name = "git2"
author = "libgit2 authors"
organization = ""
license = "GNU General Public License (GPL) v2.0 with linking exception"
version = [0, 24, 0]
extra_install_dirs = ["src/git2"]
project_start_year = 2008
```

まだまだ検証中ですが、だいぶ機能が揃ってきました。