qtpmは基本思想としては以下の様なものを持って作っています
- ポンっと配布できる実行ファイルを作る
- 開発時に必要なライブラリは自前で用意する(apt-getやport installに頼らない)
後者はnpmのローカルインストールのようなものです。配布物に使う開発ライブラリでシステムを汚さない、複数の開発が並行で行われてもお互いに邪魔しないのを目指しています。別にローカル環境の作業効率アップのツール群はMacPortsだろうがHomebrewを使おうが、ChocolateyだろうがNuGetだろうが何でも使えばいいと思うのですが、デプロイするバイナリがどこに由来して来たのか把握できないのは良くないですよね。明示的に「ここから落としてきた」と言えるのが大事。
libgit2をqtpmパッケージとしてビルドしてみたので、その備忘録も兼ねて、このビルドで使った/このビルドのために追加した機能の紹介をします。
- libgit2 zlibはOS
OSごとに必要なファイルやライブラリを細く設定
zlibはMacOS Xには最初から入っています。Linuxはdevパッケージを入れないと、もしかしたらライブラリはあるけどヘッダーがなくてリンクできないかもしれません。
Goと同様ですが、アンダースコア(_
)から始まるファイルはビルド対象から外しています。 _windows.cpp
などのサフィックスでビルド対象指定だとやりにくい(2つ以上の環境でのみ使う)時には今のところこの方法しかありません。zlibのコードは基本的にビルドしないこともあるので、すべてにアンダースコアを付けています。
CMakeExtra.txt
というファイルがパッケージの初期化時に作られますが、これは自動生成されるCMakeLists.txt
から毎回読み込まれます。CMakeLists.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で解説されている順序でライブラリを探しに行くと、OSのライブラリではなくて、MacPortsのライブラリが優先されてしまうため、/usr
以下を優先して探すように設定しています。それ以外の環境ではglobを使って除外したファイルを再びビルド対象に追加しています。
本家との動機を取りやすくするために
必要なファイルのコピーを手作業で行ってもいいのですが、そうするとバージョンアップが多いライブラリだと更新が大変です。今回はファイルの配置をqtpmに合わせてコピーするシェルスクリプトを用意しました。基本的にはsrc以下に配置していくのですが、場合によってはsedコマンドでincludeのパスを修正したりしています。また、Windowsでしか使わないファイルにサフィックスを付けたりしています。
#!/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のトップフォルダ以外のヘッダはデフォルトではインストールされないのですが、ここのリストにディレクトリ名を書けば外部から使えるようにします。
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
まだまだ検証中ですが、だいぶ機能が揃ってきました。