Visual StudioでUbuntu搭載デバイスのC/C++クロスコンパイル環境を構築する

# はじめに
エッジデバイスで規模の大きいプログラムをビルドすると時間がかかってしまうことがありますよね。
そこで今回はVisual StudioでUbuntu搭載デバイスのC/C++クロスコンパイル環境を構築する方法を紹介します。
WindowsのWSLでプログラムをビルドしてエッジデバイスにデプロイすることができます。

![wsl-structure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/4e70b22f-fbc2-8413-5bea-b0934219570e.png)


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

- e-RT3 Plus F3RP70-2L[^ert3]（Ubuntu 18.04 32bit）  
横河電機のエッジコントローラです。armhf アーキテクチャのパッケージが動作します。

Windowsのバージョン

- Windows10 64bit バージョン1909
    
ソフトウェアのバージョン

- Visual Studio Professional 2019 バージョン16.9.6
    
# デバイスの準備
必要なパッケージをデバイスにインストールします。

```bash
    sudo apt update
    sudo apt install libc6-dbg
```
※[sudoers設定](https://qiita.com/Yokogawa_Mita/items/f7996d539b29618d7159#sudoers%E8%A8%AD%E5%AE%9A)、[proxy設定](https://qiita.com/Yokogawa_Mita/items/f7996d539b29618d7159#proxy%E8%A8%AD%E5%AE%9A)が必要な場合があります。

# WSLの準備
## WSLのインストール
1. [Microsoft公式の手順](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10#manual-installation-steps)に従ってWSLをインストールします。
    
1. Microsoft StoreでUbuntu18.04 LTSをダウンロードします。
    ![vs-cross-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/ea445681-6b0b-fa06-9da6-b47866533b4c.png)

## WSLの設定
1. WSLを起動してログインします。
1. 必要なパッケージをインストールします。

    ```bash
        sudo apt update
        # armhf用のビルド環境をインストール
        sudo apt install crossbuild-essential-armhf
        # その他必要なパッケージをインストール
        sudo apt install make rsync zip
    ```
    インストールの成功を確認します。
    
    ```bash
        $ arm-linux-gnueabihf-gcc --version
        arm-linux-gnueabihf-gcc (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0
        Copyright (C) 2017 Free Software Foundation, Inc.
        This is free software; see the source for copying conditions.  There is NO
        warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
        $ arm-linux-gnueabihf-g++ --version
        arm-linux-gnueabihf-g++ (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0
        Copyright (C) 2017 Free Software Foundation, Inc.
        This is free software; see the source for copying conditions.  There is NO
        warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    ```
    ※PCがproxy環境下にある場合は[proxy設定](https://qiita.com/Yokogawa_Mita/items/f7996d539b29618d7159#proxy%E8%A8%AD%E5%AE%9A)が必要です。

# Visual Studioの準備
[以前紹介した記事のVisual Studioの準備](https://qiita.com/Yokogawa_Ishino/items/eaa8849db336391ec17b#visual-studio%E3%81%AE%E6%BA%96%E5%82%99)と同様の手順で行います。
IntelliSenceのヘッダーのダウンロードは不要です。
    
# プロジェクトの作成とデバッグ
1. プロジェクトの作成
    Visual Studioを起動して新しいプロジェクトを作成します。
    プロジェクトの種類に「C++」「Linux」を指定して「コンソールアプリケーション」を選択し、任意のプロジェクト名をつけてプロジェクトを作成します。
    ![vsremote-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/c1d343c3-0662-1f9c-c702-0373f559a16e.png)

1. プロジェクトの設定[^wsl]
    上のメニューの「プロジェクト」→「プロパティ」をクリックします。
    ![wsl-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/358957d0-efa1-4d81-89c9-cc4513763cf0.png)
    プラットフォームを「x64」とし、「全般」→「プラットフォームツールセット」に「GCC for Windows Subsystem for Linux」を指定します。
    ![wsl-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/254969a4-3e8e-34ad-5431-9ee93cbdbac4.png)

    「デバッグ」を開き、「リモートデバッグコンピュータ」に追加したデバイスを指定します。
    ![vs-cross-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/5deba043-4465-ec9e-238c-b6949ec79f3e.png)
    「C/C++」→「全般」を開き、「Cコンパイラ」と「C++コンパイラ」に「arm-linux-gnueabihf-g++」を指定します。
    ![vs-cross-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/c2527e7c-8af0-29bb-0a01-b347f803b648.png)
    「リンカー」→「全般」→「リンカー」に「arm-linux-gnueabihf-g++」を指定します。
    ![vs-cross-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/9a441c17-037c-336b-f5f9-09181af4d911.png)

1. プロジェクトのビルドとデバッグ
    プラットフォームを「x64」にしてソースコードの任意の場所にブレークポイントを張り、プログラムをビルド、実行します。
    ![wsl-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/1fc57c04-4783-6bcd-2e26-e428756d847e.png)

    プログラムがブレークポイントで止まれば成功です。
    ![vs-cross-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/e9f67858-4949-c769-1d3a-00d5fdb73a40.png)
    出力はLinuxコンソールウィンドウに表示されます。
    ![vs-cross-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/c3febf19-1673-8890-180e-a6335245ec80.png)
    
# 補足
## WSLのファイルへのアクセス
WSL2の場合、エクスプローラーに`\\wsl$`と入力するとWSLのファイルにアクセスできます。
![wsl-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/80eb232f-6cfe-f7b1-d214-f842b2c1944e.png)

## ビルドのみ行う方法
WSLでのビルドのみ行いたい場合は、「ビルド」メニューから対応する項目をクリックします。
![wsl-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/d028391a-aa73-84a0-0be3-a7db60af74f7.png)
出力ファイルはWindows上の`<ソリューションディレクトリ>\<プロジェクトディレクトリ>\bin\<プラットフォーム>\<構成>\`に配置されます。
![wsl-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/b1bc0ea1-4cc1-bb39-5261-f5e4eb8e4381.png)

## デバイス固有のライブラリの使用
デバイス固有のライブラリを使用したプログラムをビルドする場合は、ライブラリとヘッダファイルをプロジェクトに含める必要があります。

1. プロジェクトディレクトリにライブラリとヘッダファイルを格納するディレクトリを作成します。
    ![wsl-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/3db2913c-bb37-e921-8392-dd6495b75bb8.png)

1. 追加のインクルードディレクトリに、ヘッダファイルが含まれるディレクトリを指定します。
    ![wsl-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/337cd7ab-8ab0-3b5f-4ed7-f685b11f7ae9.png)

1. 追加のライブラリディレクトリに、ライブラリが含まれるディレクトリを指定します。
    ![wsl-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/392f2cef-01c1-1bd4-3a5a-fda7a2b20b08.png)

1. ライブラリの依存ファイルにライブラリ名を指定します。例えば、libfoo.soの場合は「foo」と入力します。
    ![wsl-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682603/39c97d2e-8c24-c3fb-89af-628a254eb764.png)

[^ert3]: [産業用AIプラットフォーム | 横河電機株式会社](https://www.yokogawa.co.jp/solutions/products-platforms/control-system/real-time-os-controller/ert3-ai-platform/)
[^wsl]: [C++ with Visual Studio 2019 and Windows Subsystem for Linux (WSL) | C++ Team Blog](https://devblogs.microsoft.com/cppblog/c-with-visual-studio-2019-and-windows-subsystem-for-linux-wsl/)