お手軽Windowsアプリ開発(C/C++ネイティブ編)
Visual Studio Code(以下VSCode)でサクサクWindowsアプリの開発をしようという試み、今回はC/C++でネイティブアプリをやってみます。
意外とMSのコンパイラを使用する事例が見当たらなかったので、張り切って紹介しようと思います。
なお、開発環境の構築は別の記事で説明しておりますので、そちらで準備を整えておいてください。
下準備
作業フォルダとして、今回は「cpptest」というフォルダで作業する前提で話を進めます。
VSCodeを起動し、メニューの「ファイル」→「フォルダーを開く」で、あらかじめ作成しておいた「cpptest」フォルダを開きます。
ターミナルも出しておきましょう。メニューの「ターミナル」→「新しいターミナル」です。
スケルトン生成
C/C++の場合はC#と違って一発でスケルトンを生成してくれるコマンドとかは無いので、自力でこしらえます。
「main.cpp」と「cpptest.vcxproj」を新規作成して、それぞれコードを書いていきます。
■main.cpp
#include <windows.h>
#include <tchar.h>
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd) {
::MessageBox(nullptr, _T("ほげー"), _T("慟哭"), MB_OK);
return 0;
}
■cpptest.vcxproj
<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.default.props"/>
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
<CharacterSet>Unicode</CharacterSet>
<IntermediateOutputPath>obj\$(Configuration)\$(Platform)\</IntermediateOutputPath>
<OutDir>bin\$(Configuration)\$(Platform)\</OutDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="*.cpp"/>
</ItemGroup>
<ItemGroup>
<ClInclude Include="*.h"/>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="*.rc"/>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Targets"/>
</Project>
スケルトンの説明
- main.cpp
何のことはない、メッセージボックスを表示するだけのコードです。
GUIアプリなので「windows.h」をincludeして、エントリーポイントはWinMain関数にしてます。なおかつ、Unicodeとマルチバイト両対応にするため、「tchar.h」をincludeして、WinMainを_tWinMainにしているというわけです。 - cpptest.vcxproj
C/C++版のプロジェクトファイルです。ほぼおまじないだと思ってください。てかスケルトンなのに長え。
1行目、<Project>タグの中の属性「ToolsVersion="16.0"」は、MSBuildのバージョンになります。
序盤の<ItemGroup>の中身は本来VSが使う設定なのですが、記述しておかないとビルド時に怒られます。
最初の<Import>タグ、おまじないです。ここと次の<Import>の間にプロジェクトのプロパティを入れていきます。
「ConfigurationType」は生成物の種類で、「Application」でexeが出来ます。DLLを作る場合は「DynamicLibrary」、LIB(静的ライブラリー)を作る場合は「StaticLibrary」にします。
「PlatformToolset」はビルドツールのバージョンです。
「WindowsTargetPlatformVersion」はWindows SDKのバージョン。
「CharacterSet」は特に理由が無い限り「Unicode」で良いと思いますが、マルチバイトにしたい場合は「MultiByte」となります。
「IntermediateOutputPath」は中間生成物の出力先で、これをしておかないとexeと同じフォルダにぶちまけられてしまいます。
「OutDir」は最終生成物の出力先です。
2回目の<Import>もおまじないです。ここ以降に、コンパイラやリンカの設定を記述していきます。
<ItemDefinitionGroup>タグは全体的な設定になります。が、今回Release時のみ設定するので、Condition属性で条件を絞っています。
コンパイラの設定、「RuntimeLibrary」はランタイムをどうするかで、「MultiThreaded」にするとVCランタイムをexeに含みます。ランタイムを別にしたい場合はここを「MultiThreadedDLL」にします。
次にリンカの設定、「GenerateDebugInformation」を「false」にすることで、exeにデバッグ情報を含めないようにします。
次の<ItemGroup>、本来は<ClCompile>でコンパイル対象のファイル名を列挙していくのですが、ワイルドカードが指定出来るので、1行でフォルダ内のcppまるごと指定できます。
同様に<ClInclude>でヘッダーファイルも列挙しますが、こちらもワイルドカードでいっぺんに指定しています。
<ResourceCompile>はリソーススクリプトです。リソースは大体1個なのでワイルドカードにしなくても良いかもしれませんが、ファイル名書き換えるのが面倒というものぐさな方はこのままでも良いでしょう。
そして最後に3つ目の<Import>タグ(おまじない)で締める感じになります。
デバッグ
デバッグ情報を作成します。環境の選択では「C++(Windows)」を選びます。これで「launch.json」は生成されますが、「tasks.json」は生成されません。メニューの「ターミナル」→「タスクの構成」と進み「テンプレートから tasks.json を生成」「MSBuild」を選択していき、「tasks.json」を作っておきます。
まずは「tasks.json」から。「command」のところに最初は「msbuild」とだけ入っていますが、ここはフルパスで「C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/MSBuild/Current/Bin/MSBuild.exe」に変更しておきましょう。なお区切りが¥マーク(もしくはバックスラッシュ)ではなく普通のスラッシュになっていますがこれでも大丈夫です。むしろ変にエスケープされたりとかが無くて安心です。
■tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/MSBuild/Current/Bin/MSBuild.exe",
"args": [
// Ask msbuild to generate full paths for file names.
"/property:GenerateFullPaths=true",
"/t:build",
// Do not generate summary otherwise it leads to duplicate errors in Problems panel
"/consoleloggerparameters:NoSummary"
],
"group": "build",
"presentation": {
// Reveal the output only if unrecognized errors occur.
"reveal": "silent"
},
// Use the standard MS compiler pattern to detect errors, warnings and infos
"problemMatcher": "$msCompile"
}
]
}
次に「launch.json」です。まずは「configurations」の中の項目のどこかに「"preLaunchTask": "build",」を追加します。実行する前にビルドしておくということですね。
そして「program」のところはデバッグ対象の実行ファイル名、具体的には「${workspaceFolder}/bin/Debug/Win32/cpptest.exe」としておきます。
最後に「console」のところですが、ここは最初「externalTerminal」が入っています。これはデバッグ時に別途コマンドプロンプトが立ち上がる設定で、コンソールアプリでは便利ですが今回はGUIアプリなので不要です。「internalConsole」に変更してしまいましょう。
■launch.json
{
// IntelliSense を使用して利用可能な属性を学べます。
// 既存の属性の説明をホバーして表示します。
// 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(Windows) 起動",
"type": "cppvsdbg",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/Win32/cpptest.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"console": "internalConsole"
}
]
}
F5キーを押すか、メニューの「実行」→「デバッグの開始」で、ビルドされたのちアプリが起動したら成功です。
ビルド
ビルドは「MSBuild.exe」で行います。ターミナルに次のコマンドを入れてください。
& "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe" /p:Configuration=Release /p:Platform=Win32
クリーンの時は「/t:clean」を追加、リビルドの時は「/t:rebuild」を追加します。デフォルトでは「/t:build」つまり通常のビルドになります。
ビルドが終わると cpptest¥bin¥Release¥Win32 に「cpptest.exe」が出来ていると思います。実行してみましょう。