Plan 9とGo言語のブログ

主にPlan 9やGo言語の日々気づいたことを書きます。

公式Gitのソースコードレイアウト

Gitのソースコードには、gitコマンドをビルドするためのMakefileが含まれている。Gitコマンドのレイアウトを知らなければ理解の難しいものがいくつかあったので調べた。

Gitコマンドのレイアウト

$PATHに含まれる場所(ほとんどは /usr/bin)にGit関連のコマンドが置かれている。

$ ls -l /usr/bin/git* # コマンド出力は一部加工した
git
git-cvsserver
git-receive-pack
git-shell
git-upload-archive
git-upload-pack

$PATHの他に、Gitが参照するgit-coreというディレクトリがあって、git-coreには$PATHにあるもの全てと、git-addのようにgit-プリフィックスとして付けられた実行ファイルが入っている。git-coreの場所はgit --exec-pathで調べられる。これらのファイルはGitのサブコマンドとして実行できる。実際のところ、ほとんどのファイルはgitシンボリックリンクを張ったものだけど、本体に組み込まれない一部のサブコマンドは、実行ファイルがそのまま配置されている。

$ git --exec-path
/Library/Developer/CommandLineTools/usr/libexec/git-core

$ ls -l $(git --exec-path) # コマンド出力は一部加工した
git -> ../../bin/git
git-add -> ../../bin/git
git-add--interactive
git-am -> ../../bin/git
git-annotate -> ../../bin/git
git-apply -> ../../bin/git
git-archive -> ../../bin/git
git-bisect
git-bisect--helper -> ../../bin/git
...

余談だけどgitコマンドは$PATHgit-coreの2箇所に置かれている。同じものだけど、片方が欠けると動かない。

ソースコードレイアウト

Gitのビルドでは、まずlibgit.axdiff/lib.aなどライブラリをビルドして、Gitの組み込みコマンドとそれらライブラリをリンクするという順番で行う*1

Gitリポジトリ直下にある*.cファイルの一部、例えばdir.cdiff.cなどはlibgit.aとしてビルドされる。このライブラリは、Git本体や、Git本体から独立した単体のサブコマンドとリンクする。リポジトリ直下にあるそれ以外の*.cファイルは、Git本体のソースコードであったり、単体サブコマンドのソースコードであったりする。例えばhttp-fetch.cgit fetchの実装だが、これはGit本体とは別の単体コマンドとしてビルドされる。

builtin/以下にはGit本体に組み込むサブコマンドのソースコードが置かれている。ほとんどの組み込みサブコマンドはbuiltin/以下のソースコードと1 : 1で対応している。例えばbuiltin/add.cgit addコマンドそのものであり、cmd_add(argc, argv, prefix)という関数がエントリポイントとなる。これらのファイルは最終的にGit本体に組み込まれて、git-coregit-addとしてシンボリックリンクが作られる。組み込みサブコマンドのシンボリックリンクはどれもGit本体を参照しており、Gitは実行時のファイル名によって、どのサブコマンドを実行するかを決定する。ただし、少数ではあるがbuiltin以下に対応するファイルを持たない組み込みサブコマンドも存在する。例えばgit cherry-pickbuiltin/にファイルを持たないが、git-cherry-pickという名前のシンボリックリンクは用意される。

残りのディレクトリはそれぞれの目的で用意されている。xdiff/xdiff/lib.aソースコードcompat/は各プラットフォームの互換性問題を解消するためのソースコードが格納されている。またDocumentation/には詳細なドキュメントが用意されているので眺めてみると面白いと思う。

Makefileの変数

Makefileでは上で説明したファイルをどう扱っているか。Makefile変数を調べた。

LIB_OBJS

  • libgit.aを作るためのファイルリスト

BUILTIN_OBJS

  • 組み込みサブコマンドのファイルリスト
  • Git本体はこれとgit.cと各種ライブラリで作られる

BUILT_INS

  • Git本体の組み込みサブコマンドリスト
  • BUILTIN_OBJSと、git cherry-pickなどファイルを持たないもの全て

PROGRAM_OBJS

PROGRAMS

GITLIBS

  • Git本体や単体サブコマンドとリンクするファイル
  • libgit.axdiff/lib.acommon-main.o

BINDIR_PROGRAMS_NEED_X, BINDIR_PROGRAM_NO_X

  • 直接$PATHに置かれる単体コマンド
  • Windowsの場合に.exeを付けるかどうかで変数を使い分ける

*1:libgit.alibgit2とは全く別のものでGitからリンクするためだけに使う