LoginSignup
4
7

More than 1 year has passed since last update.

Windows10にVSCodeでLinuxのC++開発環境を構築

Last updated at Posted at 2021-06-05

はじめに

お仕事でRasberry Pi用のインターフェイスプログラムの作成がありました。もともとWindows用にDelphi5からC#(.NET 4.x)で移植したものがあり、Linux用でも動作するためC#(.NET 5.0) に修正してRasberry Piでも動作することが確認できました。
Bashからインターフェイスプログラムを呼び出すことが出来たのですが、C++でインターフェイスプログラムを呼び出すにはどうすればいいのか forkとexeclを使えば出来そうと分かったが、それにはLinux用開発環境を構築する必要がありました。

下記サイトを参考にVSCodeとWSLを開発環境を構築しました。

環境構築

  • Windows 10 Pro
  • WSL(Ubuntu 18.04 LTS)
  • Visual Studio Code 1.56.2

※WSL2(Ubuntu 20.04 LTS)でも方法は同じになります。

WSLの追加作業

WSL(Ubuntu 18.04 LTS)にて、下記アプリケーションをインストールします。

  • gcc、g++、makeなどのC/C++ソースコードをビルドするのに必要な実行ファイルのインストール
  • デバッガgdbのインストール
  • VSCodeのインストール
sudo apt update;
sudo apt install build-essential -y;
sudo apt install gdb -y;
sudo apt install code;

build-essentialをインストールしたはずなのに「/usr/bin/g++: No such file or directory」のエラーになっていました。原因は「sudo apt update」をしていなかったためです。
教訓として、先に「sudo apt update」はしておきましょう。

VSCodeに拡張機能を追加

Windows 10側のVSCodeに下記の拡張機能を追加します。

  • Remote WSL
  • C/C++
  • C/C++ IntelliSense

ビルドとデバッグの設定

サンプルとして、Hello Worldではつまらないのでフィボナッチ数列を求めるプログラムを作成します。

プロジェクトフォルダ用意

Windows上に下記のフォルダを作成します。

C:\WorkSpace\LinuxFibonacci

Remote WSL

VSCodeの左パネルからリモートエクスプローラーをクリックします。
WSL_TARGETSのUbuntu-18.04を選択し右クリックメニューから「Connect to WSL」をクリックします。
image.png

VSCodeがもう一つ起動してきます。これが、WSL内のVSCodeになります。
最初のVSCodeは閉じても構いません。
image.png

対象プロジェクトフォルダーを開く

VSCodeからフォルダを開くをクリックします。
今回はWindowsフォルダ内の「C:\WorkSpace\LinuxFibonacci」にしたいので、「/mnt/c/WorkSpace\LinuxFibonacci」まで辿っていき、OKボタンをクリックします。

image.png

作業開始

左下隅にてWSL:Ubuntu-18.04の接続が確認できます。これで作業の開始となります。

image.png

プログラム作成

Fibonacci.cpp
#include<iostream>
using namespace std;
 
int main()
{
    int fib1 = 0, fib2 = 1, fib3 = 1;
 
    cout << "The Fibonacci Series is follows : " << endl << fib1 << " " << fib2 << " ";
    while (fib1 + fib2 < 1000)
    {
        fib3 = fib1 + fib2;
        fib1 = fib2;
        fib2 = fib3;
        cout << fib3 << " ";
    }
    cout << endl;
 
    return 0;
}

上記のソースコードを入力して、「Fibonacci.cpp」で保存します。
image.png

ビルドとデバッグの設定

適当な位置にブレイクポイントをセットして、メニューの「実行」から「デバッグの開始」をクリックします。
image.png

launch.jsonがまだ生成されていない場合、環境の選択と構成の選択が選択肢が出てきます。
※一度生成されるとlaunch.jsonを削除しても勝手に自動生成されてしまい環境の選択が出来ないです、よく分からない。

image.png
image.png

すると、launch.jsonとtask.jsonが自動生成されます。

launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "g++ - アクティブ ファイルのビルドとデバッグ",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "gdb の再フォーマットを有効にする",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "C/C++: g++ アクティブなファイルのビルド",
            "miDebuggerPath": "/usr/bin/gdb"
        }
    ]
}
task.json
{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "cppbuild",
			"label": "C/C++: g++ アクティブなファイルのビルド",
			"command": "/usr/bin/g++",
			"args": [
				"-g",
				"${file}",
				"-o",
				"${fileDirname}/${fileBasenameNoExtension}"
			],
			"options": {
				"cwd": "${fileDirname}"
			},
			"problemMatcher": [
				"$gcc"
			],
			"group": "build",
			"detail": "コンパイラ: /usr/bin/g++"
		}
	]
}

タスクの構成の再生成

