CMakeでビルドした実行プログラムのあるディレクトリにリソースファイルをコピーする
やりたいこと
CMakeを用いてプロジェクトを管理しているときに、ビルドした実行ファイルと同じディレクトリ(またはそこから相対的に定義されるディレクトリ)に画像データ等のリソースデータをコピーしたいという状況を考える。
リソースファイルは、例えば次のように定義されているとする。
file(GLOB RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/*.png)
問題点
ビルド環境ごとにビルドした実行プログラムが配置されるディレクトリは異なる可能性がある。
例えば、Makefileを生成してmake
とした場合には${CMAKE_CURRENT_BINARY_DIR}
に実行プログラムが配置されるが、Xcodeを用いてビルドすると、例えばDebug
モードでビルドすると${CMAKE_CURRENT_BINARY_DIR}/Debug
に配置される。
更に、macOSで.app
バンドルを生成する場合は、実行ファイルの本体は[...].app/Contents/MacOS
に配置される。
したがって、リソースファイルを実行ファイルのあるディレクトリにコピーしたい場合、単にfile
コマンドを使って
file(COPY ${RESOURCE_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
としても、ビルド環境によっては意図通りにコピーされないことがある。
解決策:Generator Expression
Generator Expressionを用いれば良い。これは、CMakeのドキュメントに
Generator expressions are evaluated during build system generation to produce information specific to each build configuration.
と説明にあるように、ビルド環境に応じて評価される式ということらしい。
cmake-generator-expressions
https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html
したがって、ビルド環境依存の部分は、generator expressionsを用いることで統一的に記述することができるようになる。
CMakeに定義されているgenerator expressionsのうち、特に
$<TARGET_FILE_DIR:my-program>
という式を用いると、ビルドした実行プログラムが配置されるディレクトリを得ることができる。ただしmy-program
の部分にはそれぞれのターゲット名が入る。
リソースファイルをコピーするには、これを用いて
add_custom_command(TARGET my-program POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${resources} $<TARGET_FILE_DIR:my-program>)
などと記述すれば良い。
add_custom_command
https://cmake.org/cmake/help/latest/command/add_custom_command.html