目次
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;
}
コード自体は以下のサイトから拝借してきました。
さて、前回作成した環境にて、以下のようなフォルダ構成のもとでビルドを行います。
├ 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設定で使えるビルトイン変数に関する情報は少々探しにくかったので備忘録を兼ねてまとめておきます。以下は参考にしたサイトです。
変数 | 説明 |
---|---|
${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}の部分を消すなどしてください
実行する際は、以下の手順でできます。
あるいは、「ctrl+shift+B」で実行できます(Build Taskとして認識するための設定が書かれているため)。
なお、上記のtasks.jsonでecho
コマンドを実行していることから分かるように、tasks.jsonには任意のコマンドを登録して実行させることができます。
よく使うコマンドはtasks.jsonで登録しておくと便利かもしれません
まとめ
この記事では、前回の記事で作成した環境では複数ファイルに分割した場合のビルドが通らないことに触れ、その原因と解決策を述べました。
また、tasks.jsonで使用可能な変数についても具体例を交えてまとめました。
VSCodeの設定ファイルとかについて調べると、「以下をコピペすればOK」というものが多いですが、使える変数を覚えておくと自分で色々設定したいときにも応用が利くと思います。
さて、今回の内容は以上です。tasks.json周りの話で困っている人の助けになれば幸いです。
コメント