VSCode （VSCodium）によるポータブルなC言語開発環境の構築（2020年度版）

# はじめに
一年前にも同様のタイトルで、[VSCode+cpptoolsとMinGW-w64のgccをポータブルにインストールしてC言語開発環境を構築する方法](https://qiita.com/TakekazuKATO/items/5bd51b6fe79b2714484f)を投稿しましたが、今年度は少しだけ環境が変わったので、2020年度版として再投稿します。前年度と同様、ターゲットは初学者のプログラミング演習で学生に配布する開発環境です。軽快で使いやすい一方で、初心者にはインストールや設定が難しいVSCodeの環境をポータブルにして、配布ファイルを好きな場所（USBでも）展開するだけですぐ使える環境を目指します。使用目的に応じてカスタマイズして配布できるように、配布ファイルそのものではなく、構築方法を説明します。

# ポータブル環境の構築
## VSCode(VSCodium)のインストールとポータブルモード
[VSCodium](https://github.com/VSCodium/vscodium)はVSCodeからロゴなどの一部オープンでない部分を差し替えて、完全にオープンソースにしたVSCodeのディストリビューションです。バイナリで再配布するためにVSCodiumを使っていますが、以下の話は本家のVSCodeでも同じです。

releasesを見ると各種OS向けのバイナリやインストーラが揃っています．今回はWindows向けでインストーラのないVSCodium-win32-x64-1.45.1.zipを選びました。これを好きなところに展開します。

ポータブルモードで起動するには展開したフォルダ直下にdataというフォルダを作成しておけば拡張機能や設定ファイルはここから読み込まれるようになり、フォルダごと移動したりUSBメモリに展開しても、そのまま使用できるようになります。プログラムの起動はVSCodium.exeをダブルクリックすればVSCodiumが起動します．
フォルダ構成は以下のようにしておきます．

```
CPrograming/
         |- VSCoduim/      このフォルダ作成しておいて，その下にVSCodiumを展開
                 |- data/  VSCodiumの展開後に，このフォルダを自分で作成する
                 ：
                 └ VSCodium.exe
```     

## gccのインストール
前年度は、mingw-w64版のgccを直接ダウンロード、インストールしたんですが、バージョンが若干古いのと、インストールが面倒なので、今回は[TDM-gcc](https://jmeubank.github.io/tdm-gcc/)を利用しました。これは、最新のgccとmingw-w64の実行環境、gdb、makeをまとめてインストールできます。

TDM-GCCの[ダウンロード](https://jmeubank.github.io/tdm-gcc/download/)のページから、tdm-gcc-webdl.exeをダウンロードして実行します。するとインストーラーが立ち上がるので、「Create」を選び、「MinGW-w64/TDM64 (32-bit and 64-bit)」を選択します。インストールディレクトリを聞かれるので、さきほどのCProgramingディレクトリ以下に適当なディレクトリ（ここではtools）を作って選択し、Nextを押します。「Select the type of Install」は「TDM-GCC Recommended, C/C++」のままで、下のコンポーネント一覧の一番下の「Start Menu Items」と「Add to PATH」のチェックを外します（今回はポータブルなのでスタートメニューとPATHの設定は不要）。最後にInstallボタンを押します。そうすると、必要なパッケージをダウンロードして指定したフォルダ以下にインストールします。
フォルダ構成は次のようになっています．

```
CPrograming/
         |- tools/
         |- VSCoduim/      
                 |- data/  
                 ：
                 └ VSCodium.exe
```

## ショートカットの作成
前年度は、実行時のパスを調べるために起動スクリプトを作成してたんですが、その後の調査でVSCodeの変数のexecPathを利用して実行時パスを指定できることがわかりました（指定方法は、「設定」の章で説明します）。
そこで、今回は起動スクリプトはなくして、代わりに起動用のショートカットを作成しておきます。
```
CPrograming/
         |- mingw64/
         |- VSCoduim/      
                 |- data/  
                 ：
                 └ VSCodium.exe
         └ Start (VSCodium.exeへのショートカット)
```

このStartをダブルクリックすれば開発環境が立ち上がります。

## 拡張機能のインストール
ここでVSCodiumで必要な拡張機能をインストールします．使用した拡張機能は以下のものです．

- C/C++ (ms-vscode.cpptools)
  - コード補完，コード整形
- Japanese Language Pack for Visual Studio Code (ms-ceintl.vscode-language-pack-ja)
  - 日本語パック
- Project Templates (cantonios.project-templates)
  - テンプレートプロジェクトの作成，テンプレートからプロジェクトを作成
- zenkaku (cantonios.project-templates)
  - 全角スペースが見えるようになる
- Command bar (vscode-commandbar)
  - ステータスバーに便利なボタンをつける

前年度は簡易的にコンパイル&実行をするCodeRunnerをインストールしていたんですが、１ソースファイル１プログラムという癖が抜けなくなって、プロジェクトを作成せずに適当な場所にソースファイルを作成する人が続出したため、今年度は簡易実行はやめにして、かならずプロジェクトからmakeでコンパイル&実行してもらうことにしました。代わりにvscode-commandbarでステータスラインにコンパイルのボタンをつけます．

## 設定
VSCodiumの設定をします。設定ファイルは以下にあります。

```
CPrograming/
         |- mingw64/
         |- VSCoduim/      
                 |- data/
                      |- user-data/
                             |- User/
                                   ：
                                   └ settings.json 設定ファイル
                 ：
                 └ VSCodium.exe
         └ Start
```

settings.jsonの中身を以下のようにします．VSCodiumからメニューの設定を選んでもいいですが，上記のsettings.jsonを直接置き換えてもいいです．

```settings.json
{
    "terminal.integrated.env.windows": {
       "PATH": "{$env:Path};${execPath}/../../tools/bin"
    },
    "terminal.integrated.shell.windows": "cmd.exe",
    "terminal.integrated.shellArgs.windows": ["/k","chcp","65001"],
    "files.autoSave": "onFocusChange",
    "editor.renderWhitespace": "all",
    "update.enableWindowsBackgroundUpdates": false,
    "update.mode": "none",
    "update.showReleaseNotes": false,
    "extensions.autoCheckUpdates": false,
    "extensions.autoUpdate": false,
    "workbench.activityBar.visible": false
}
```
主な設定は以下の通り

- terminal.integrated.env.windows ターミナルの環境変数を設定。PATHにVSCodium.exeからの相対パス
でtools/binを指定している
- terminal.integrated.shell, terminal.integrated.shellArgs ターミナルのシェルをcmd.exeにしてUTF8の日本語が使えるように
- editor.renderWhitespace スペースが見えるように
- files.autoSave: セーブし忘れを防ぐためにマウスフォーカスが変わるときに自動保存
- update.enableWindowsBackgroundUpdates VSCodiumの自動アップデートを防ぐ
- extensions.autoCheckUpdates, extensions.autoUpdate 拡張のアップデートチェックや自動アップデートを防ぐ

前年度からの変更点は、PATHの設定にexecPathからの相対パスを使用したところと、VSCodiumや拡張の自動アップデートを止めたところ。人によって自動アップデートを受け入れたりキャンセルしたりでバージョンが揃わなかったりしたので、アップデートは止めておくことにしました。

## テンプレートプロジェクトの作成
プロジェクト作成を簡単にするためにテンプレートプロジェクトを作成します．
Template Projects拡張機能のためのテンプレートプロジェクトを作成します．テンプレートプロジェクトは VSCode/data/user-data/User/ProjectTemplates以下にプロジェクト名のフォルダを作成してそこにテンプレートをおきます．
C Projectというテンプレートを作成するとフォルダ構成は次のようになります．

```
CPrograming/
         |- mingw64/
         |- VSCoduim/      
                 |- data/
                      |- user-data/
                             |- User/
                                   |- ProjectTemplates/
                                         |- C Project/
                                   ：
                                   └ settings.json 設定ファイル
                 ：
                 └ VSCodium.exe
         └ Start
```

このテンプレートの中身はVSCodiumのプロジェクト(フォルダ)そのものです．ここにコンパイル，デバッガ実行などの設定をしておきます．

ProjectTemplates以下は次のようにします．

```
ProjectTemplates/
  |- C Project/
    |- .vscode/
    | |- launch.json
    | └  tasks.json
    |- src/ 
    | └ main.c
    └ Makefile
```

launch.jsonは以下の通り，

```launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/bin/main",
            "preLaunchTask": "build",
            "args": [],
            "stopAtEntry": true,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "gdb",
            "windows": {
                "miDebuggerPath": "${execPath}/../../tools/bin/gdb.exe"
            },
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}
```

注意は miDebuggerPathで指定しているgdb.exeを${execPath}を使ってフルパスで指定しているところ。settings.jsonに書いた環境変数PATHはここでは有効になっていないようで、フルパスで指定しないと動きません。また、preLaunchTaskの設定が次のtasks.jsonのlabelと一致していること．
次にtasks.jsonの中身

```tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "process",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "command": "cmd.exe",
            "args": [
                "/c",
                "mingw32-make"
            ],
            "problemMatcher": [
                "$gcc"
            ]
        },
        {
            "label": "clean",
            "type": "process",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "command": "cmd.exe",
            "args": [
                "/c",
                "mingw32-make clean"
            ],
            "problemMatcher": []
        },
        {
            "label": "build & run",
            "type": "process",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "command": "cmd.exe",
            "args": [
                "/c",
                "chcp 65001 && mingw32-make run"
            ],
            "problemMatcher": [
                "$gcc"
            ]
        }
    ]
}
```

ポイントは、runのところで、cmd.exeから起動するコマンドに chcp 65001を加えているところ。こうするとプログラムにUTF8の日本語で出力が含まれていても文字化けせずに表示できます。

また、Makefileは以下の通り、

```Makefile
# compilers and flags
CC        := gcc
C_FLAGS   := -Wall -pedantic -Wextra -std=c11 -g -O0

LD        := gcc
LD_FLAGS  := 

# folder structure
BIN       := bin
SRC       := src
INCLUDE   := include
BUILD     := build

# update flags
C_FLAGS  := $(C_FLAGS) -I$(INCLUDE)

# program outputs
LIBRARIES   :=
EXECUTABLE  := main

# C sources and dependences
C_SOURCES   := $(wildcard $(SRC)/*.c) 
C_DEPENDS   := $(patsubst $(SRC)/%.c, $(BUILD)/%.c.d, $(C_SOURCES))
C_OBJECTS   := $(patsubst $(SRC)/%.c, $(BUILD)/%.c.o, $(C_SOURCES))

# platform-specific commands and settings
ifeq ($(OS),Windows_NT)
	EXECUTABLE := main.exe
	RM_CALL     = del /Q /F $(subst /,\,$(1)) 2>NUL
	MKDIR_CALL  = if not exist "$(subst /,\,$(1))" mkdir "$(subst /,\,$(1))"
	FIND_CALL   = dir /b/s "$(subst /,\,$(1))"
	PATH_CALL   = $(subst /,\,$(1))
else
	RM_CALL     = rm -rf $(1)
	MKDIR_CALL  = mkdir -p $(1)
	FIND_CALL   = find -L . -name $(1)
	PATH_CALL   = $(1)
endif

# targets
TARGET := $(BIN)/$(EXECUTABLE)

all:  $(TARGET)

deps: $(C_DEPENDS)

rebuild: clean all

run: all
	$(call PATH_CALL,$(TARGET))

clean:
	$(call RM_CALL,$(TARGET) $(C_DEPENDS) $(C_OBJECTS) )

# include dependency rules
-include $(C_DEPENDS)

# build and bin directories
$(BUILD):
	$(call MKDIR_CALL,$@)

$(BIN):
	$(call MKDIR_CALL,$@)

# dependencies
$(BUILD)/%.c.d: $(SRC)/%.c | $(BUILD)
	$(CC) $(C_FLAGS) -MM -MT $(@:.d=.o) $< >> $@

# objects
$(BUILD)/%.c.o: $(SRC)/%.c | $(BUILD)
	$(CC) $(C_FLAGS) -o $@ -c $<

# binary
$(BIN)/$(EXECUTABLE): $(C_OBJECTS) | $(BIN)
	$(LD) $(LD_FLAGS) $(C_OBJECTS) -o $@ $(LIBRARIES)
```

基本的にProjectTemplatesのサンプルにあったMakefileですが、EXECUTABLEをmain.exeにしておかないと（元はmain）cleanでmain.exeが消去されません。

他にもProjectTemplates以下にフォルダを追加して，プロジェクトの雛形を作っておけば複数のテンプレートを使い分けることもできます。

授業では，後半でライブラリを使ってプログラムを書くためにライブラリやヘッダファイルを同梱した雛形を作りました．

## vscode-commandbarの設定
前年度のCodeRunnerでは、実行ボタンがあったので使いやすかったのですが、今回はタスクを実行させる必要があり、なかなか敷居が高いと思ったので、vscode-commandbarを使ってステータスバーにボタンを作ることにしました。vscode-commandbarの設定は、VSCodium/data/extensions/commandbar.jsonです。このファイルに拡張機能の説明に従ってコマンドを記入していきます。

```commandbar.json
{
  "skipTerminateQuickPick": true,
  "skipSwitchToOutput": false,
  "skipErrorMessage": true,
  "commands": [
    {
      "text": "$(file-directory)Open/New Project",
      "tooltip": "Open/New Project Folder",
      "commandType": "palette",
      "command": "workbench.action.addRootFolder",
      "alignment": "left",
      "skipTerminateQuickPick": false,
      "priority": 0
    },
    {
        "text": "$(gear)Init Project",
        "tooltip": "Initialize Project Folder",
        "commandType": "palette",
        "command": "extension.createProjectFromTemplate",
        "alignment": "left",
        "skipTerminateQuickPick": false,
        "priority": 0
      },
      {
        "text": "$(tools)Build",
        "tooltip": "Build Project",
        "commandType": "palette",
        "command": "workbench.action.tasks.runTask|build",
        "alignment": "left",
        "color": "yellow",
        "skipTerminateQuickPick": false,
        "priority": 0
      },
      {
        "text": "$(play)Run",
        "tooltip": "Run Project",
        "commandType": "palette",
        "command": "workbench.action.tasks.runTask|build & run",
        "alignment": "left",
        "color": "yellow",
        "skipTerminateQuickPick": false,
        "priority": 0
      },
      {
        "text": "$(reply)Clean",
        "tooltip": "Clean Project",
        "commandType": "palette",
        "command": "workbench.action.tasks.runTask|clean",
        "alignment": "left",
        "color": "yellow",
        "skipTerminateQuickPick": false,
        "priority": 0
      },
      {
        "text": "$(bug)Debug",
        "tooltip": "Debug Project",
        "commandType": "palette",
        "command": "workbench.action.debug.start",
        "alignment": "left",
        "color": "yellow",
        "skipTerminateQuickPick": false,
        "priority": 0
      }
  ]
}
```

順番に次のコマンドボタンを作成しています。
- Open/New Project プロジェクトフォルダを開き（新規作成も）ワークスペースに加える
- Init Project プロジェクトフォルダをテンプレートから初期化
- Build タスクbuildを実行し、プロジェクトをビルドする
- Run タスクbuild & runを実行し、プロジェクトをビルド後実行する
- Clean タスクcleanを実行し、コンパイル生成物を片付ける
- Debug デバッガを起動する

## マルチフォルダワークスペースの作成
昨年度やってみて、結局みんな思い思いの場所にプロジェクトを作るので、今年度はワークスペースのひな型の準備はやめました。代わりに上のOpen/New Projectボタンを使わせて、ワークスペースに追加させることにします。

## 配布ファイルの作成
配布ファイルの作成は単純にCProgramingをzipなどで圧縮して渡せば，ユーザは圧縮ファイルを好きな場所に展開するだけで使用することができます．

# カスタム環境の使い方
## インストール
カスタム環境を圧縮した配布ファイルをCPrograming.zipとします．インストールはこれを好きな場所に展開するだけです．ただし，展開するパス名に日本語フォルダ名が含まれているとデバッガが正しく動かないので注意が必要です．

また，ユーザが初心者の場合は配布ファイルを単にダブルクリックすると圧縮フォルダで中身が見えるのですが，この状態では使えないので，必ず「全て展開」で展開するように注意しておく必要があります．

## 起動
展開したフォルダの中にある Startをダブルクリックすれば起動します．初回起動時だけはなぜか日本語モードにならないので，そういう時は一度終了してもう一度起動し直します．

## 新しいプロジェクトの作成
ステータスバーのOpen/New Projectボタンをクリックします。出てきた選択ウィンドウで、新規作成の場合は右クリックして「新規作成」「フォルダ」を選んで新しいプロジェクトをフォルダを作成し，そのフォルダを選択して「追加」ボタンをクリックします．

「ワークスペース」のところに今作成したフォルダが表示されます。新規作成した場合は空っぽのフォルダです。

## プロジェクトの初期化
ステータスバーのInit Projectボタンを押すと上部でテンプレートを選択するメニューが表示されているので，好きなテンプレートを選択すると，テンプレートが適用されて設定やMakefile, サンプルのmain.cが作成されます．

## プログラムの編集
プロジェクトの中のsrc/main.cを好きなように編集します．

## プログラムのビルド＆実行
ステータスバーのRunボタンをクリックすると，編集中のプログラムをコンパイル＆実行できます．実行結果はエディタの下にターミナルが現れてここに表示されます．

## プログラムのデバッグ
ステータスバーのDebugをクリックするとデバッガが起動します。事前にブレイクポイントを指定しなくてもmain関数で停止するようになっているので、そのまま実行する場合は再開ボタンを押します。

# 最後に
今年度は新型コロナの影響で開始が遅れているので、このカスタムポータブル環境を使い始めるのはこれからです。一応前年度の引っ掛かりポイントはふさいだと思いますが、また新たな引っ掛かりポイントが生まれているかもしれません。