JetsonTX2(arm64のUbuntu Linux)上でVSCodeでC++のコード補完(IntelliSense)をしたい

# これは何？
nVidiaのJetson、arm64のLinuxでVSCode(実際は、Code - OSS(headmelted))を使ってC++コード補完(IntelliSense)ができるようにするためのメモです。
クロスコンパイル環境ではなく、デバイス上で直接VSCodeを実行する時の情報になります。
他のJetsonシリーズやRaspberryPiでも同様の手法が使えると推測しています。

(追記)
本セットアップが済んでいれば、自分のPC上のVSCodeにて、Remote – SSHを入れて、ccls拡張をSSH側にインストールして、下記のccls拡張の設定を行えば、SSHリモート開発でも補完がきくようになりました。

armのLinuxでは、MicrosoftのVSCodeのC++拡張をインストールしても、"Architecture arm64 is not supported."というエラーが出てしまい、コード補完他の支援機能が働きませんでした。
この件、かなり昔からいろいろな場所(Github上のVSCode公式含む)で同様の質問が出ていますが、C++拡張自体がarmに対応していないため、解決方法はありませんでした。

# 筆者の環境
- nVidia JetsonTX2
- Ubuntu 16.04
- Code - OSS(headmelted)導入済み

# 基本的な流れ
VSCodeのC++拡張に期待するのは一旦やめて、ccls拡張が動作するようにします。
ネット上にある、色々な情報を組み合わせて試行錯誤しながらセットアップしました。
先人の皆様の情報に深く感謝致します。
各位、作業の細部はご自分の環境に合わせてimproviseしてください。

- 作業用フォルダの作成
- メモリ不足対策
- cmakeのアップデート
- gcc7、ninjaのインストール
- llvmのコンパイル
- cclsのコンパイル
- VSCodeでccls拡張のインストールと設定
- 補足：プロジェクト毎にcompile_commands.jsonを作成

# セットアップ作業
## 作業用フォルダの作成
VSCodeの動作に必要となるため、利用中はllvmやcclsのフォルダは削除できません。
ゴチャゴチャにならないよう、全ての作業は`~/src`でおこないました。

```
$ mkdir ~/src
$ cd ~/src
```


## メモリ不足対策（仮想メモリの作成）
llvmのコンパイルにはとても多くのメモリが必要で、仮想メモリが無いとエラーが発生することがあります。
JetsonTX2の8GBでは、エラーになりました。

```
$ cd ~/src
$ git clone https://github.com/JetsonHacksNano/installSwapfile
$ cd installSwapfile
$ ./installSwapfile.sh -s 16
```
## cmakeのアップデート
aptで取得できるcmakeは古いのでllvmをコンパイルできません。ということで、削除します。

```
$ sudo apt uninstall cmake
```
その後、以下のようなページを参考にして、新し目のcmakeをコンパイル＆インストールします。
自分は、3.17.3を選択しました。
(公式)https://cmake.org/install/
(Qiita記事)https://qiita.com/koara-local/items/9d01c6bb9dd93563b7c6

## gcc7、ninjaのインストール
llvmのコンパイルを少しでも早くするため、makeの代わりにninjaを利用します。

```
$ sudo apt install -y ninja-build
```

cclsのコンパイルにはgcc7以降が必要とのことなので、インストールしておきます。
(参考)https://blog.medalotte.net/archives/473

```
$ sudo apt install -y gcc-7 g++-7
```

## llvmのコンパイル
cmakeするまでは、公式情報に従って作業します。
(公式)http://clang.llvm.org/get_started.html
公式のままの方法でcmakeすると、不要な作業もたくさん含まれてしまうので、必要最小限になるようにします。
以下の情報を参考にしながら、今回の目的にふさわしいオプションを考えました。それでもコンパイルには数時間かかりました。
(参考)https://blog.medalotte.net/archives/1002
(参考)https://qiita.com/akinobufujii/items/5f0f729be620830dae28
gitで取得してきたフォルダは、VSCodeのccls拡張の動作に必要となりますので、消さずにおきましょう。
本当は必要なデータのみを/etcなどに入れるべきなのかも。(Linux苦手)

