ポエム
CMakeLists.txt は便利なのだが、ちゃんと書き方を考えるほど切羽詰まった場面が自分にはなかった。今回は書いていて気になったのでちゃんと書く方法を調べたりしてみた。正直知見がなかったので何でググったっけを書いておくメモみたいなものである。
やりたいこと
- static に依存させるライブラリを作成したい
- 作成したライブラリは
ExternalProjectなどで github 上から依存解決をしたい - なるべくならグローバルを汚染しないで依存解決をしたい
要は cmake でのライブラリの書き方がわかれば良い。ただ、静的ライブラリであれば add_subdirectory すればよくね?という気持ちがないではない。今回は何が何でも静的リンクさせたかった、 cmake 経由でやれたことなかったからね。
やること
ライブラリ側
特殊なことは今回はしないのでこれだけ。target_sources コマンドでコンパイル対象を指定し、 set_property コマンドから PUBLIC_HEADER プロパティを指定してインストール時にインストールすべきヘッダを指定して、 target_include_directories で自身のヘッダファイルの場所を指定して、 install コマンドでインストール先を指定している。あとはこの辺の単語でググれば最終的にはリファレンスにぶつかって解決できると思う。
- CMakeLists.txt
project(sample_lib VERSION 0.0.1 LANGUAGES CXX)
add_library(sample_lib STATIC)
target_sources(sample_lib
PRIVATE
# .cpp ファイルはここに書く
)
set_property(TARGET sample_lib
PROPERTY PUBLIC_HEADER
# .hpp ファイルはここに書く
)
target_include_directories(sample_lib
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> # ライブラリのビルド時に読み込むべき include ディレクトリ
$<INSTALL_INTERFACE:include>) # ライブラリのインストール時(依存側で)読み込むべき include ディレクトリ
install(TARGETS sample_lib
EXPORT libsample_lib
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
PUBLIC_HEADER DESTINATION include)
利用する側
ExternalProject_add で CMakeLists.txt のあるディレクトリやレポジトリを指定すると、 cmake が走りよしなにビルドしたりインストールしてくれる。 INSTALL_DIR などでインストール先指定しているけれど、特段指定しなければデフォルトのディレクトリに突っ込まれる。が、 Windows 環境でやっていたのでインストールステップ時に C:\Program Files\ 下にライブラリをインストールしようとし、パーミッションが足りずに失敗する罠に引っかかったりするの利用側で指定してしまうのが、別段深い知見はないのだが、良いのではと思った。
- CMakeLists.txt
project(test_app)
add_executable(test_app main.cpp)
include(ExternalProject)
## Dependencies
ExternalProject_add(sample_lib
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/sample_lib
GIT_REPOSITORY https://path/to/sample_lib
GIT_TAG master
INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}
CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}"
)
add_dependencies(test_app sample_lib)
link_directories(test_app PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/lib)
target_include_directories(test_app PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include)
target_link_libraries(test_app PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/lib/libsample_lib.a)
あとがき
別段ベストプラクティスではないと思うので動くもの書いたくらい。 lib とか .a とか cmake 側でちゃんと生成して作ったほうがいいし、そも add_subdirectory と差があるんだっけとか、たぶん改善ポイントはすごく多い。
あと、今回作ってて依存側が依存先のことを超絶細かく知っていてもおかしくないという作りに本能が納得するまですごく時間がかかった。仕事では利用先のライブラリの名前とバージョン書いたら利用できることが多く、ここまでビルドやインストールの中身を意識したのが久々でたいへんつらかった。