tasks.jsonが生成されていない場合、下記の方法で同じものを生成できます。

メニューの「ターミナル」から「タスクの構成」をクリックします。
image.png

Linux用なので「C++:g++ アクティブなファイルのビルド」を選択します。
image.png

すると、task.jsonが自動生成されますので、保存します。

launch.jsonの修正

「デバッグの開始」で下記エラー「launch:program (パス名)/build/Debug/outDebug does not exist」が出るようでしたら、launch.jsonを修正します。

image.png

修正前

launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "C/C++ Runner: Debug Session",
      "type": "cppdbg",
      "request": "launch",
      "args": [],
      "stopAtEntry": false,
      "cwd": "/mnt/c/WorkSpace/LinuxFibonacci",
      "environment": [],
      "program": "/mnt/c/WorkSpace/LinuxFibonacci/build/Debug/outDebug",
      "internalConsoleOptions": "openOnSessionStart",
      "MIMode": "gdb",
      "miDebuggerPath": "/usr/bin/gdb",
      "externalConsole": false
    }
  ]
}

修正後

"cwd"と"program"の内容を変更、"preLaunchTask"を追加しています。

修正箇所
"cwd": "${fileDirname}",
"program": "${fileDirname}/${fileBasenameNoExtension}",
"preLaunchTask": "C/C++: g++ アクティブなファイルのビルド",
launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "C/C++ Runner: Debug Session",
      "type": "cppdbg",
      "request": "launch",
      "args": [],
      "stopAtEntry": false,
      "cwd": "${fileDirname}",
      "environment": [],
      "program": "${fileDirname}/${fileBasenameNoExtension}",
      "internalConsoleOptions": "openOnSessionStart",
      "MIMode": "gdb",
      "preLaunchTask": "C/C++: g++ アクティブなファイルのビルド",
      "miDebuggerPath": "/usr/bin/gdb",
      "externalConsole": false
    }
  ]
}

フォルダ構成

「Fibonacci」は実行ファイルになります。Linuxでは実行ファイルでも「exe」などの拡張子が付きません。
実行ファイルは、“./(実行ファイル名)“と先頭に”./“を付けることでBashなどで実行できるようになる。
先頭に”./“を付けないと、「command not found」エラーとなります。

C:\WorkSpace\LinuxFibonacci
│  Fibonacci
│  Fibonacci.cpp
│
└─.vscode
    launch.json
    tasks.json
    c_cpp_properties.json
    settings.json

実際にビルド・デバッグを試す

ようやく環境が整ったので、ビルド・デバッグの動作を確認してみます。

ビルド実施

メニューの「実行」の「デバッグの開始」をクリックすればビルドとデバッグが開始されます。
また、メニューの「ターミナル」の「ビルドタスクの実行」をクリックすればビルドのみが行われます。

> Executing task: C/C++: cpp アクティブなファイルのビルド <

ビルドを開始しています...
/usr/bin/cpp -g /mnt/c/WorkSpace/LinuxFibonacci/Fibonacci.cpp -o /mnt/c/WorkSpace/LinuxFibonacci/Fibonacci
ビルドが正常に完了しました。

ターミナルはタスクで再利用されます、閉じるには任意のキーを押してください。

デバッグ実施

左側に変数の値が出力されます。
image.png

結果

ターミナルに結果が出力されます。
image.png

結果
The Fibonacchi Series is follows :
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

外部プロセス実行プログラム

C++でインターフェイスプログラムを呼び出すプログラムになります。
Windowsでは CreateProcessとWaitForSingleObjectを使用するが、Linuxにはないため forkとexeclとwaitpidを使用する。

Clientフォルダに「Test」という実行ファイルを引数2つ(-u,HOGE)を渡して実行する。

main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
 
int main()
{
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork");
        exit(-1);
    }
    else if (pid == 0) {
        // 子プロセスで別プログラムを実行
        execl("./Client/Test", "./Client/Test", "-u", "HOGE", NULL);
        exit(-1);
    }
 
    // 親プロセス
    int status;
    //子プロセスの終了待ち
    pid_t r = waitpid(pid, &status, 0); 
    if (r < 0) {
        perror("waitpid");
        exit(-1);
    }
    if (WIFEXITED(status)) {
        // 子プロセスが正常終了の場合
        printf("child exit-code=%d\n", WEXITSTATUS(status));
    }
    else {
        printf("child status=%04x\n", status);
    }
 
    return 0;
}

最後に

WSL(Linux)用の実行ファイルの生成とデバッグができるようになります。
でも、今回本当にやりたいのは、Rasberry Pi用(CPU:Arm)の実行ファイルの生成とデバッグなんですよね。
まだ、実現できていないのですが、出来るようになったら記事を作成します。

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7