Visual StudioでUbuntu搭載デバイスのC/C++リモート開発環境を構築する

# はじめに
最近ではエッジデバイスでもPythonのような便利な開発言語が使えるようになってきていますが、時にはC/C++でがっつりプログラミングしたいときもありますよね。
そこで今回は、Visual StudioでUbuntu搭載デバイスのC/C++リモート開発環境を構築する方法を紹介したいと思います。
弊社のe-RT3やRaspberry Piなど、Ubuntu搭載のエッジデバイスのC/C++リモート開発環境を簡単に作ることができます。

# 環境
動作確認済デバイス（OS）

- e-RT3 Plus F3RP70-2L[^ert3]（Ubuntu 18.04 32bit）
    横河電機のエッジコントローラです。

- Raspberry Pi 4 Model B （Ubuntu Server 20.04 32bit）

これらのデバイスでは armhf アーキテクチャのパッケージが動作します。
また、Windows 10 搭載のPCでデバイスを操作しています。

ソフトウェアのバージョン

- Visual Studio Professional 2019 バージョン16.9.0
- Visual Studio Professional 2022 バージョン17.2.6

# デバイスの準備
**Raspberry Piの場合のみ**デバイスに必要なパッケージをインストールします。

```bash
sudo apt update
sudo apt install g++ make gdb gdbserver zip
```

# Visual Studioの準備
1. Linux開発に必要なツールセットをインストールします。
    Visual Studio Installerを開き、「C++によるLinux開発」[^linux]をインストールします。
    ![vsremote-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/9f09ac32-5c5b-5f81-615a-582c81e4fb42.png)

1. Visual Studioとデバイスを接続するための設定を行います。
    Visual Studioを起動し、「ツール」→「オプション」→「クロスプラットフォーム」→「接続マネージャ」を開き「追加」をクリックします。
    ![vsremote-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/ccf61803-e293-0df0-9090-26563c508f87.png)

    以下の項目を入力し、「接続」をクリックします。
    ![vsremote-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/23c4457b-bc64-e93b-1ab7-4f8e7503438b.png)

    | 項目             | 値                                    |
    | ---------------- | ------------------------------------- |
    | ホスト名         | デバイスのIPアドレス                  |
    | ポート           | 22                                    |
    | ユーザー名       | デバイスのユーザー名                  |
    | 認証の種類       | パスワード                             |
    | パスワード |ユーザーのパスワード |

    IntelliSenseで使用するヘッダーをダウンロードします。
    「接続マネージャ」→「リモートヘッダー IntelliSenseマネージャー」を開いて追加したデバイスを選択し、「ダウンロード」をクリックします。
    ![vsremote-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/873505b3-d950-ca7e-4e1d-955ec9d30c9a.png)

# プロジェクトの作成とデバッグ
1. プロジェクトの作成
    Visual Studioを起動して新しいプロジェクトを作成します。
    プロジェクトの種類に「C++」、「Linux」を指定して、「コンソールアプリケーション」を選択し、任意のプロジェクト名をつけてプロジェクトを作成します。
    ![vsremote-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/5d6f97b8-5867-a978-cf51-a879a67bc1e5.png)

1. プロジェクトの設定
    上のメニューの「プロジェクト」→「プロパティ」をクリックします。
    ![vsremote-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/65b50a20-810b-3332-b1c9-96a387d4ac07.png)

    構成に「Debug」、プラットフォームに「ARM」を指定し、「全般」→「リモートビルドマシン」に追加したデバイスを指定します。
    ![vsremote-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/a7de5a10-eec8-3e4e-d93f-9f86732f48ae.png)

    「デバッグ」を開き、「リモートデバッグコンピュータ」に追加したデバイスを、「デバッグモード」に「gdbserver」を指定し「適用」をクリックします。
    ![vsremote-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/1e80bc5c-d3b3-0f3c-4f54-1166dfafc6d6.png)

1. プロジェクトのビルドとデバッグ
    構成を「Debug」、プラットフォームを「ARM」にしてソースコードの任意の場所にブレークポイントを張り、プログラムをビルド、実行します。
    ![vsremote-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/67c5213b-0ef3-38d1-5802-229be7852895.png)

    プログラムがブレークポイントで止まれば成功です。
    ![vsremote-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/d69409e8-60a5-91f9-12e8-7d3b2fc2eee2.png)

    出力はLinuxコンソールウィンドウに表示されます。
    ![vsremote-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/faf6dc6b-ba08-2011-7568-d49a4d461710.png)
    
# 付録
## ソースファイルの追加
1. プロジェクトのアイコン上で右クリックし、「追加」→「新しい項目」をクリックします。
    ![vsremote-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/fbbd482a-a316-0783-cfeb-45a8d1689561.png)

1. 追加する項目の種類と名前を入力して、項目を追加します。
    ![vsremote-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/8c4d78e7-6e6e-2b98-28d5-d8a309bb2a7d.png)

## ライブラリのリンク
1. プロジェクトのプロパティ→「リンカー」→「入力」→「ライブラリの依存ファイル」の「編集」をクリックします。
    ![vsremote-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/9da3752d-6ad1-cddb-fefc-b3bb9080b84f.png)

1. 追加するライブラリの名前を入力します。以下はlibmを追加する場合の例です。
    ![vsremote-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/0199f493-b67e-40d5-e87c-25d7c1b50a86.png)

    （**e-RT3の場合** libm3を利用する場合はm3と入力します。）
    
## インクルードパスの追加
デフォルト以外の場所にあるヘッダファイルを利用する場合は、インクルードパスの設定を行う必要があります。
1. プロジェクトのプロパティ→「C/C++」→「全般」→「追加のインクルードディレクトリ」の「編集」をクリックします。
    ![vsremote-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/c61b84b0-89c9-936a-a398-17ed9ed707f8.png)

1. ヘッダファイルが含まれるデバイス上のディレクトリのパスを追加します。
    ![vsremote-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/7e48f406-7e91-acee-4de7-4c25bc08e27a.png)

# 参考
[^linux]: [C++ による Linux 開発 | Microsoft Docs](https://docs.microsoft.com/ja-jp/cpp/linux/?view=msvc-160)
[^ert3]: [産業用AIプラットフォーム | 横河電機株式会社](https://www.yokogawa.co.jp/solutions/products-platforms/control-system/real-time-os-controller/ert3-ai-platform/)