【環境構築】VSCode+WSL+Remote WSLでWindows上にC/C++開発・デバッグ環境を構築する【ビルドタスク設定編】

IT関連

C/C++の環境構築したけど、複数ファイルのコンパイルが失敗しないか?

こんにちは、novです。
今回は、前回の記事の補足編になります。

前回構築した環境では、単体で完結するファイルのビルドまでは、「F5キー」を押すことでビルド・デバッグまでできるようにしていました。

ところが、いざクラス定義や関数の定義を別ファイルに切り出してビルドしようとすると、切り出したファイルのビルドが失敗するという現象が起きていました。
で塗りつぶしているところは、余分なPathの部分です。

これを解決するにあたって、VSCodeの「tasks.json」についてあれこれ調べたので、解決方法と合わせてまとめようと思った次第です。

なお、この画像を見てピンとくる人もいると思いますが、実行されているg++の引数に各ファイルが与えられていなかったことが原因でビルドエラーとなっています。
以下ではこれを解消するためにどういう設定が必要かを述べていきます。

複数ファイルでのビルドが失敗する理由

一言でいうと、F5キーを押したときに走っているコンパイルのコマンドに不備があるからでした。

例えば、以下のようなコードをコンパイルするとしましょう。

#ifndef _SAMPLE_H_
#define _SAMPLE_H_

class CSample
{
public:
    void set(int num);
    int get();

private:
    int m_num;
};

#endif //_SAMPLE_H_
#include "sample.h"

void CSample::set(int num)
{
    m_num = num;
}

int CSample::get()
{
    return m_num;
}
#include <iostream>
#include "include/sample.h"

using namespace std;

int main(){
    CSample obj1, obj2;

    obj1.set(1);
    obj2.set(2);

    cout << obj1.get() << endl;
    cout << obj2.get() << endl;

    return 0;
}

コード自体は以下のサイトから拝借してきました。

一週間で身につくC++言語の基本|トップページ~C++言語の初心者でも、簡単にプログラミングが気軽に学習できるサイトです。
すでにC言語について学んだプログラマーが1週間でC++言語でプログラミングが出来るように、基礎からきちんと学べるサイトです。オブジェクト指向やクラスの基本概念から、継承やSTLやテンプレートなどといった行動な話題まで取り扱っています。

さて、前回作成した環境にて、以下のようなフォルダ構成のもとでビルドを行います。

├ include ┬ sample.h
│              └ sample.cpp
└ main.cpp

本来ならば、

g++ -g main.cpp sample.cpp -o main

というコマンドが走ってほしいところなのですが、

g++ -g main.cpp -o main

というコマンドが走っていました。これではクラスの実装がコンパイラに渡されていないのでビルドできないのもむべなるかなといったところです。

ここら辺のコマンドを調整するのは「tasks.json」の役割のようです。
では、さっそく解決方法について触れていきましょう。

tasks.jsonへ設定する内容

前回の記事で作成した環境にて、launch.jsonがない状態でF5キーを押し、デバッグ環境を自動生成すると以下のようなtasks.jsonが「.vscode」フォルダ以下に生成されます。

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++ アクティブなファイルのビルド",
            "command": "/usr/bin/g++",
            "args": [
                "-g",
                "${file}",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "デバッガーによって生成されたタスク。"
        }
    ],
    "version": "2.0.0"
}

今回調整するのは、このうち「args」の項目になります。ビルドが通るように変更したファイルが以下になります。

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++ アクティブなファイルのビルド",
            "command": "/usr/bin/g++",
            "args": [
                "-g",
                "${file}",
                "${fileDirname}/include/**", // ここを追加
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "デバッガーによって生成されたタスク。"
        }
    ],
    "version": "2.0.0"
}

変更箇所は”args”の”-g”で与えている引数の二つ目の部分ですね。
tasks.jsonに関してはbashで走るコマンドと引数が設定されているので、それに対応した部分をカスタマイズすることで好きなコマンドを実行させることができます。

コマンドは”command”、引数は”args”以下に値を設定することで変更することが可能です。

今回は、

  • command:g++
  • args: -g main.cpp sample.cpp -o main

とできれば良かったので、上記のような変更になっています。

VSCodeのtasks.jsonなどで使えるビルトインの変数

ここからは余談になります。

上記のような現象が起こった場合、tasks.jsonで自分の環境に合わせた設定をすることになります。
その際に「現在のフォルダへの絶対パス」などを格納している変数を使えないと、べた書きで多数のパスを書くことになり非常に非効率です。

VSCodeのjson設定で使えるビルトイン変数に関する情報は少々探しにくかったので備忘録を兼ねてまとめておきます。以下は参考にしたサイトです。

