Visual Studio 2022 を使用して C++ のプロジェクトを CMake で作成する方法を紹介しています。今回は、UTF-8 のプロジェクトを作る際の手続き(コンパイルオプション・マニフェスト・コードページの切り替え)を一つにまとめてライブラリ化し、CMake の find_package() から参照できるようにする方法を報告します。プロジェクトにマニフェストファイルを用意してターゲットに追加する手間が軽減されます。
ライブラリの要件
https://qiita.com/kkoba775/items/3acfe243048266834722 でまとめたように、Visual Studio で UTF-8 を使ったプログラムを使う際には
- コンパイルオプションに
/utf-8
をつける。 - Active Code Page を UTF8 にするための manifest ファイルをプロジェクトに追加する。
- コンソールの出力文字コードを
SetConsoleOutputCP()
で変更する。
ことが有効です。これらを target_link_libraries() とヘッダファイルのインクルードだけで達成できるライブラリを作成します。
環境
- 開発環境として、Visual Studio 2022(Community)の「C++デスクトップ環境」がインストールされていること。
- CMake (最新版を推奨)がインストールされ、コマンドラインから cmake が実行できること。1
- 環境変数の設定ができること。2
- コマンドラインでの作業には「Developer Command Prompt for VS 2022」を使用すること。3
ディレクトリ構成
この記事では、ライブラリとそのソースは c:\dev にいれることにします。これは任意の場所に変更することができます。
dev/
├── utf8cp
├── include
├── lib
├── manifest
├── make
├── utf8cp
├── build
- ライブラリを作るための CMakeLists.txt は c:\dev\make\utf8cp に用意します。
- c:\dev\utf8cp にビルドしたライブラリがインストールされます。
- インストール後、 c:\dev\make\utf8cp\build は削除できます。
ライブラリ utf8cp の作成
ディレクトリ C:\dev\make
がなければ作成し、Developer Command Prompt for VS 2022 で以下を実行する。
> cd \dev\make
> md utf8cp
> cd utf8cp
c:\dev\make\utf8cp に、utf8console.hpp, utf8api.manifest, CMakeLists.txt をそれぞれ次の内容で作成する。(Visual Studio Code をインストール済みなら > code .
で作業を始めると良い。)
#pragma once
#include <windows.h>
#include <exception>
#ifndef __cpp_inline_variables
#error "C++17 is required for inline static varialbles."
#endif
namespace automatic_utf8 {
struct chcp_utf8 {
inline static UINT old_ = 0;
chcp_utf8() noexcept {
UINT cp = GetConsoleOutputCP();
if (cp != 0 && cp != CP_UTF8) {
old_ = cp;
SetConsoleOutputCP(CP_UTF8);
std::set_terminate(restore);
}
}
~chcp_utf8() noexcept {
restore();
}
static void restore() noexcept {
UINT cp = old_;
if (cp != 0 && cp != CP_UTF8) {
SetConsoleOutputCP(cp);
old_ = 0;
}
}
};
struct automatic_chcp_utf8 {
inline static chcp_utf8 chcp_;
};
}
- Visual Studio はデフォルト(
/Zc:__cplusplus
がない場合)では__cplusplus
マクロによるバージョンチェックができないので、代わりに機能テストマクロを使った。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity type="win32" name="..." version="6.0.0.0"/>
<application>
<windowsSettings>
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
</windowsSettings>
</application>
</assembly>
cmake_minimum_required(VERSION 3.15)
set(CMAKE_CXX_STANDARD 17)
project(lib_utf8cp VERSION 0.1.0
DESCRIPTION "Active Code Page UTF-8" LANGUAGES CXX)
add_library(utf8cp INTERFACE)
target_compile_options(utf8cp INTERFACE "/utf-8")
target_sources(utf8cp INTERFACE
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/utf8api.manifest>
$<INSTALL_INTERFACE:manifest/utf8api.manifest>
)
target_include_directories(utf8cp INTERFACE
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
install(TARGETS utf8cp
EXPORT utf8cp-config
)
install(EXPORT utf8cp-config
NAMESPACE utf8cp::
DESTINATION lib/cmake/utf8cp
)
install(FILES
${CMAKE_SOURCE_DIR}/utf8console.hpp
DESTINATION include
)
install(FILES
${CMAKE_SOURCE_DIR}/utf8api.manifest
DESTINATION manifest
)
Developer Command Prompt for VS 2022 でライブラリのインストールを行う。
> cd \dev\make\utf8cp
> md build
> cd build
> cmake -DCMAKE_INSTALL_PREFIX="c:\dev\utf8cp" ..
> cmake --build . --target INSTALL
環境変数の設定
次のうちいずれかを行う。上にある設定が優先される。
- 環境変数
utf8cp_DIR
にc:\dev\utf8cp\lib\cmake\utf8cp
もしくはc:\dev
を設定する。 - 環境変数
CMAKE_PREFIX_PATH
にc:\dev
を設定する。 - 環境変数
Path
にc:\dev\bin
を追加する。
使い方
簡単な例で使い方を説明する。作業用の適当なディレクトリを用意して、以下の内容で main.cpp
と CMakeLists.txt
を作成する。main.cpp
は文字コードを UTF-8 にして保存する。
#include <filesystem>
#include <iostream>
#include <fstream>
#include <string>
#include <utf8console.hpp>
int main() {
std::cout << "数値以外の入力で例外が発生" << std::endl;
std::string s;
std::cin >> s;
int a = std::stoi(s);
std::filesystem::path fn = "結果";
std::filesystem::create_directory(fn);
fn = fn / "数値.txt";
std::ofstream fo(fn);
fo << "入力値 " << a << std::endl;
std::cout << "正常終了" << std::endl;
return 0;
}
- 別に
utf8console.cpp
を用意して、そちらで#include <utf8console.hpp>
としても良い。 - 同一ターゲットの複数のソースファイルで
#include <utf8console.hpp>
としても問題ない。 - コンパイルには C++17 以上の指定が必要。
cmake_minimum_required(VERSION 3.15)
set(CMAKE_CXX_STANDARD 17)
project(test_cp CXX)
find_package(utf8cp REQUIRED)
add_executable(main main.cpp)
target_link_libraries(main utf8cp::utf8cp)
Developer Command Prompt から
> md build
> cd build
> cmake ..
とすることで Visual Studio のプロジェクトである build\main.vcxproj
とソリューションである build\test_cp.sln
が作成される。いずれかを Visual Studio で開くことで IDE を用いた開発ができる。あるいは IDE を使わずに、コマンドラインから
> cmake --build . --config Release
> Release\main.exe
数値以外の入力で例外が発生
775
正常終了
としてコンパイル・実行することもできる。実行を行ったディレクトリに、新しく"結果"ディレクトリが作られ、"数値.txt" に入力した数値が書き込まれる。数値以外を入力すると途中で停止するが、文字コードはもとに戻る。
> chcp
現在のコード ページ: 932
> type 結果\数値.txt
蜈・蜉帛、 775
> Release\main.exe
数値以外の入力で例外が発生
s
> chcp
現在のコード ページ: 932
参考にしたサイト
-
https://cmake.org/ にある Latest Release の Windows x64 Installer を実行して 「Add CMake to the system PATH for all users」にチェックを入れてインストールする。 ↩
-
環境変数は、設定の「システム」>「バージョン情報」>「システムの詳細設定」から変更できます。
> set
で環境変数の一覧が見れるので、設定が反映されていない場合には一旦 Windows からサインアウトしてサインインし直してください。 ↩ -
スタートメニューの「Visual Studio 2022」フォルダ内にショートカットがあります。「ターミナル」の設定を変更し、「既定のプロファイル」に「Developer Command Prompt for VS 2022」を登録しておくと、エクスプローラーで作業するディレクトリを開き、コンテキストメニューから「ターミナルで開く」ことができて便利です。 ↩