WSL(Ubuntu)のC++開発環境を Visual Studio Codeで構築

WSL Ubuntu開発環境を VS Codeで構築

WSL Ubuntu開発環境を VS Codeで構築

WSL(Ubuntu) C++開発環境をVS Codeで構築

2018年3月、Windows Subsystem for Linux(WSL)で動作するUbuntuのC++開発環境をWindows環境で動作するVisual Studio Codeで実現しました。

マイクロソフトが WSLを正式リリースして、Microsoft StoreからUbuntuがダウンロードできるようになり、WindowsでLinuxが動作するという便利な時代となりました。

WSL : Windows で Ubuntu環境 を実行する

Visual Studio Code(VS Code)を使用して、Windows Subsystem for Linuxで動作するUbuntuのC++開発環境を構築しました。VS Codeは、マイクロソフト社が開発したクロスプラットフォームで動作する高機能なソースコードエディターです。VS Codeはエディターであり、Visual Studio 20xx のような統合開発環境(IDE)ではありません。しかし、デバッグ機能やタスク機能(頻繁に行う作業の自動化)が組み込まれています。従って、「コード編集→ビルド処理→デバッグ実行」がVS Code内で行うことができます。

VS Codeでデバッグ

VS Codeでデバッグ

Ubuntu C++開発環境

最初に Windows Subsystem for Linux (Ubuntu) のC++開発環境を構築します。


gccを使用できるように開発ツールをインストールします。

sudo apt install build-essential

gdbデバッガをインストールします。

sudo apt install gdb

使用したツールのバージョンを下記に示します。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.4 LTS
Release:        16.04
Codename:       xenial
$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gdb --version
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
$ make --version
GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

C++ 作業ディレクトリー

C++言語をビルドして実行するのは、WSLで動作する Ubuntu環境です。また、Visual Studio Codeは、Windows環境で動作します。

今回は、このUbuntu環境とWindows環境を連携したC++開発環境を構築します。Windows環境からUbuntu環境のファイルへの(追加/変更/削除)アクセスは禁止されていますので、作業ディレクトリーをWindows側にします。

「c:\Users\pi\MyHome」をWindows環境とUbuntu環境から共通でアクセスする作業ディレクトリーとします。

MyHome ディレクトリーを作成します。

$ pwd
/home/pi

$ cd /mnt/c/Users/pi

$ sudo mkdir MyHome
$ cd MyHome

.bashrc の最後に、カレントディレクトリーを MyHome にするコマンドを入れます。

$ cd
$ pwd
/home/pi
$ tail -1 .bashrc
cd /mnt/c/Users/pi/MyHome

次にログインすると、/mnt/c/Users/pi/MyHome がカレントディレクトリーになります。

Visual Studio Codeのインストール

マイクロソフトのVisual Studio CodeサイトからVisual Studio Codeをダウンロードします。

VS Code ダウンロード1

VS Code ダウンロード1

Visual Studio Code ダウンロード」を入力します。

VS Code ダウンロード2

VS Code ダウンロード2

Windowsプラットフォームを選択します。

VS Code ダウンロード3

VS Code ダウンロード3

インストールを開始します。

Visual Studio Code を実行します。

VS Code 実行

VS Code 実行

 

Gitが見つかりません」とメッセージが表示されます。Gitは使いませんので、 [今後は表示しない]をクリックします。

Visual Studio Code のバージョンを確認します。

ヘルプ(H)-バージョン情報(A)」と入力します。

VS Code バージョン

VS Code バージョン

バージョン 1.21.1
コミット 79b44aa704ce542d8ca4a3cc44cfca566e7720f1
日付 2018-03-14T14:46:47.128Z
シェル 1.7.9
レンダラー 58.0.3029.110
Node 7.9.0
アーキテクチャ x64

統合ターミナルの設定

Visual Studio Code の統合ターミナルで、WSL(Ubuntu)のbashを使うように設定します。