Visual Studio Code Variables Reference
Visual Studio Code variable substitution reference
VS Codeの設定をキレイに変数置換 - Qiita
変数置換構文 launch.json や tasks.json では ${variableName} という構文で変数置換を行うことができます。どの言語でコーディングするときでも使えるので一読しておくと後で役に立ちそう。 役...
変数 説明
${workspaceFolder} 現在VSCodeで開いているフォルダへの絶対パス
${wordspaceFolderBasename} 現在VSCodeで開いているフォルダの名前
${file} 現在編集中のファイルへの絶対パス
${relativeFile} VSCodeで開いているフォルダから現在編集中のファイルへの相対パス
${relativeFileDirname} VSCodeで開いているフォルダから現在編集中のファイルが存在するフォルダへの相対パス
${fileBasename} 現在編集中のファイル名
${fileBasenameNoExtension} 現在編集中のファイル名(拡張子なし)
${fileDirname} 現在編集中のファイルが存在するフォルダへの絶対パス
${fileExtname} 現在編集中のファイルの拡張子名
${cwd} タスクランナー起動時のカレントワーキングディレクトリ
${lineNumber} 現在選択中の行番号(カーソルの存在する位置)
${selectedText} 現在選択中のテキスト
${execPath} 実行中のVSCodeの実行可能ファイル「code.exe」のアドレス
${defaultBuildTask} デフォルトのビルドタスク名(「ctrl+shift+B」で起動されるタスク名)

具体例として、以下のフォルダ構成のもとでこれらの変数がどのようになるかを説明します。

work(VSCodeで開いているディレクトリ)

├ .vscode ─ tasks.json
└ sample ─ sample_nest ─ sample.txt(このファイルを編集中とする)

sample.txtの中身は以下とします。

tasks.jsonを確認するためのファイル

"Select this sentence"

“Select this sentence” という部分を選択した状態で実行することとします。

この場合の各変数の中身がどうなるかを一覧にまとめると以下のようになります。

変数 実行結果
${workspaceFolder} [path to "work"]/work
${wordspaceFolderBasename} work
${file} [path to "work"]/work/sample/sample_nest/sample.txt
${relativeFile} sample/sample_nest/sample.txt
${relativeFileDirname} sample/sample_nest
${fileBasename} sample.txt
${fileBasenameNoExtension} sample
${fileDirname} [path to "work"]/work/sample/sample_nest
${fileExtname} .txt
${cwd} [path to "work"]/work (設定による)
${lineNumber} 3
${selectedText} "Select this sentence"
${execPath} C:\Users\hogehoge\AppData\Local\Programs\Microsoft VS Code\Code.exe (環境による)
${defaultBuildTask} echo variables (tasks.jsonの"label"で指定した値)

自分で確認したい場合は以下のtasks.jsonの内容をコピーして実行してみてください。

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "echo variables",
            "type": "shell",
            "command": "echo",
            "args": [
                "${workspaceFolder}",
                "${workspaceFolderBasename}",
                "${file}",
                "${relativeFile}",
                "${relativeFileDirname}",
                "${fileBasename}",
                "${fileBasenameNoExtension}",
                "${fileDirname}",
                "${fileExtname}",
                "${cwd}",
                "${lineNumber}",
                "${selectedText}",
                "${execPath}",
                "${defaultBuildTask}"
            ],
            "problemMatcher": [],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}


なお、テキストを選択した状態で実行しないと動作しないのでご注意ください。

※ あるいは${selectedText}の部分を消すなどしてください

実行する際は、以下の手順でできます。

  • 以下の内容をコピーしたtasks.jsonファイルを「.vscode」以下に配置
  • 「ctlr+shift+P」でコマンドパレットを開く
  • 「task」で検索し、「タスクの実行(Tasks/Run Task)」を選択
  • 次に出てきた項目のうち、「echo variables」を選択
  • あるいは、「ctrl+shift+B」で実行できます(Build Taskとして認識するための設定が書かれているため)。


    なお、上記のtasks.jsonでechoコマンドを実行していることから分かるように、tasks.jsonには任意のコマンドを登録して実行させることができます。
    よく使うコマンドはtasks.jsonで登録しておくと便利かもしれません

    まとめ

    この記事では、前回の記事で作成した環境では複数ファイルに分割した場合のビルドが通らないことに触れ、その原因と解決策を述べました。
    また、tasks.jsonで使用可能な変数についても具体例を交えてまとめました。

    VSCodeの設定ファイルとかについて調べると、「以下をコピペすればOK」というものが多いですが、使える変数を覚えておくと自分で色々設定したいときにも応用が利くと思います。

    さて、今回の内容は以上です。tasks.json周りの話で困っている人の助けになれば幸いです。

    コメント

    タイトルとURLをコピーしました