vcpkg+cmakeでC++開発環境を整える
初めに
C++のプロジェクトを作る度にゴミみたいなC++の環境設定に悩まされていました。GLFWみたいなバイナリを使うのが楽だけどあんまgitに入れたくない、でもビルドはやりたくない面倒くさい外部ライブラリを組み込む際はかなり悩みます。
最近またプロジェクトを作ることにしたのでいつも通り環境でう~んと悩んでいましたが、(どなただったか覚えてないんですが)以前にvcpkgというC++パッケージマネージャが良いと教えられたのを思い出しました。
それで今回試しにやってみたところ、悩みの種だった外部ライブラリの管理がとてもシンプルになり、とても良い開発体験になりました。
今回の記事はその備忘録も兼ねて、簡単なサンプルプロジェクトの例でvcpkgの環境構築について解説していこうと思います。
vcpkgとは
Microsoftが提供しているオープンソースのC++向けパッケージマネージャーです。
vcpkgのチュートリアルは以下にあります。今回の記事はこのチュートリアルを基づいて解説します。
vcpkgのインストール
まずはvcpkgをGitHubから任意の場所にcloneします。
git clone https://github.com/microsoft/vcpkg.git
中身としてはこんな感じです
これがパッケージマネージャーの本体となりますので、認識されるように色々と設定をしていきます。最初にやることはbootstrap-vcpkg.bat
というbatファイルの実行です。これは環境チェックをしたうえで、vcpkgの実行ファイルのインストールをするものです。
実行後はこんな感じでexe
ファイルの他にも様々なファイルがインストールされます
vcpkgは基本的にこれらの実行ファイルを使って操作していきます。
ただし、環境パスは自動的に設定されるわけではないので、実用上は手動でVCPKG_ROOT
とPATH
の二つの環境設定をしておくと便利です。これらはvcpkgのパスを通してあげればOKです(Pathは追加する形で)。私はC:\vcpkg\vcpkg
にあるのでこんな感じに設定しています。
めんどくさかったら以下のPower Shellコマンドを設定すると楽です(PowerShellのコマンドって怖いので自己責任でお願いします)。hoge/vcpkg
の部分を自分のvcpkgのパスに置き換えて貰えればOKです。
[Environment]::SetEnvironmentVariable("VCPKG_ROOT", "C:\hoge\vcpkg", "User")
[Environment]::SetEnvironmentVariable("PATH", "C:\hoge\vcpkg;" + [Environment]::GetEnvironmentVariable("PATH", "User"), "User")
これでvcpkgのセットアップは終了です。他の場所でvcpkg
コマンドを打ってusageが出れば上手くいっています。もし出なかったら環境パスのチェックをお勧めします。
vcpkg
vcpkgとcmakeでプロジェクトを作る
ここからはプロジェクト制作に入ります。今回は最もミニマルな構成のプロジェクトにGLFWとglmを導入するという例で解説していこうと思います。
project/
├── src/
└── main.cpp
vcpkgはプロジェクト単位でパッケージの管理を行います。vcpkgの環境設定はパッケージの設定ファイルであるマニフェストファイルを作成し、必要なパッケージ名を記述、それをもとにインストールするというような流れで行われます。
まず最初にやることはマニフェストファイルの作成です。プロジェクトフォルダで以下のコマンドを実行するとマニフェストファイルとなるvcpkg.json
が生成されます(+vcpkgのコンフィグファイル)。
vcpkg new --application
project/
├── vcpkg.json // マニフェストファイル
├── vcpkg-configuration.json
└── src/
└── main.cpp
次はこのvcpkg.json
にパッケージを記述し、依存関係を記載します。パッケージ名
vcpkg add port hoge
今回はGLFWとglmを入れます。それぞれのコマンドは以下のような感じです。
vcpkg add port glfw3
vcpkg add port glm
これをするとvcpkg.json
にはdependenciesという項目が追加され、GLFWとglmが追加されていることが確認できます。
{
"dependencies": [
"glfw3",
"glm"
]
}
これをもとにパッケージのインストールを次のコマンドで行います。
vcpkg install
インストールが成功するとvcpkg_installed
というフォルダにパッケージのデータが生成されます。基本的には開発するPCのプラットフォーム環境でのデータがインストールされます(プラットフォームを指定する場合はトリプレットで指定できるらしいのですがここでは割愛)。
project/
├── vcpkg.json
├── vcpkg-configuration.json
├── vcpkg_installed/ # ← vcpkg が自動生成したインストール内容
│ └── x64-windows/
│ ├── include/
│ └── lib/
└── src/
└── main.cpp
cmakeとの連携
ここからはcmakeと連携してプロジェクトを生成してみます。プリセットだとか色々出ますが、ここではcmake自体の解説はしませんのでご了承ください。
CMakeLists.txt
を追加し、以下のように編集します。vcpkgで取得したパッケージはfind_package
を通してcmakeに伝えることができます。後は通常の外部ライブラリと同様のリンクの設定をしてあげれば問題ありません。
cmake_minimum_required(VERSION 3.16)
project(project)
set(CMAKE_CXX_STANDARD 17)
find_package(glfw3 CONFIG REQUIRED)
find_package(glm CONFIG REQUIRED)
add_executable(project src/main.cpp)
target_link_libraries(project PRIVATE glfw glm::glm)
ただし、cmake側が自動的にvcpkgを判別することはないので、cmakeにcvpkgの情報を設定する必要があります。ドキュメントによるとCMAKE_TOOLCHAIN_FILEにvcpkg本体にある/scripts/buildsystems/vcpkg.cmake
というファイルの指定をすればよいとのことです。
これはコマンドでもパスを設定できますが、cmakeのプリセットで書いた方がシンプルにまとまると思います。なのでここでは以下のようなプリセットファイルCMakePresets.json
を用意して実行することにします。
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 16,
"patch": 0
},
"configurePresets": [
{
"name": "default",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
}
}
]
}
最終的なファイル構成はこんな感じです
project/
├── CMakeLists.txt
├── CMakePresets.json
├── vcpkg.json
├── vcpkg-configuration.json
├── vcpkg_installed/
└── src/
└── main.cpp
ビルドとテストコード
ではcmakeのビルドをやってみましょう。defaultプリセットを作ったので次のようなコマンドでcmakeのビルドができるはずです。
cmake --preset default
ビルドがうまく行けばbuild
フォルダが作られてその中にプロジェクトのproject.sln
ファイルが作られているはずです。
ソリューションを開き、project
プロジェクトをスタートアッププロジェクトに設定し、次のようなmain.cpp
でデバッグ実行をしてみてください(コードはVulkan Tutorialからお借りしました)。
// main.cpp
#include <iostream>
#include <glm/glm.hpp>
#include <GLFW/glfw3.h>
int main()
{
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(800, 600, "test", nullptr, nullptr);
glm::mat4 matrix;
glm::vec4 vec;
auto test = matrix * vec;
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
これでエラーなく、ウィンドウが実行できれば成功です。こんな感じでvcpkgを使うと中々面倒くさいGLFWとかを簡単に導入することができます。
終わりに
噂に聞いていたvcpkgを使ってみましたが、環境設定がシンプルになりとても良いなと感じました。やはりパッケージマネージャーがあると色々と楽ですね(nugetとかどうしたんだろう)。今きつかったWindows環境での整備が簡単になりそうですWSL使えばいいんですが。
どこまでパッケージを網羅しているかはちょっと未知数で心配ですが、しばらくはC++の環境設定には困らなさそうで嬉しいです。ぜひ良かったらvcpkgを使ってみてください。
Discussion