VCPKGを利用して、Windows上でgrpc_cppする

Windowsで [gRPC Basics - C++](https://grpc.io/docs/tutorials/basic/cpp/) するのが環境面でやっかいだったのでメモ。
[VCPKG](https://github.com/Microsoft/vcpkg) で比較的楽にできる。

作業環境は、

* Windows10
* VisualStudio2019のC++
* VSCode(+ cmake extension)

実験プロジェクト
https://github.com/ousttrue/grpc_cpp

# GRPCライブラリのインストール

```
$ vcpkg install grpc
```

以上。
grpc は `zlib, openssl, protobuf, c-ares, upb, abseil` に依存していますが自動でこれらもビルドしてくれます。

以降の作業のため、
vcpkgをcloneしたフォルダに対して環境変数 `VCPKG_DIR` を付与しています。

# protoc でジェネレート

`protoc.exe` と `grpc_cpp_plugin.exe` を手に入れる必要があるのですが、`%VCPKG_DIR%\packages` にあります。

`$env:VCPKG_DIR\packages\protobuf_x64-windows\tools\protobuf\protoc.exe`
`$env:VCPKG_DIR\packages\grpc_x64-windows\tools\grpc\grpc_cpp_plugin.exe`

vscodeのタスク的には、以下のような感じに。

```json:.vscode/tasks.json
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "protoc",
            "type": "shell",
            "command": "${env:VCPKG_DIR}/packages/protobuf_x64-windows/tools/protobuf/protoc.exe",
            "args": [
                "protos/route_guide.proto",
                "--cpp_out=."
            ],
            "problemMatcher": []
        },
        {
            "label": "protoc.grpc",
            "type": "shell",
            "command": "${env:VCPKG_DIR}/packages/protobuf_x64-windows/tools/protobuf/protoc.exe",
            "args": [
                "protos/route_guide.proto",
                "--plugin=protoc-gen-grpc=${env:VCPKG_DIR}/packages/grpc_x64-windows/tools/grpc/grpc_cpp_plugin.exe",
                "--grpc_out=."
            ],
            "problemMatcher": []
        },
    ]
}
```

# cmake でビルド

いくつか問題がありました。

## find_package 失敗

```cmake
find_package(gRPC CONFIG REQUIRED)
```

が失敗する。
cmake 実行時に以下のコマンドラインを追加してやれば見つけられるので、

```
-DCMAKE_PREFIX_PATH=${env:VCPKG_DIR}/installed/x64-windows
```

vscode 的には以下のようにします。

```json:.vscode/settings.json
{
    "cmake.configureArgs": [
        "-DCMAKE_PREFIX_PATH=${env:VCPKG_DIR}/installed/x64-windows"
    ],
}
```

```cmake
# client
set(TARGET_NAME client)
add_executable(${TARGET_NAME}
    route_guide_client.cc
    helper.cc
    protos/route_guide.grpc.pb.cc
    protos/route_guide.pb.cc    
    )
target_link_libraries(${TARGET_NAME} 
PRIVATE 
    gRPC::grpc++ # find_package の結果を使う
    )
```

## _WIN32_WINNT の要求

`Please compile grpc with _WIN32_WINNT of at least 0x600 (aka Windows Vista)`

`#include <Windows.h>` 等で定義されるのですが protobuf の生成コードに手を入れるのは避けたいので、外から決め打ちで定義します。

```cmake:CMakeLists.txt
target_compile_definitions(${TARGET_NAME}
PRIVATE
    "_WIN32_WINNT=0x0A00"
    )
```

## debugビルドの依存するdllに debug と release が混在する
vcpkg の cmake が `libprotobufd.dll` にリンクします。
こんな感じで両方にパスを通します。

```json:.vscode/launch.json
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "client",
            "type": "cppvsdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/client.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [
                {
                    "name": "PATH",
                    "value": "${env:VCPKG_DIR}\\installed\\x64-windows\\bin;${env:VCPKG_DIR}\\installed\\x64-windows\\debug\\bin;${env:PATH}" // debug/release
                }
            ],
            "externalConsole": false
        },
        {
            "name": "server",
            "type": "cppvsdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/server.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [
                {
                    "name": "PATH",
                    "value": "${env:VCPKG_DIR}\\installed\\x64-windows\\bin;${env:VCPKG_DIR}\\installed\\x64-windows\\debug\\bin;${env:PATH}" // debug/release
                }
            ],
            "externalConsole": false
        },
    ]
}
```

以上で動きました。
冒頭のプロジェクトに実験内容が入っています。

[C++ Quick Start](https://grpc.io/docs/quickstart/cpp/) に Linux と macOS しかなくて Windows 大変そうだなと思ったのだけど、 VCPKG でわりとなんとかなる。