[Ctrl]+[Shift]+[P]キー」でコマンドパレットを表示して「shell」と入力します。

統合ターミナルの設定1

統合ターミナルの設定1

ターミナル:規定のシェルの選択」を入力します。

統合ターミナルの設定2

統合ターミナルの設定2

シェルの選択項目が表示されます。

  • Command Prompt
  • PowerShell
  • WSL Bash

WSL Bash c:\WINDOWS\System32\bash.exe」を選択します。

統合ターミナルの設定3

統合ターミナルの設定3

表示(V)-統合ターミナル(I)」または、[Ctrl]+[Shift]+[@]キーを入力します。

統合ターミナルの設定4

統合ターミナルの設定4

画面下にUbuntu環境のbashターミナルが開きます。

C++言語のサンプルコード

これからVisual Studio Code でC++言語の開発環境を構築します。文字のASCIIコードを表示する簡単なC++言語のサンプルコードを使用します。

MyHomeに cpp_outAscii ディレクトリーを作成して、ソースコード outAsciiCode.cpp を作成します。

[ファイル(F)]-[フォルダを開く]」で、c:\Users\pi\MyHome\cpp_outAscii を指定します。次に「[ファイル(F)]-[新規ファイル(N)]」で、outAsciiCode.cppを指定します。

C++言語のサンプルコード

C++言語のサンプルコード

 

#include <stdio.h>

char cvhex(int ihex)
{
    char cHex; 
    if (ihex <10)    { cHex = '0' + ihex;      }
    else             { cHex = 'A' + ihex - 10; }
    return(cHex);
}

void outAsciiCode(char code)
{
    int ih = int(code / 16);
    int il = int(code % 16);
    char ch = cvhex(ih);
    char cl = cvhex(il);
    printf("%c \t %c%c \n", code ,ch,cl);
}

int main(void)
{
    outAsciiCode('1');
    outAsciiCode('A');
    outAsciiCode('I');
    outAsciiCode('J');
    outAsciiCode('a');
}

ソースコードをWindows環境とUbuntu環境からアクセスすることを考慮して、文字コードのエンコードを BOM付き Unicode(UTF-8)にします。

文字エンコード UTF-8

文字エンコード UTF-8

右下の 「UTF-8」をクリックします。

文字エンコード 保存

文字エンコード 保存

[エンコード付きで保存]を選択します。

文字エンコード UTF-8 with BOM

文字エンコード UTF-8 with BOM

[UTF-8 with BOM]を選択します。

 

Ubuntu環境でのビルドと実行

次に makefile を作成します。

# Makefile 
#
#     make clean
#     make
#     make exec
#
#-----------------------------------------  

#####
TARGET = outAscii 

OBJ     = 
OBJ    += outAsciiCode.o


# Optimaze Option
# 
CFLAGOPT  = 
CFLAGOPT += -O0

#
#
# cc options:
CFLAGS =
CFLAGS += -Wall 
CFLAGS += -g 
CFLAGS += $(CFLAGOPT)


#
# Link-time cc options:
LDFLAGS =

CC  = gcc
CPP = g++

#----------------------------- Command
#                                       file deletion command
RM= rm -f
#                                       linker
LN= $(CC)

#----------------------------------------------
all: $(TARGET)

.c.o:
	#----------------------------------------------------- [$<]
	$(CC)  $(CFLAGS)  -c $*.c

.cpp.o:
	#----------------------------------------------------- [$<]
	$(CPP) $(CFLAGS)  -c $*.cpp

$(TARGET) : $(OBJ) 
	#------------------------------------------------------ LINK
	$(LN) -o $(TARGET) $(OBJ)  $(LDFLAGS)  


clean:
	$(RM) *.o $(TARGET)

exec:
	./$(TARGET)

gdbでデバッグしますので、次のオプションを付けます。

  • -g : コンパイル,リンク時にDEBUG情報を付加する
  • -O0 : 最適化をしません

表示(V)-統合ターミナル(I)」 で、ターミナルを開きます。

