【複数ファイル対応版】VSCode+WSL2+Cmake+Clang+LLDBでWindows10にC/C++開発環境を構築する

# この記事の目的
- WSL とか Linux とかは詳しくなくても、とりあえず C/C++ のビルド＆デバッグ環境を作る。
- 開発環境を仮想マシン内に構築することで、ローカル環境に依存しない環境を作る。

# 前提条件
- Windows10 に VSCode がインストール済み

- x64 システムの場合
Windows10 Version 1903 以降 / Build 18362 以上

- ARM64 システムの場合
Windows10 Version 2004 以降 / Build 19041 以上

# VSCode 拡張機能 : Remote Development のインストール

まずは今回の要ともいうべき拡張機能 [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) をインストールしておきましょう。この拡張機能は、下記 3 つの拡張機能をパッケージにしたものです。

- [Remote - WSL](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl)
- [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
- [Remote - SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh)

インストールする拡張機能は最小限にしたい！という方は、[Remote - WSL](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl) だけインストールしておけば大丈夫です。

# WSL2 の利用準備

## CPU 仮想化が有効になっていることを確認

[ タスクマネージャー ] > [ パフォーマンス ] の [ CPU ] 項目を開き、仮想化（下図の赤枠部分）が **有効** になっていることを確認。有効になっていない場合は [CPU仮想化の確認 ( Windows10 )](https://dwapp.top/environment/virtualization/817) を参考に設定を変更しておきましょう。
![2021-11-06_185819.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/91dcd366-6ca0-c4df-b205-b4ae83f11598.png)

## WSL ( Windows Subsystem for Linux ) の有効化
**Windows PowerShell ( 管理者 )** を開き、下記コマンドを実行。

```PowerShell:PowerShell
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
```

## VMP ( Virtual Machine Platform ) の有効化
**Windows PowerShell ( 管理者 )** を開き、下記コマンドを実行。

```PowerShell:PowerShell
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
```

## Linux カーネル更新プログラムのインストール

- x64 システムの場合
[wsl_update_x64.msi](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi) をインストール

- ARM64 システムの場合
[wsl_update_arm64.msi](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_arm64.msi) をインストール

## WSL の規定値を WSL2 に設定
**Windows PowerShell ( 管理者 )** を開き、下記コマンドを実行。

```PowerShell:PowerShell
wsl --set-default-version 2
```

# Linux 上に開発環境を構築

## インストール
[Ubuntu 20.04 LTS ( Microsoft Store )](https://www.microsoft.com/store/apps/9n6svws3rx71) を開き、「入手」ボタンをクリックしてインストール。
他のディストリビューションを使用したい場合は、Microsoft 公式の [選択した Linux ディストリビューションをインストールする](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10#step-6---install-your-linux-distribution-of-choice) を参照してください。
![2021-05-13_013532.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/74812ef6-3b9c-c0a8-03dd-9c1fc403bef7.jpeg)

## 起動
スタートメニューから **Ubuntu 20.04 LTS** を探して起動します。初回起動時のみユーザーの作成が求められるので、画面の指示に従って「ユーザー名」と「パスワード」を設定してください。
ここで作成するユーザーは、Windows のユーザーと一致させる必要はありません。

```console:Linux
Installing, this may take a few minutes...
Please create a default UNIX user account. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: slangsoft
New password:
Retype new password:
passwd: password updated successfully
```

## システムアップデート
Linux システムを最新にするため、以下のコマンドを順に実行。パスワードの入力を求められるので、ユーザー作成時に設定したパスワードを入力してください。
プロキシ環境下の場合は、事前に [Ubuntu 20.04 LTS のプロキシ設定まとめ](https://compass-note.hatenablog.com/entry/ubuntu2004LTS-proxy) を参考に設定しておきましょう。

```console:Linux
sudo apt update
```

```console:Linux
sudo apt upgrade -y
```

## 各種パッケージのインストール

必要なパッケージをまとめてインストールします。

```console:Linux
sudo apt install cmake clang lldb llvm-dev liblldb-dev -y
```
```Ubuntu``` の ```lldb``` パッケージには ```lldb-mi``` が入っておらず、無効なエイリアスだけが残っているらしい。
ということで、一旦、無効なエイリアスを削除しておく。

```console:Linux
sudo rm -f /usr/bin/lldb-mi
```
```lldb-server``` の起動に失敗する問題に対処するため、エイリアスを作成しておく。

```console:Linux
sudo ln -s /usr/bin/lldb-server-10 /usr/bin/lldb-server-10.0.0
```
```Ubuntu``` 用の ```lldb-mi``` はバイナリが提供されていないため、自力でソースからビルドします。

```console:Linux
git clone https://github.com/lldb-tools/lldb-mi.git
```
```console:Linux
cd lldb-mi
```
```console:Linux
cmake .
```
```console:Linux
cmake --build .
```
```console:Linux
sudo cp src/lldb-mi /usr/bin/
```
```console:Linux
cd ..
```

## Linux 上にプロジェクト用ディレクトリを作成
ここでは便宜的に ```TestProject``` ディレクトリをホームディレクトリ直下に作成しています。

```console:Linux
mkdir TestProject
```

## VSCode を起動
カレントディレクトリを TestProject に変更。

```console:Linux
cd TestProject
```

VSCode を起動。
以下のコマンドは Linux 上で実行しますが、VSCode は Windows10 側で起動します。

```:Linux
# VSCode Stable 版 ( 通常版 ) を利用する場合
code .
# VSCode insiders 版 ( プレビュー版 ) を利用する場合
code-insiders .
```

初回起動時は ```VS Code Server``` のインストールプロセスが走るため、少しだけ時間がかかります。

```console:Linux
Installing VS Code Server for x64 (e713fe9b05fc24facbec8f34fb1017133858842b)
Downloading: 100%
Unpacking: 100%
Unpacked 1952 files and folders to /home/slangsoft/.vscode-server/bin/e713fe9b05fc24facbec8f34fb1017133858842b.
```

```VS Code Server``` のインストールが完了すると、Windows10 側で VSCode が起動します。起動した VSCode の左下に ```WSL: Ubuntu-20.04``` という表示が出ていることを確認しておきましょう。
![2021-05-14_004644.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/007058c3-5a26-5470-70ce-0043dae6c1f3.jpeg)

Linux 側での操作は以上となりますので、ターミナルウィンドウは「×」ボタンで閉じても問題ありません。

# C/C++ 開発に必要な VSCode 拡張機能のインストール
ここでは以下の拡張機能をインストールします。

- [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)
- [CMake](https://marketplace.visualstudio.com/items?itemName=twxs.cmake)
- [CMake Tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools)
- [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)

拡張機能は Linux 側にインストールします。

Linux 側にインストールするには、いつもの ```Install``` ボタンではなく、```Install in WSL:<Distribution Name>``` ボタンをクリックするだけです。
![2021-05-14_010828.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/ab533b28-cd26-e452-11a3-e5abe7d305d5.jpeg)

# c_cpp_properties.json の作成
```Ctrl+Shift+P``` でコマンドパレットを開き、```C/C++: Edit Configurations (JSON)``` を実行します。
![2021-06-06 022439.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/7267d339-eba5-a110-29ec-cdaf9e2c4216.png)
```c_cpp_properties.json``` が自動生成されます。
修正は必要ありませんので、そのまま閉じておきましょう。

```json:c_cpp_properties.json
{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/clang",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "linux-clang-x64",
            "configurationProvider": "ms-vscode.cmake-tools"
        }
    ],
    "version": 4
}
```

# CMake プロジェクトの作成

```Ctrl+Shift+P``` でコマンドパレットを開き、```CMake: Quick Start``` を実行
![2021-05-23 211318.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/70b5c34f-089c-9819-d991-08f3e7884610.png)
コンパイラは ```Clang``` を選択
![2021-05-23 211319.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/8df3bcab-1515-7c41-fcc4-777fc049f470.png)
プロジェクト名 ( 好きな名前でOK ) を入力
![2021-05-23 211709.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/d5a3e45f-3cf7-984a-e6fa-dcede4a48457.png)
生成対象は ```Executable``` を選択
![2021-05-23 212554.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/b2be3603-118c-ae7c-59f9-330b723ae195.png)

これで CMake プロジェクトの生成は完了です。
プロジェクトが以下の様な構成になっていることを確認しておきましょう。

```console
[\\wsl$\Ubuntu-20.04\TestProject]
  ├─ [.vscode]
  ├─ [build]
  ├─ CMakeLists.txt
  └─ main.cpp
````

# 動作確認用プログラムの作成

簡単な加減算プログラムを準備します。
ディレクトリ構成は、複数の SWC ( ソフトウェアコンポーネント ) が連携するソフトウェアを意識した構成にしています。
```main.cpp``` ファイルは不要なので削除しておきましょう。

```diff
[\\wsl$\Ubuntu-20.04\TestProject]
  ├─ [.vscode]
  ├─ [build]
+ ├─ [swc]
+ │    ├─ [swc_addition]
+ │    │    ├─ [inc]
+ │    │    │    └─ swc_addition.h
+ │    │    └─ [src]
+ │    │         └─ swc_addition.c
+ │    └─ [swc_subtraction]
+ │         ├─ [inc]
+ │         │    └─ swc_subtraction.h
+ │         └─ [src]
+ │              └─ swc_subtraction.c
  ├─ CMakeLists.txt
+ ├─ main.c
- └─ main.cpp
````
```c:swc/swc_addition/inc/swc_addition.h
extern int func_addition ( int arg_a, int arg_b );
```
```c:swc/swc_addition/src/swc_addition.c
int func_addition ( int arg_a, int arg_b )
{
	int	result;
	result = arg_a + arg_b;
	return result;
}
```
```c:swc/swc_subtraction/inc/swc_subtraction.h
extern int func_subtraction ( int arg_a, int arg_b );
```
```c:swc/swc_subtraction/src/swc_subtraction.c
int func_subtraction ( int arg_a, int arg_b )
{
	int	result;
	result = arg_a - arg_b;
	return result;
}
```
```c:main.c
#include <stdio.h>
#include "swc/swc_addition/inc/swc_addition.h"
#include "swc/swc_subtraction/inc/swc_subtraction.h"

int main ()
{
	int	val_a, val_b;
	int res_add, res_sub;

	val_a   = 10;
	val_b   = 20;

	res_add = func_addition ( val_a, val_b );
	res_sub = func_subtraction ( val_a, val_b );

	printf ( "Result (addition)    : %d.\n", res_add );
	printf ( "Result (subtraction) : %d.\n", res_sub );

	return 0;
}
```

# ビルド＆動作確認用プログラムの実行

## SWC 用 CMakeLists.txt の新規作成
SWC 毎に CMakeLists.txt を作成し、それらをプロジェクトルートにある CMakeLists.txt で読み込む様に設定します。

```diff
[\\wsl$\Ubuntu-20.04\TestProject]
  ├─ [.vscode]
  ├─ [build]
  ├─ [swc]
  │    ├─ [swc_addition]
  │    │    ├─ [inc]
  │    │    │    └─ swc_addition.h
  │    │    └─ [src]
+ │    │         ├─ CMakeLists.txt
  │    │         └─ swc_addition.c
  │    └─ [swc_subtraction]
  │         ├─ [inc]
  │         │    └─ swc_subtraction.h
  │         └─ [src]
+ │              ├─ CMakeLists.txt
  │              └─ swc_subtraction.c
  ├─ CMakeLists.txt
  └─ main.c
````
```text:swc/swc_addition/src/CMakeLists.txt
# 定数定義
set(SWC_NAME swc_addition)

# ファイルリスト生成
file(
	GLOB
	TARGET_FILES
	RELATIVE
	${CMAKE_CURRENT_SOURCE_DIR}
	*.c
)
# ライブラリ生成
add_library(
	${SWC_NAME}
	SHARED
	${TARGET_FILES}
)
# インクルードディレクトリ指定
target_include_directories(
	${SWC_NAME}
	INTERFACE
	${PROJECT_SOURCE_DIR}/swc/${SWC_NAME}/inc
)
```
```text:swc/swc_subtraction/src/CMakeLists.txt
# 定数定義
set(SWC_NAME swc_subtraction)

# ファイルリスト生成
file(
	GLOB
	TARGET_FILES
	RELATIVE
	${CMAKE_CURRENT_SOURCE_DIR}
	*.c
)
# ライブラリ生成
add_library(
	${SWC_NAME}
	SHARED
	${TARGET_FILES}
)
# インクルードディレクトリ指定
target_include_directories(
	${SWC_NAME}
	INTERFACE
	${PROJECT_SOURCE_DIR}/swc/${SWC_NAME}/inc
)
```

## プロジェクト用 CMakeLists.txt の修正
赤文字部分は削除、緑文字部分を追加します。

```diff:CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0)
project(TestProject VERSION 0.1.0)

include(CTest)
enable_testing()
- add_executable(TestProject main.cpp)
+ # サブディレクトリ登録
+ add_subdirectory(swc/swc_addition/src/)
+ add_subdirectory(swc/swc_subtraction/src/)
+ # 実行ファイル生成
+ add_executable(main.out main.c)
+ target_link_libraries(
+ 	main.out
+ 	swc_addition
+ 	swc_subtraction
+ )

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
```

## ビルドの実行
ステータスバーに表示されている「Build」ボタンをクリックすることでビルドを実行します。
![2021-05-23_215031.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/ba9985de-513c-4577-8e89-971fdc18cdc3.png)
OUTPUT ウィンドウに以下の様な出力が出れば成功です。

```console
[main] Building folder: TestProject 
[build] Starting build
[proc] Executing command: /usr/bin/cmake --build /home/slangsoft/TestProject/build --config Debug --target all -j 10 --
[build] -- Configuring done
[build] -- Generating done
[build] -- Build files have been written to: /home/slangsoft/TestProject/build
[build] [ 66%] Built target swc_subtraction
[build] [ 66%] Built target swc_addition
[build] Scanning dependencies of target main.out
[build] [ 83%] Building C object CMakeFiles/main.out.dir/main.c.o
[build] [100%] Linking C executable main.out
[build] [100%] Built target main.out
[build] Build finished with exit code 0
```

## 動作確認用プログラムの実行

ステータスバーに表示されている「Launch」ボタンをクリックすることでプログラムを実行します。
![2021-06-05_173215.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/e2880981-51ae-8b9e-e0d1-3d48c67ca6e9.png)
TERMINAL ウィンドウに以下の様な出力が出れば成功です。

```console
slangsoft@DELL-PC:~/TestProject/build$ /home/slangsoft/TestProject/build/main.out 
Result (addition)    : 30.
Result (subtraction) : -10.
```

# デバッグ

## launch.json ファイルの新規作成

アクティビティバーから ```Run and Debug``` を開き、```create a launch.json file``` をクリックします。
![2021-06-05_174910.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/c4be4564-ca3c-d29f-21b0-d677ff1066c4.png)
環境は ```LLDB``` を選択
![2021-06-05 175842.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/97ca8028-b560-92d2-9e1b-df7aee050e26.png)
## launch.json ファイルの修正

```diff:.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": [
		{
			"type": "lldb",
			"request": "launch",
			"name": "Debug",
-			"program": "${workspaceFolder}/<your program>",
+			"program": "${command:cmake.launchTargetPath}",
+			"console": "integratedTerminal",
			"args": [],
			"cwd": "${workspaceFolder}"
		}
	]
}
```

## settings.json ファイルの新規作成
```.vscode``` フォルダ直下に ```settings.json``` を新規に作成し、以下の内容を貼り付けて保存します。

```json:.vscode/settings.json
{
	"cmake.debugConfig": {
		"stopAtEntry": false,
		"MIMode": "lldb",
		"miDebuggerPath": "/usr/bin/lldb-mi",
		"logging": {
			"trace": true,
			"engineLogging": true,
			"traceResponse": true
		}
	}
}
```

## デバッグ実行
デバッグ実行そのものは一般的な IDE と同じ操作感で行うことができます。以下では ```swc_subtraction.c``` の 4 行目にブレークポイントを設定しています。
![2021-07-04 223925.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/29bee4a4-c151-a8fd-0abc-af793b684e97.png)
最適化方法を指定するため、下図の赤枠部分をクリックします。 
![2021-07-04 223926.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/553241d0-ada9-57f0-722d-38c1b74a206d.png)
デバッグを行う際は ```Debug``` を選択します。
![2021-07-04 223927.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/dca4318c-8159-20e7-e6c2-83bbde851767.png)
デバッグの実行は、下図の赤枠部分をクリックするだけです。
![2021-07-04_223705.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/fc005b7c-afac-a166-0f1e-c604fc574c8f.png)
ちゃんとブレークポイントで停止しました。
![2021-07-04_225804.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/54c629a1-5fb2-0552-fc4e-1ead869831a9.png)

# 関連リンク
- [Windows 10 用 Windows Subsystem for Linux のインストール ガイド](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10)

# 参考サイト様
- [[ WSL/WSL2 ] VSCode×WSL で Windows 上に Linux 開発環境を構築](https://qiita.com/_masa_u/items/d3c1fa7898b0783bc3ed)
- [Windows 10 で Linux を使う ( WSL2 )](https://qiita.com/whim0321/items/ed76b490daaec152dc69)
- [個人的 VSCode 上での C++ 開発環境](https://qiita.com/np_hsgw/items/ffb4360fc8dcfa9e33f5)
- [[ C++/Mac ] C++をVisual Studio Code で書きたい](https://jumble-note.blogspot.com/2019/05/cmac-cvisual-studio-code.html)
- [Vscode-cpptools: Linux での Clang と LLDB の公式サポート](https://bleepcoder.com/ja/vscode-cpptools/613032389/official-support-for-clang-and-lldb-on-linux)
- [CPU仮想化の確認 ( Windows10 )](https://dwapp.top/environment/virtualization/817)