```
$ cd ~/src
$ git clone https://github.com/llvm/llvm-project.git
$ cd llvm-project
$ mkdir build
$ cd build
$ cmake -GNinja \
        -BRelease \
        -DCMAKE_C_COMPILER=gcc \
        -DCMAKE_CXX_COMPILER=g++ \
        -DLLVM_USE_LINKER=gold \
        -DLLVM_ENABLE_PROJECTS="clang;polly" \
        -DCMAKE_BUILD_TYPE=Release \
        -DLLVM_TARGETS_TO_BUILD="Native" \
        -DLLVM_PARALLEL_LINK_JOBS="1" \
        ../llvm
$ ninja -C Release all
```

## cclsのコンパイル
公式と以下のサイトを参考にします。
gitで取得してきたフォルダは、VSCodeのccls拡張の動作に必要となりますので、消さずにおきましょう。
本当は必要なデータのみを/etcなどに入れるべきなのかも。(Linux苦手)
(公式)https://github.com/MaskRay/ccls/wiki/Build
(参考)https://blog.medalotte.net/archives/473

```
$ cd ~/src
$ sudo git clone --depth=1 --recursive https://github.com/MaskRay/ccls
$ cd ccls
$ mkdir build
$ cd build
$ cmake -H. \
             -BRelease \
             -G Ninja  \
             -DCMAKE_BUILD_TYPE=Release \
             -DCMAKE_CXX_COMPILER=g++-7 \
             -DCMAKE_PREFIX_PATH=~/src/llvm-project/build/Release
$ ninja -C Release all
```

## VSCode(Code - OSS(headmelted))でccls拡張のインストールと設定
以下のページを参考にしながら、ccls拡張を設定します。
先程コンパイルして作成したcclsがVSCodeのccls拡張から起動できるように、ccls拡張のsettingsに以下のようにします。

settings.jsonに、こんな感じのを追記します。
[ctrl]+[,]でSettingsを開いて、画面右上にあるアイコンの右から３つ目が"Open Settings(JSON)"となっています。

```
    "ccls.launch.command": "~/src/ccls/Release/ccls",
    "C_Cpp.autocomplete": "Disabled",
    "C_Cpp.formatting": "Disabled",
    "C_Cpp.errorSquiggles": "Disabled",
    "C_Cpp.intelliSenseEngine": "Disabled",
```

(参考)https://qiita.com/akinobufujii/items/fb55c92c8b5caa018ebb#%E5%AE%9F%E9%9A%9B%E3%81%ABvscode%E3%81%A7%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B

以上でセットアップは完了です。あとは、新しいプロジェクト毎に必要な作業が残っています。

##プロジェクトごとの作業
ひとつ上で紹介したページに書いてあるcompile_commands.jsonの作成をします。
このファイルには、インクルード情報などが含まれていて、補完情報の収集に利用されます。
プロジェクトのcmakeがない場合は、その他の手段で作成します。
一連の作業の後、VSCodeで初めてフォルダを開くとcclsが自動でindex作業を開始します。
画面右下に```ccls: 3/3 jobs```などと表示され、しばらくすると補完やマウスオーバーがきくようになります。
(参考)https://uchan.hateblo.jp/entry/2018/12/29/104132

# まとめと課題など
ようやくVSCodeで補完やマウスオーバーで関数や変数の情報が表示されるようになりました。
VSCodeを使い始めたときは簡単に解決するかと思いましたが、意外と苦労して、１年近くリサーチしていました。

残った課題として、
- llvmとcclsのインストールフォルダはこれで良かったかな？
- ヘッダファイル編集の際、opencvのcv::matなどを使うとundeclaredと警告になる。compile_commands.jsonにはヘッダファイルが含まれていないためだと思われる
- 補完候補がイマイチ納得できない候補になる
などがあります。

Linuxは不慣れなので五里霧中で設定しており、もっと良い方法があるかもしれません。
アドバイスなどありましたら、コメントを頂けると嬉しいです。