makeコマンドでビルドします。

makeコマンド実行

makeコマンド実行

$make
#----------------------------------------------------- [outAsciiCode.cpp]
g++  -Wall  -g   -O0  -c outAsciiCode.cpp
#------------------------------------------------------ LINK
gcc -o outAscii   outAsciiCode.o

outAscii を実行して、結果を確認します。

$ ./outAscii
1        31
A        41
I        49
J        4A
a        61

makefileに実行用のオプションを入れましたので、makeコマンドからでも実行できます。

プログラム実行

プログラム実行

$ make exec
./outAscii
1        31
A        41
I        49
J        4A
a        61

Visual Studio Codeからビルド

Visual Studio Code から、プログラムのビルドをできるようにします。

VS Code ビルド設定1

VS Code ビルド設定1

タスク(T)-ビルドタスクの実行(B)」と入力します。

VS Code ビルド設定2

VS Code ビルド設定2

ビルドタスクを構成する…」をクリックします。

VS Code ビルド設定3

VS Code ビルド設定3

テンプレートから task.json を生成」をクリックします。

「Others 任意の外部コマンドを実行する例」を選択します。

VS Code ビルド設定4

VS Code ビルド設定4

task.json のひな形が表示されます。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "echo",
            "type": "shell",
            "command": "echo Hello"
        }
    ]
}

task.json を下記のように修正して、makeコマンドを実行するようにします。

VS Code ビルド設定5

VS Code ビルド設定5

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "My build",
            "type": "shell",
            "command": "make",
            "group":  {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

項目の意味は、Tasks in Visual Code ドキュメントを参考にします。

項目 設定例 意味
label My build ユーザーインターフェイスで使用するタスクのラベル
type shell タスクのタイプ (shell or process)
・shell : コマンドはシェルコマンドとして解釈
・process : コマンドは実行するプロセスとして解釈
command make 実行する実際のコマンド
group build 実行タスクが属するグループ (build or test)

タスク(T)-ビルドタスクの実行(B)」 または、[Ctrl]+[Shift]+[B]キーで、makeコマンドを実行してビルドします。

VS Code ビルド設定6

VS Code ビルド設定6

Visual Studio Codeからプログラムの実行

Visual Studio Code から、プログラムの実行ができるようにします。

task.json を下記のように修正して、testグループを追加します。

VS Code タスク実行1

VS Code タスク実行1

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "My build",
            "type": "shell",
            "command": "make",
            "group":  {
                "kind": "build",
                "isDefault": true
            }
        },
        {
            "label": "My exec",
            "type": "shell",
            "command": "make exec",
            "group": "test"
        }
    ]
}
VS Code タスク実行2

VS Code タスク実行2

タスク(T)-タスクの実行(R)」と入力します。

VS Code タスク実行3

VS Code タスク実行3

タスクの選択になりますので、「My exec」を選択します。

VS Code タスク実行4

VS Code タスク実行4

make execコマンドにより、./outAscii プログラムを実行しました。

Visual Studio Code C++拡張機能インストール

拡張機能インストール1

拡張機能インストール1

左の拡張機能をクリックします。

拡張機能インストール2

拡張機能インストール2

C/C++を選択してインストールします。

拡張機能インストール3

拡張機能インストール3

[インストール]をクリックします。

拡張機能インストール4

拡張機能インストール4

[再読み込み]をクリックします。


拡張機能インストール5

拡張機能インストール5

C/C++ InteliSense を選択してインストールします。

拡張機能インストール6

拡張機能インストール6

[インストール]をクリックします。

拡張機能インストール7

拡張機能インストール7

[再読み込み]をクリックします。

拡張機能インストール8

拡張機能インストール8

インストール済みの拡張機能を確認します。

 

Visual Studio Codeからデバッグの設定

Visual Studio Codeからブレークポイントを設定してデバッグできるようにします。

