S/Wだとそんなことはまずないが、H/Wだと今動いているコードが何か知りたいので、コードの一部にgitのコミット番号を埋め込みたい、みたいなことが起こる (らしい。) その時に引っかかったことがあるので残しておく。結論から言うとTARGET
を使うadd_custom_command
を使うのが一番いい気がする。なおCMakeに関してはほとんどわかっていないのでご容赦を...
gitのコミットハッシュを取得する
gitのコミットハッシュ自体は下で取得できる(長いやつ)
$ git log --pretty=format:%H -1
# 又は
$ git rev-parse HEAD
短いやつ
$ git log --pretty=format:%h -1
# 又は
$ git rev-parse --short HEAD
CMakeの処理3段階
- Configure ファイルの依存関係をさらう
- Generate さらった依存関係を元にビルド用ファイルを作成
- Build ビルドを実行
の主に3段階ある。よく
-- Configuring done
-- Generating done
-- Build files have been written to: /hogehoge
みたいな表示を見る。
CMakeでコマンド実行
CMakeでコマンドを実行する方法は主に2通りある。 execute_process
と add_custom_command
の2つ。2つと書いたが、add_custom_command
には使い方が2通りあって、頭にOUTPUT
を持ってくるかTARGET
を持ってくるかで処理が全く違う。OUTPUT
を持ってきた場合はビルド用のファイル生成でTARGET
を使うのはビルド時にコマンド実行(ビルドイベント)をする用途になる。
cf. add_custom_command - CMake
このうち、上のビルド時に実行されるのはadd_custom_command
のTARGET
のみ。他は configure or generate で実行される。
Gitハッシュ埋め込み
execute_process
とadd_custom_command
の使い方についてはCMakeの公式リファレンスにしっかり載ってるのでそちらに譲る。
cf. execute_process - CMake
1つ目の方法としてexecute_process
でハッシュ値を取得、configure_file
で埋め込み、という手がある。WORKING_DIRECTORYはgit ~
を実行するディレクトリを指定するので、git submodule
内部のハッシュ値が欲しい場合はそのディレクトリを指定してあげればいい。
execute_process(COMMAND git rev-parse --short HEAD
OUTPUT_VARIABLE git_rev
OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${WORKING_DIRECTORY})
configure_file ("hogehoge.tmp" "hogehoge.h")
hogehoge.tmp
の中に@git_rev@
みたいな文字列を用意しておけば、そこが勝手にgitのハッシュに置き換わってhogehoge.h
を出力してくれる。
別の方法としてadd_custom_command
でOUTPUT
を使う場合。こちらは公式リファレンスにもあるが役目がGenerating Filesなのでビルド前にファイル生成を行うのが主目的。そのファイルがCMakeLists.txt
でビルドに使用されるとわかっている時、適当に文字列をハッシュに書きかえる.bat
なり.sh
なりを用意してあげればconfigure & generate中にそのコマンドが実行されてくれる。
add_custom_command(OUTPUT hogehoge.h
COMMAND hogehoge.bat
WORKING_DIRECTORY ${WORKING_DIRECTORY})
ただ上の2つの問題点は上でも書いたようにビルド直前では実行されないことだ。一度フォルダを開いてconfigure & generateが済まされた場合、hogehoge.h
に何らかの変更が加えられてもその変更を超えてgitのハッシュの反映をなされない。そういう場合でも変わらず埋め込みたい場合はadd_custom_command
のTARGET
を使用する。こちらの役割はBuild Eventsである。
add_custom_command(TARGET ${PROJECT_NAME}
PRE_BUILD
COMMAND hogehoge.bat
WORKING_DIRECTORY ${WORKING_DIRECTORY})
これはビルドが実行される場合、つまりプログラムが走る場合常に直前に実行されるので他の改変の影響を受けない。のでそうして欲しい場合はadd_custom_command
のTARGET
を使用しよう。ここではビルド直前に反映されて欲しいのでPRE_BUILD
としているが、PRE_LINK
, POST_BUILD
などで実行するタイミングを指定できる。