cmakeでfind_packageライクに自作ライブラリ有無をチェックしたりしたい、そんな時にはfind_package_handle_standard_argsが使える

## はじめに

[自作ツール](https://github.com/developer-kikikaikai/EncryptedEditor)に対して[CUnit](https://sourceforge.net/projects/cunit/)での単体テストを導入したはいいんですが、どの環境でもCUnitが無いとビルドが出来ない。
これは使い勝手が悪すぎるので対策を検索したところ、タイトルのような使い方が出来そうなので備忘録。

## CMake、サポートされているパッケージはfind_packageで検索

OpenSSLのような一般的なライブラリはcmake本家で処理が用意されているようで、`find_package(OpenSSL REQUIRED)`のように対象の名前を指定して[find_package](https://cmake.org/cmake/help/v3.3/command/find_package.html?highlight=find_package)してあげればOKです。
例えば[OpenSSL](https://cmake.org/cmake/help/v3.7/module/FindOpenSSL.html)なら、`OPENSSL_INCLUDE_DIR`でヘッダーパスが取れるなど。

ただし、これはあくまで用意されたものに対しての話な模様。`find_package(CUnit REQUIRED)`と書いたところで「FindCUnit.cmakeなんてないからCUnit見つからんよ！」と怒られます。そんな時の話

```console
CMake Error at lib/src/CMakeLists.txt:5 (find_package):
  By not providing "FindCUnit.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "CUnit", but
  CMake did not find one.

  Could not find a package configuration file provided by "CUnit" with any of
  the following names:

    CUnitConfig.cmake
    cunit-config.cmake

  Add the installation prefix of "CUnit" to CMAKE_PREFIX_PATH or set
  "CUnit_DIR" to a directory containing one of the above files.  If "CUnit"
  provides a separate development package or SDK, be sure it has been
  installed.
```

## 自作に対してはfind_package_handle_standard_argsを使う

調べてみると、サポート外のパッケージ名に対しては以下のように[FindPackageHandleStandardArgs](https://cmake.org/cmake/help/v3.3/module/FindPackageHandleStandardArgs.html)を利用して設定を与えることが出来ました。

```cmake
#ヘッダーパスを検索
find_path(CUNIT_INCLUDE_DIR NAMES CUnit/CUnit.h)
#使いたいライブラリのパスを検索
find_library(CUNIT_LIBRARY NAMES cunit)
#Optionを指定してfind_package
find_package_handle_standard_args(CUnit DEFAULT_MSG CUNIT_LIBRARY CUNIT_INCLUDE_DIR)
```

後は通常のfind_packageのようにXXX_FOUND等が使えるようになります。例えばCUnitがインストールされている時だけビルドしたいなら、CUNIT_FOUNDで処理をくくってあげればOK
(サンプルに非推奨のコマンドを記載しているのはよろしくないですが、本筋じゃないのでスルーしてください(-_-;))

```cmake
IF(CUNIT_FOUND)
include_directories("${PROJECT_SOURCE_DIR}/lib/include")
include_directories(${CUNIT_INCLUDEDIR})
link_directories("${PROJECT_SOURCE_DIR}/lib/src")
link_directories(${CUNIT_LIBDIR})
add_executable(test_main main.c)
target_link_libraries(test_main ${CUNIT_LIBRARY})
ENDIF(CUNIT_FOUND)
```

## あるべき姿：ライブラリ側がcmake.configを作成してあげる

@yumetodo さんより「本来はライブラリ側がxxx-config.cmakeを生成するべき」とコメントいただきました。
先ほど紹介したやり方は「CMakeで見つからないライブラリを取り込みたい」でしたが、cmakeで作ったライブラリだったらあるべき姿は「find_packageで見つかるようにしよう！」が正しいですね。

というわけでやり方を追記

### ライブラリ作成者側がやること：install対象にconfig.cmakeを追加するだけ

どうするんだろうと調べたところ、想像以上に簡単に導入が出来ました。やり方としては「ライブラリにEXPORTを指定してFILEの記載を追加する」だけ。
これだけでOKです。

```cmake
#ライブラリのインストール記述。EXPORT encrypt_api-exportを追記
install(TARGETS encrypt_api
        EXPORT encrypt_api-export
        LIBRARY DESTINATION lib
        PUBLIC_HEADER  DESTINATION include)

#新規追加。FILEでファイル名を、DESTINATIONでインストール先を指定するだけ。EXPORTはライブラリに合わせる
install(EXPORT encrypt_api-export
    FILE encrypt_api-config.cmake
    DESTINATION share/cmake/encrypt_api/
    )
```

### ライブラリ利用者側がやること：

find_packageしてtarget_link_librariesするだけなのでらくちんです。

```
find_package(encrypt_api REQUIRED)
target_link_libraries(encrypted_vim encrypt_api)
```

## 参考

調べるとっかかり: [ありきたりなCMakeのプロジェクト作成 for C++](https://qiita.com/yumetodo/items/bd8f556ab56298f19ba8#findxxx%E7%B3%BB%E3%82%92%E3%81%A4%E3%81%8B%E3%81%86-boost%E3%81%A8openssllibressl%E3%82%92%E4%BE%8B%E3%81%AB)
本題の参考元: [adobkin/FindCUnit.cmake](https://gist.github.com/adobkin/1073354)

cmake.configの参考:[お手軽な xxx-config.cmake の作成方法](https://qiita.com/osamu0329/items/134de918c0ffa7f0557b)