BashOnWindowsでのVisualStudioCodeのlaunch.jsonの書き方を参考にしました。

VS Code デバッグ設定1

VS Code デバッグ設定1

デバッグ(D)-デバッグの開始(S)」と入力します。

VS Code デバッグ設定2

VS Code デバッグ設定2

環境の選択で [More…]を選択します。

VS Code デバッグ設定3

VS Code デバッグ設定3

launch.json のひな形が表示されます。

{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "enter program name, for example ${workspaceFolder}/a.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "gdb",
            "miDebuggerPath": "/path/to/gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

 

VS Code デバッグ設定4

VS Code デバッグ設定4

右下の「構成の追加…」をクリックします

VS Code デバッグ設定5

VS Code デバッグ設定5

C/C++: (gdb) Bash on Windows Launch」を選択します。

元の launch.json ひな形を削除して、以下のようになります。

VS Code デバッグ設定6

VS Code デバッグ設定6

{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Bash on Windows Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "enter program name, for example ${workspaceFolder}/a.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": true,
            "pipeTransport": {
                "debuggerPath": "/usr/bin/gdb",
                "pipeProgram": "C:\\Windows\\sysnative\\bash.exe",
                "pipeArgs": [],
                "pipeCwd": ""
            },
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

launch.json を自分の環境に合わせて修正します。

項目 意味
name 構成の名前
program Ubuntu環境の実行ファイルのパス
args 実行時の引数
stopAtEntry エントリーポイントで停止
cwd Ubuntu環境の実行ディレクトリー
pipeTransport:
debuggerPath
Ubuntu環境のgdbのパス
pipeTransport:
pipeProgram
Windows環境のbashのパス
pipeTransport:
pipeArgs
pipeのオプション
sourceFileMap Ubuntu環境とWindows環境のマップ

以下のようになりました。

VS Code デバッグ設定7

VS Code デバッグ設定7

{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Bash on Windows Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "/mnt/c/Users/pi/MyHome/cpp_outAscii/outAscii",
            "args": [],
            "stopAtEntry": false,
            "cwd": "/mnt/c/Users/pi/MyHome/cpp_outAscii",
            "environment": [],
            "externalConsole": true,
            "pipeTransport": {
                "debuggerPath": "/usr/bin/gdb",
                "pipeProgram": "C:\\Windows\\sysnative\\bash.exe",
                "pipeArgs": ["-c"],
                "pipeCwd": "/"
            },
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "sourceFileMap": {
                "/mnt/c/Users/pi/MyHome/": "C:\\Users\\pi\\MyHome"
            }
        }
    ]
}

C/C++: (gdb) Bash on Windows Launchの修正前後の差分を示します。

launch.json 変更差分

launch.json 変更差分

Visual Studio Codeからデバッグの実行

VS Code デバッグ実行1

VS Code デバッグ実行1

左のデバッグボタンを押します。

VS Code デバッグ実行2

VS Code デバッグ実行2

ソースコードの行番号の左をクリックしてブレークポイントを設定します。

VS Code デバッグ実行3

VS Code デバッグ実行3

デバッグ(D)-デバッグの開始(S)」と入力します。

VS Code デバッグ実行4

VS Code デバッグ実行4

ブレークポイントで実行が停止します。左の領域には、変数の内容が表示されます。

VS Code デバッグ実行5

VS Code デバッグ実行5

デバッグ(D)-ステップインする(I)」または、F11を入力します。ステップ実行もできました。

まとめ

Windows Subsystem for Linux(WSL)で動作するUbuntuのC++開発環境をVisual Studio Codeで実現することができました。Visual Studio Codeは高機能なエディターですが、Visual Studio 20xx のような統合開発環境(IDE)風に使えます。

今までは、Windows環境はVisual Studio 20xx統合環境で快適に開発できますが、Linux環境はgdbでデバッグが大変という認識を持っていました。しかし、Visual Studio CodeによりUbuntu環境のC++開発が快適にデバッグできる時代になり感激しています。