cmake で依存ライブラリをダウンロードする

`cmake-3.11` から FetchContent という機能が追加されて便利になっていた。

- dependency をビルド時にダウンロードもしくは clone することができる
- ダウンロードしたソースを `subdirs` できる
- ダウンロードしたソースに対して `add_library` などを記述できる
  - ビルド済みの `dll` や `lib` をダウンロードする使い方(Windowsでたまにある)

https://cmake.org/cmake/help/latest/module/FetchContent.html

:::note warn
ソースの展開先

基本的には `build(CMAKE_BINARY_DIR)` に展開される。

* FetchContent_Declare は `build/_deps`
* FetchContent_Populate は `build` 

なんか `CMAKE_CURRENT_LIST_DIR` に展開されることがあったのだが原因はよくわからず。
`toolchain` や `subdirs(../../../some)` のような場合に構成の影響を受けるかもしれない。
:::

# FetchContent_Declare & FetchContent_MakeAvailable

ソースの中に `CMakeLists.txt` が含まれているので、そのままこれをビルドして使う例。
`download extract` or `clone` してから `subdirs(SOURCE_DIR)` すると考える。

## GLFW

```cmake
include(FetchContent)
set(BUILD_SHARED_LIBS ON)
set(GLFW_BUILD_EXAMPLES OFF)
set(GLFW_BUILD_TESTS OFF)
set(GLFW_BUILD_DOCS OFF)
FetchContent_Declare(
  glfw
  GIT_REPOSITORY https://github.com/glfw/glfw.git
  GIT_TAG 3.3.8)
FetchContent_MakeAvailable(glfw) # 👈 FetchContent_Declare で指定した名前。target ではない。多分、違う名前でも動く
```

```cmake
# 使う
target_link_libraries(${TARGET_NAME} PRIVATE glfw) # 👈 これは glfw/src/CMakeLists.txt で定義された target 名。この名前である必要がある。
```

## SDL2 と freetype

```cmake
include(FetchContent)
FetchContent_Declare(
  sdl
  GIT_REPOSITORY https://github.com/libsdl-org/SDL
  GIT_TAG release-2.26.1
  GIT_PROGRESS TRUE)

FetchContent_Declare(
  freetype2
  GIT_REPOSITORY https://github.com/freetype/freetype.git
  GIT_TAG VER-2-13-2
  GIT_PROGRESS TRUE)

FetchContent_MakeAvailable(sdl freetype2) # 👈 FetchContent_Declare で指定した名前。target ではない。多分、違う名前でも動く
```

```cmake
# SDL2 使う
target_link_libraries(${TARGET_NAME} PRIVATE SDL2::SDL2 SDL2::SDL2main) # 👈 SDL2main に注意

# freetype 使う
target_link_libraries(${TARGET_NAME} PUBLIC freetype)
```

# FetchContent_Populate

ダウンロードと解凍まで。
ソースの中に `CMakeLists.txt` が含まれていなかったり使わない場合。
展開されたソースは FetchContent_Populate に指定した `some_SOURCE_DIR` という変数に格納される。
`${some_SOURCE_DIR}` に対して `add_library` や `target_include_directories` などする。

## glew

```cmake
include(FetchContent)
FetchContent_Populate(
  glew
  URL https://sourceforge.net/projects/glew/files/glew/2.1.0/glew-2.1.0.tgz/download
)
add_library(glew SHARED ${glew_SOURCE_DIR}/src/glew.c
                        ${glew_SOURCE_DIR}/src/glewinfo.c)
target_include_directories(glew PUBLIC ${glew_SOURCE_DIR}/include)
target_compile_definitions(glew PRIVATE GLEW_BUILD # PUBLIC GLEW_STATIC
)
target_link_libraries(glew PUBLIC OpenGL32)
```

## getopt の windows 代替

CMake を自前で記述する例。

```cmake
if(WIN32)
  FetchContent_Populate(
    getopt # 👈 ソースの展開先は ${getopt_SOURCE_DIR} に格納される
    GIT_REPOSITORY https://github.com/takamin/win-c.git
    GIT_TAG v1.0)
  add_library(getopt ${getopt_SOURCE_DIR}/source/getopt.c)
  target_include_directories(getopt PUBLIC ${getopt_SOURCE_DIR}/include)
endif()
```

## OpenXR

ちょっと変則的。

Windows では、 `OpenXR.Loader.1.0.25.nupkg` をダウンロードしてビルド済みの `dll` を使う。
`OpenXR-SDK`, `OpenXR-SDK-Source` をクローンしてもできるが、python が動いたりややこしいのでビルド済みで楽をする。

```cmake
include(FetchContent)
FetchContent_Populate(
  openxrsdk # 👈 ソースの展開先は ${openxrsdk_SOURCE_DIR} に格納される
  URL https://github.com/KhronosGroup/OpenXR-SDK/releases/download/release-1.0.25/OpenXR.Loader.1.0.25.nupkg # 👈 zip として解凍してくれる
)
add_library(openxr_loader SHARED IMPORTED) # 👈 ビルド済みの dll なので `SHARED IMPORTED`

  set_target_properties(
    openxr_loader
    PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${openxrsdk_SOURCE_DIR}/include
               IMPORTED_LOCATION
               ${openxrsdk_SOURCE_DIR}/native/x64/release/bin/openxr_loader.dll # 👈 Windows の build 済み
               IMPORTED_IMPLIB
               ${openxrsdk_SOURCE_DIR}/native/x64/release/lib/openxr_loader.lib
               IMPORTED_GLOBAL true)

install(IMPORTED_RUNTIME_ARTIFACTS openxr_loader)
```

# 参考

https://toge.hatenablog.com/entry/2021/01/27/150632

https://github.com/eliasdaler/cmake-fetchcontent-tutorial-code/blob/master/dependencies/CMakeLists.txt