Visual Studio CodeのRemote ContainersでC++開発環境構築


C++の開発をすることになったので、とりあえず開発環境をどうにかしようと思い、安定板にも入ったということで、今流行りのVisual Studio CodeのRemote - Containersを使って環境構築しました。

はじめに

注意 Docker上でgdbを使うためにセキュリティレベルを下げる設定を追加しています。外部に公開される環境では用いないようにしてください。

動作環境

macOS Mojave

version 10.14.5

$ docker --version
Docker version 18.09.2, build 6247962
$ code --version
1.35.1
c7d83e57cd18f18026a8162d042843bda1bcf21f
x64

実行方法

gitリポジトリにプロジェクトのテンプレートを上げているので、そこから取得します。

簡単な設定概要については 設定の概要をご参照ください。

git clone https://github.com/dbgso/vscode-cpp-devcontainer.git
code vscode-cpp-devcontainer

以下のダイアログがでるので、Reopen in Containerを選択します。

あるいは、コマンドパレットからRemote-Containers: Reopen Folder in Containerを選択しても同様です。

docker-compose.ymlとDockerfileに定義したビルドが走るので、しばらく待機します。

ビルドが終わればこんな感じで拡張機能ありの状態でコンテナ内の環境が立ち上がります。

コマンドパレットからCmake: Quick Startを実行して、プロジェクトの雛形を作ってもらいます。

途中でこんなダイアログが出たらScan for kitsを選択します。

Kitの種類も聞かれますが、[Unspecified] でとりあえずCMakeにお任せしておきます

ここからいくつか入力を促されます。

  • Projectname
    • 任意(helloとしました)
  • Library or Executable
    • 今回は実行ファイルを作りたいのでExecutableを選択しました

ここまで、プロジェクトの雛形が作成されました。

ちなみにこんな感じの階層になってました。実際にはもっと深いですが参考までに

$ find . -maxdepth 2
.
./CMakeLists.txt
./.gitkeep
./build
./build/compile_commands.json
./build/CMakeFiles
./build/Makefile
./build/cmake_install.cmake
./build/CTestTestfile.cmake
./build/Testing
./build/CPackConfig.cmake
./build/CPackSourceConfig.cmake
./build/hello
./build/CMakeCache.txt
./build/DartConfiguration.tcl
./.vscode
./.vscode/ipch
./main.cpp

ここからCMakeLists.txtmain.cppをベースに変更していけば良さそうです。

実行

この時点で最低限実行に必要な設定はされているので、下部のDebugボタン押下で起動できます。
Hello world!がちゃんと表示されました。

デバッグ機能をつかってみる

ブレークと変数書き換えをしたかったので、こんな感じに書き換えて最終行で止めてみました。

#include <iostream>

int main(int, char**) {
    std::cout << "Hello, world!\n";
    int i = 10;
    std::cout << i;
}

ちゃんと指定した行で止まってくれたので、variablesのパネルで変数i10->5に書き換えました。

再開すると、ちゃんと5で表示されました。ちゃんとデバッガで書き換えできてますね。

設定の概要

コンテナの設定は.devcontainer/devcontainer.jsonに定義します。

devcontainer/devcontainer.json
{
    "name": "cpp-devcontainer-project",
    "dockerComposeFile": [
        "./docker-compose.yml"
    ],
    "service": "cpp",
    "extensions": [
        "ms-vscode.cpptools",
        "vector-of-bool.cmake-tools",
        "twxs.cmake"
    ],
    // 社内プロキシなどで、拡張機能がインストールできない場合にコメントを外す
    //"settings": {
    //    "http.proxyStrictSSL": false
    //},
    "workspaceFolder": "/data"
} 

同ディレクトリ内のdocker-compose.ymlに従って起動するようにしています。
Developing inside a Container using Visual Studio Code Remote Development を見た感じ、port forwarding等もdevContainer.jsonに設定することで可能なようですが、既存設定の流用を考えた場合はdocker-composeの方が楽なので、docker-composeで起動しています。
ちなみにdocker-composeの場合は、立ち上がった複数のコンテナの内このコンテナに接続しますよ、というのを指定する必要があるのでdocker-composeのサービス名(cpp)を指定しています。

Visual Studio Codeの拡張機能も定義できるので、以下3つのC++とCMake関連を入れています。

docker-compose.ymlとDockerファイルはシンプルにC++関連の設定をしているだけです。ただし、注意点に書いている通り、gdb利用のための設定を入れています。

docker-compose.yml
version: '3.3'

services:
  cpp:
    build: .
    volumes:
      - ../data:/data
    working_dir: /data
    tty: true
    # to use gdb
    cap_add:
      - SYS_PTRACE
    security_opt:
      - seccomp:unconfined
FROM ubuntu:18.04

RUN apt-get update && \
    apt-get install -y git build-essential cmake clang libssl-dev && \
    apt-get install -y cpputest libsqlite3-dev clang-format gdb

注意点

Dockerコンテナ上のプロセスにstraceでアタッチする - Qiita

Docker上でgdbを動かす - 俺より凄いやつしかいない。

の記事そのままになるのですが、Docker上でgdbを動かすには以下のオプションを付けてコンテナを起する必要があります。

    cap_add:
      - SYS_PTRACE
    security_opt:
      - seccomp:unconfined

付けない場合、GDB: Failed to set controlling terminal: Operation not permitted\n cmake のエラーが出ます。理由がわからず結構はまったので気をつけてください

ただし、最初にも書きましたがセキュリティレベルが下がることになりますので、開発環境でのみ使うよう気をつけてください。

おわりに

C++環境をVisual Studio Code + Docker で構築してみました。
複雑なプロジェクトになった場合は試せてないですが、なかなか良さそうな感じがします。

あとRemote - Containers楽しい便利。

参考

Dockerコンテナ上のプロセスにstraceでアタッチする - Qiita

Docker上でgdbを動かす - 俺より凄いやつしかいない。

Visual Studio Code を使った C++ のビルド&デバッグ方法(with CMAKE) - Daily Tech Blog