cmakeでHeader Onlyライブラリをお手軽に使う
FetchContentを使う動機
cmakeでHeader Onlyライブラリをちょっと使いたい場合ありますよね。
git submoduleでいいのですが、ちょっと管理が煩雑だなぁと思っています。
普段はなるべくConanパッケージを作る→使うのですが、お試しでマイナーなライブラリ使うときには仰々しいかなぁと思ったりします。
そこでCMake 3.11から導入されたFetchContent機能を利用してみました。 cmake.org
FetchContentはかなり柔軟に書くことができて、gitで指定ブランチもtar.gz/zipの取得・展開もできます。
私は「なるべくリリースされたものを使いたい」という考え方なので、リリースされたものを利用することにします。
今回はちょうど最近リリースされたCTML 2.0.0を触ってみたかったのでそれを例にしてみます。
※CTMLはHeader OnlyのHTML生成ライブラリです。
CMakeLists.txtの書き方
FetchContent機能を使ったCMakeLists.txtの例です。
project(ctml CXX) cmake_minimum_required(VERSION 3.11.0) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") include(FetchContent) FetchContent_Populate( ctml URL https://github.com/tinfoilboy/CTML/archive/2.0.0.tar.gz URL_HASH MD5=936e08167384fee9a4445fed343e83dc ) include_directories(${ctml_SOURCE_DIR}/include) add_executable(test test.cpp)
本当はFetchContent_Declare
や FetchContent_MakeAvailable
を組み合わせるべきなんでしょうが、簡単にするため FetchContent_Populate
だけですませています。
CMakeの実行と結果の確認
CMakeLists.txtの存在するディレクトリでcmakeを実行してみます。
% cmake -B build --verbose -S . -- The CXX compiler identification is AppleClang 12.0.0.12000032 -- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ -- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Populating ctml -- Configuring done -- Generating done -- Build files have been written to: /Users/toge/src/ctml/build/ctml-subbuild Scanning dependencies of target ctml-populate [ 11%] Creating directories for 'ctml-populate' [ 22%] Performing download step (download, verify and extract) for 'ctml-populate' -- Downloading... dst='/Users/toge/src/ctml/build/ctml-subbuild/ctml-populate-prefix/src/2.0.0.tar.gz' timeout='none' -- Using src='https://github.com/tinfoilboy/CTML/archive/2.0.0.tar.gz' * Closing connection 0 -- verifying file... file='/Users/toge/src/ctml/build/ctml-subbuild/ctml-populate-prefix/src/2.0.0.tar.gz' * Closing connection 1 -- Downloading... done -- extracting... src='/Users/toge/src/ctml/build/ctml-subbuild/ctml-populate-prefix/src/2.0.0.tar.gz' dst='/Users/toge/src/ctml/build/ctml-src' -- extracting... [tar xfz] -- extracting... [analysis] -- extracting... [rename] -- extracting... [clean up] -- extracting... done [ 33%] No patch step for 'ctml-populate' [ 44%] No update step for 'ctml-populate' [ 55%] No configure step for 'ctml-populate' [ 66%] No build step for 'ctml-populate' [ 77%] No install step for 'ctml-populate' [ 88%] No test step for 'ctml-populate' [100%] Completed 'ctml-populate' [100%] Built target ctml-populate -- Configuring done -- Generating done -- Build files have been written to: /Users/toge/src/ctml/build
こうすると、buildディレクトリの下が次のようになります。
% find build -type d build build/ctml-src build/ctml-src/include build/ctml-src/tests build/ctml-src/.github build/CMakeFiles build/CMakeFiles/3.15.3 build/CMakeFiles/CMakeTmp build/CMakeFiles/test01.dir build/ctml-subbuild build/ctml-subbuild/CMakeFiles build/ctml-subbuild/CMakeFiles/ctml-populate.dir build/ctml-subbuild/CMakeFiles/3.15.3 build/ctml-subbuild/ctml-populate-prefix build/ctml-subbuild/ctml-populate-prefix/tmp build/ctml-subbuild/ctml-populate-prefix/src build/ctml-subbuild/ctml-populate-prefix/src/ctml-populate-stamp build/ctml-build
ちゃんとctml-srcの下にCTML-2.0.0.tar.gzを展開した結果が配置されてます。
ソースコードでの参照方法
build/ctml-src
というパスは <name>_SOURCE_DIR
というCMakeの変数で参照可能になっています。
name
はFetchContent_Populateの最初の引数で指定しているので、今回の場合はctml
ですね。
このため、今回は次のようにinclude_directoryを指定しています。
include_directories(${ctml_SOURCE_DIR}/include)
これでソースコードの中でCTMLのヘッダをインクルードできます。
#include <iostream> #include "ctml.hpp" int main(int argc, char* argv[]) { ...
まとめ
CMakeのFetchContentを利用してHeader Onlyライブラリを利用する方法を説明しました。
FetchContentではconfigure→build→testの処理も定義できるみたいなのですが、今回はHeader Onlyライブラリなので何も指定していませんでした。
機会があればビルド必須なライブラリをFetchContentで利用してみようと思います。