組込み開発 cheat sheet

# Linuxコマンド
## 検索
### ファイル検索
```
find / -name "*.h"  2>/dev/null
find / -name "*.h"  2>/dev/null -ls
```

### 拡張子を指定して再帰的にgrep
```
find /usr -name "*.h" -or -name "*.hpp" | xargs grep -n -2 "jpeg_destroy_decompress"
```

### 行数表示してcat
```
cat -n XXX
```

### 最近更新されたファイル
```
find . -mmin -1 -ls
find . -type d -mmin -1 -ls
find . -type f -mmin -1 -ls
```

## ファイルのアップロード/ダウンロード
### 同期
```
rsync -auv dirOnHost  pi@192.168.1.88:/home/pi/mirror/
```

### ホスト⇒ターゲットへコピー (don't forget dot(.))
```
scp fileOnHost.txt pi@192.168.1.88:.
scp -r dirOnHost pi@192.168.1.88:.
```

### ターゲット⇒ホストへコピー (don't forget dot(.))
```
scp pi@192.168.1.88:~/fileOnTarget.txt .
scp -r pi@192.168.1.88:~/dirOnTarget .
```

### sftp
```
sftp pi@192.168.1.88
> put fileOnHost.txt
> get fileOnHost.txt
```

### その他
```
# 受付中ポート確認
netstat -nlt

# 簡易webサーバ
python -m http.server

# 頻繁にRSA keyが変わるターゲットへのssh
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@192.168.1.87

```
### ライブラリのパス追加
カレントディレクトリや実行ファイルと同じ場所にあるsoファイルをロードしたいとき。

```
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./:
```

### 画面の出力先を変える
SSHからログインして操作しているが、画面はデバイスに接続されたHDMIに出力したいとき

```
export DISPLAY=:0
```

### ARM用クロスコンパイラ
- Linux, armel(浮動小数点演算ハードウェア非搭載), 用gcc
	- `sudo apt-get install gcc-arm-linux-gnueabi`
	- `sudo apt-get install g++-arm-linux-gnueabi`
- Linux, armhf(浮動小数点演算ハードウェア搭載), 用gcc
	- `sudo apt-get install gcc-arm-linux-gnueabihf`
	- `sudo apt-get install g++-arm-linux-gnueabihf`
- ベアメタル用gcc
	- `sudo apt-get install gcc-arm-none-eabi`

コンパイラ名は`arm-linux-gnueabi-gcc`とかになる
(`arm-linux-gnueabi-g++`というものは存在しないのかな?)

- `apt install -y crossbuild-essential-arm64` を使った方が良いかも
    - `aarch64-linux-gnu-gcc` , `aarch64-linux-gnu-g++`
    - ライブラリは、 `/usr/aarch64-linux-gnu/lib/` に格納される
        - ターゲット環境でglibcのバージョン不一致などが発生した場合には、↑をターゲットにコピーして、LD_LIBRARY_PATHで指定すれば動くかも


# Linuxコマンド (Target)
ターゲット上でよく使うコマンド。メモリ使用量とか

```
ps aux | grep XX
kill -9 464

cat /proc/cpuinfo
cat /proc/interrupts
cat /proc/meminfo
cat /proc/464/maps	# プロセスのアドレスマップ
cat /proc/464/status	# プロセスのステータス
cat /proc/464/stack	# 今現在のスタック情報
cat /proc/464/status | grep Vm		# スタックなどのメモリ使用量

strace ./a.out

dmesg
```

# C/C++
## 環境を調べる
### includeパスを調べる
実際にどこのヘッダが使われているかの調査

```
gcc main.cpp -v
```

### makeで実行されている内容の詳細を表示する

```
make V=1
```

### 使用されているコンパイラ等の場所を取得
makefile等をたどっていけば分かるけど、面倒な時  
調査中。コード中のマクロやpragmaで何かないかと思ったけど、環境変数を見るくらいしかなさそう。

ビルドオプションは、`make VERBOSE=1`でみられる
gccでインクルードパスを見るには、`g++ main.cpp -H`

## バイナリ解析
クロスコンパイルの時は、コンパイラ(arm-linux-gnueabihf-gcc)と同じプリフィックスを持ったツールを使うこと。

### 逆アセンブル
```
objdump -S a.out
objdump -S module.o
```

### セクション情報
```
readelf -S a.out
objdump -h a.out
```

### コードサイズ取得
```
size a.out
```

### シンボル表示
```
nm main.o
```
### 使用するライブラリの表示
```
ldd a.out
```

### addr2line
Exceptionした時のPC(プログラムカウンタ)から、問題のコードの場所を探す

```
addr2line a.out 0x110a4
```

## コーディング
### Enter入力を待たずにgetcharする 1
デバッグコマンド入力や、即時エコーバックが必要な時。

Windowsなら、`conio.h`をインクルードして、`getch()`、`getche()`、`_getch()`
Linuxなら、`curses.h`

それ以外なら、バッファを無効にしてしまう。

```c
	setvbuf(stdin, NULL, _IONBF, 0);
	while(1){
		char c = getchar();
		LOG("input = %c\n", c);
	}
```

### Enter入力を待たずにgetcharする 2
Linuxのみ

```c
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <termios.h>

void DisableNonBlocking()
{
    int32_t flags = fcntl( fileno( stdin ), F_GETFD, NULL );
    flags &= ~O_NONBLOCK;
    fcntl( fileno( stdin ), F_SETFL, flags); 
}

void EnableNonBlocking()
{
    struct termios settings;
    tcgetattr( fileno( stdin ), &settings );
    // settings.c_lflag       &= ~( ECHO | ICANON );
    settings.c_lflag       &= ~( ICANON );
    tcsetattr( fileno( stdin ), TCSANOW, &settings );
    fcntl( fileno( stdin ), F_SETFL, O_NONBLOCK );
}

int main()
{
    EnableNonBlocking();
    for (int cnt = 0; ; cnt++) {
        int key = getchar();
        if (key > 0) {
            printf("%d: %c (%x)\n", cnt, key, key);
            if (key == 'q') break;
        }
    }
    DisableNonBlocking();
    return 0;
}
```

# cmake
## cmakeで作られた他ライブラリを読み込み、定義された変数を確認する
他ライブラリの`ooo.cmake` や `oooConfig.cmake` を使う方法

```cmake
    get_directory_property(_vars_before VARIABLES)
    find_package(ncnn REQUIRED PATHS ${CMAKE_CURRENT_LIST_DIR}/../ncnn_prebuilt/ncnn-20211208-windows-vs2019/x64/lib/cmake)
    get_directory_property(_vars VARIABLES)
    list(REMOVE_ITEM _vars _vars_before ${_vars_before})
    foreach(_var IN LISTS _vars)
        message(STATUS "${_var} = ${${_var}}")
    endforeach()
```

# gdb
`-g3`オプションをつけてコンパイルする
##　コマンド
```
quit	# 終了
start	# b main, runと同じ
b main	# 関数の先頭にブレークポイント
b file.c:10	# ファイルの指定行にブレークポイント
b ClassA::funcA	# クラスのメンバ関数の先頭にブレークポイント
run		# run
c	# 実行再開
n	# 関数飛ばし実行
s	# ステップ実行
finish	# 関数を抜けるまで実行

i b	# ブレークポイント一覧表示
d XXX	# ブレークポイント削除

p var # 変数表示
p var = XXX # 変数に値を代入

i locals	# ローカル変数一覧
i args		# 引数一覧

f	# 現在の場所
where	# 現在の場所
up	# スタックフレームを上げる (呼び出し元のレベルにする)
down	# スタックフレームを下げる
l	# ソースコード表示
bt	# バックトレース表示
```

## 実行中プロセスへのアタッチ
```
ps aux | grep a.out
gdb -p 1012
```

## コアダンプの解析
```
ulimit -c unlimited
gdb ./a.out core.dump
bt
```

# パフォーマンス解析
```sh
sudo apt install linux-perf
perf_4.19 list
sudo perf_4.19 stat -I 100 -a -e cache-misses
sudo perf_4.19 stat -I 100 -a -e armv8_cortex_a72/bus_access/
```

# ハードウェア
## Active High/Low Reset
ここでいうActiveとはリセットをかけるということ。回路がActiveになるということではない。そのため、

- Active High Reset
    - High("1")にすることでリセットがかかる。通常時はLow("0")にすることでリセットが解除され、回路が通常動作する。
- Active Low Reset
    - ↑の逆

# TeraTerm
todo

# バッチファイル
指定したフォルダ内の指定の拡張子に対して何らかの処理をする
(引数で渡されたフォルダ内のすべてのjpgファイルの先頭に現在の日付をつけてコピー)

```bat
@echo off

cd /d %~dp0

for /f "usebackq tokens=*" %%i in (`dir /s /b %1\*.jpg`) do (
	call :run "%%i"
)

exit /b

:run
	call :get_time_str
	set NEW_FILENAME=%TIME_STR%_%~n1.jpg
	copy %1 "%NEW_FILENAME%"
	exit /b

:get_time_str
	set yyyy=%date:~0,4%
	set mm=%date:~5,2%
	set dd=%date:~8,2%
	set time2=%time: =0%
	set hh=%time2:~0,2%
	set mn=%time2:~3,2%
	set ss=%time2:~6,2%
	set TIME_STR=%yyyy%%mm%%dd%%hh%%mn%%ss%
	exit /b
```

# シェルスクリプト
指定したフォルダ内の指定の拡張子に対して何らかの処理をする

```bash
#!/bin/bash
set -eu

SEARCH_PATH=$1

run () {
    base_name=`basename $1 .jpg`
    echo "$1"
    echo "$base_name"
}

# for image_file in `find $SEARCH_PATH -name "*.jpg" | sort | grep -e "..\.jpg" -`; do
for image_file in `find $SEARCH_PATH -name "*.jpg" | sort `; do
    run "$image_file"
done
```

# その他
## 2進数のビット数から10進数の桁数に変換
n-bitの2進数は、10進数だと、`N = n x 0.3010299`桁になる(小数は繰り上げ)。
(N = log_10(2^n) = log_2(2^n) / log_2(10) = n / log_2(10) = n * log_10(2) = n * 0.3010299)

## SSH先でsudo権限でXアプリケーションを動かして表示したい
```sh
touch ~/.Xauthority
xauth generate :0 . trusted 
xauth nlist $DISPLAY | sudo xauth nmerge -
```

# Raspberry Pi
## よく使うコマンド
```
sudo shutdown -h now
sudo reboot yes
crontab -e
crontab -l
crontab -r
```

## ヘッドレスセットアップ
- wifi設定
    - `/boot/wpa_supplicant.conf` に以下を追加

```txt:wpa_supplicant.conf`
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
	ssid="hoge"
	psk="fuga"
	key_mgmt=WPA-PSK
	scan_ssid=1
}
```
- ssh
    - `/boot/` に、`ssh` というファイルを作る

## スワップ
```
sudo nano /etc/dphys-swapfile 
sudo /etc/init.d/dphys-swapfile restart
```

## VNC
### 解像度を固定にする
- HDMI接続していないと、画面が出力されなかったり、解像度が640x480固定になってしまうことがある。
	- ~~GUIのRaspberry Pi Configurationから、CAE 1280x720あたりを選択する~~
		- 最近のバージョンだと未対応
		- Screen Configurationに設定が分けられたが、そちらを変更してもHDMIが刺さっていないと無効になる (コンポーネントの設定が使用されるっぽい？)
	- `sudo nano /boot/config.txt` で設定を変更する
		- `hdmi_force_hotplug=1`
		- `hdmi_group=1`
		- `hdmi_mode=4`

## カメラ
`v4l2-ctl -d /dev/video0 --list-formats-ext`
`raspivid --demo`

## Python
### virtualenv
```sh
sudo pip install virtualenv
sudo pip install virtualenvwrapper

# ↓はOpenCV用
#sudo apt-get install libatlas3-base libwebp6 libtiff5 libjasper1 libilmbase12 libopenexr22 libilmbase12 libgstreamer1.0-0 libavcodec57 libavformat57 libavutil55 libswscale4 libqtgui4 libqt4-test libqtcore4

nano ~/.bashrc 
>>> 以下を追加
export LC_ALL="en_US.UTF-8"
export LC_CTYPE="en_US.UTF-8"
### Virtualenvwrapper
if [ -f /usr/local/bin/virtualenvwrapper.sh ]; then
    export WORKON_HOME=$HOME/.virtualenvs
    source /usr/local/bin/virtualenvwrapper.sh
fi
<<<
# ターミナル再起動

mkvirtualenv --python=python3 py3_env1
deactivate
workon py3_env1

pip install --upgrade setuptools
pip install opencv-python
```


# Jetson Nano
## USBメモリを好きな場所に自動マウントする
https://www.youtube.com/watch?v=ihCzhNmj4eM のやり方でもいいけど、マウント先を変えたいので自分でやった。
標準だと、USBメモリは`/media/takeshi/usbm` に自動マウントされる。
この場所を変えてみる。
(`/dev/sda1` 等を使うと、場合によっては変わってしまう可能性があるので、UUIDで指定する)

```sh:
# USBメモリのUUIDを探す
sudo blkid | grep sda
> /dev/sda1: LABEL="usbm" UUID="89d03081-d990-4d51-8f53-5ef4df35fb44" TYPE="ext4" PARTUUID="babe5f12-01"

# 既存のマウントを解除し、新しいマウントポイントを作成
sudo umount /media/takeshi/usbm
sudo mkdir /mnt/usbm

# とりあえず手動でマウント
# sudo mount /dev/sda1 /mnt/usbm/ -t ext4
sudo mount UUID="89d03081-d990-4d51-8f53-5ef4df35fb44" /mnt/usbm -t ext4

# 自動マウントさせる
sudo nano /etc/fstab
>>> 以下を追加
UUID=89d03081-d990-4d51-8f53-5ef4df35fb44 /mnt/usbm ext4 defaults 0 0
```

## Swap設定
https://www.jetsonhacks.com/2019/04/14/jetson-nano-use-more-memory/


## インストール～環境設定、Python関係
https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit 
https://docs.nvidia.com/deeplearning/dgx/install-tf-xavier/index.html
https://qiita.com/take-iwiw/items/a3bd8d0527dec431ef0f


```sh:Python仮想環境インストール～Tensorflowインストールまで
sudo apt-get install python3-opencv
sudo apt-get install libhdf5-serial-dev hdf5-tools
sudo apt-get install zlib1g-dev zip libjpeg8-dev libhdf5-dev 
sudo apt-get install python-pip python3-pip
sudo pip install virtualenv
sudo pip install virtualenvwrapper

nano ~/.bashrc 
>>> 以下を追加
### Virtualenvwrapper
if [ -f /usr/local/bin/virtualenvwrapper.sh ]; then
    export WORKON_HOME=$HOME/.virtualenvs
    export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
    export VIRTUALENVWRAPPER_VIRTUALENV=/usr/local/bin/virtualenv
    source /usr/local/bin/virtualenvwrapper.sh
fi
<<<
# ターミナル再起動

mkvirtualenv --python=python3.6 env_py36_tfgpu_01

pip install --upgrade setuptools
pip install numpy grpcio absl-py py-cpuinfo psutil portpicker grpcio six mock requests gast h5py astor termcolor
pip install --pre --extra-index-url https://developer.download.nvidia.com/compute/redist/jp/v42 tensorflow-gpu
pip install Pillow

python
>>> import tensorflow as tf
>>> tf.__version__
```

## Python3用OpenCV3インストール
JetPackの場合、OpenCV3は最初から入っている。ただし、Python2とC用ライブラリ(/usr/lib/libopencv_core.so.3.3.1)のみ。
Python3用には別途インストールが必要(`sudo apt-get install python3-opencv`)
また、仮想環境からうまく呼ぶことが出来なかったので、手動でシンボリックリンクを張る (参照: https://qiita.com/hiiguruma/items/3876db288e5233250ee4)
コピー先は仮想環境名に応じて適宜書き換え

```sh
find / -name "*cv2*"  2>/dev/null    # 念のため元の場所を探す
ln -s /usr/lib/python3/dist-packages/cv2.cpython-36m-aarch64-linux-gnu.so ~/.virtualenvs/py3_env1/lib/python3.6/site-packages/cv2.so
```

## aptインストールでエラー
```
E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
```

といったエラーが出る場合は、aptの定期アップデートが邪魔している可能性有。
以下コマンドで自動アップデートを無効にする

```sh:apt自動アップデート無効
sudo systemctl disable apt-daily-upgrade.service
sudo systemctl disable apt-daily-upgrade.timer
sudo systemctl disable apt-daily.timer
sudo nano /etc/apt/apt.conf.d/20auto-upgrades    # 0に書き換え
```

## X11 Forwardingでアプリケーション画面を転送する
- インストール: https://sourceforge.net/projects/vcxsrv/files/latest/download
- 起動: Multiple windows(お好みで), Display number = -1(自動) -> Start no client

### TeraTermから接続する場合
- 普通通りにssh接続する
- Setup -> SSH Forwarding -> X Forwardingの`Display remote X application on local X server` にチェック
- Setup -> Save setupで設定を保存する(TERATERM.INI)
- 一度切断して、再度SSH接続する
- `xeyes &` などで画面がWindows側に飛ぶ
	- DISPLAY設定は無くて大丈夫だった

### MSYS, GitBashなどから接続する場合(Linuxも同じ)
```sh:ホストPCのターミナル(MSYSなど)
export DISPLAY=localhost:0.0  # 接続前にローカルのターミナルで設定する。なくても良いかも
ssh -X -Y takeshi@192.168.1.115
xeyes &
```

うまくいかないときはssh設定(/etc/ssh/sshd_config) を見てみる
(デフォルト設定で大丈夫だった。`#X11DisplayOffset 10` もコメントアウトされてた。けど、DISPLAY番号の「10」はどこから来たのだろう。
とりあえず`netstat -at` で確認したら6010ポートだったから、6000+10で10にしてみたけど、この「10」がどこから来たのか不明）

ホストがUbuntuなどのLinux PCの場合は、Xサーバソフトのインストールは不要

WindowsのSSHターミナルからchromium-browserを実行したら、うまく飛んでくれなかった。 Linuxからは出来たので、リモート側(Jetson側)というよりかは、ローカル側(vcxsrv)に原因があるのかも。 `export LIBGL_ALWAYS_INDIRECT=1` してもダメだった。


## VSCodeインストール
https://devtalk.nvidia.com/default/topic/1049448/jetson-nano/quick-build-guide-for-visual-studio-code-on-the-nano/

```sh
sudo apt install curl

# Yarn package repo
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list

# Install packages
sudo apt update
sudo apt install -y libx11-dev libxkbfile-dev libsecret-1-dev fakeroot npm curl nodejs nodejs-dev yarn

# Clone repo
git clone https://github.com/Microsoft/vscode.git

pushd vscode

# Reduce max_old_space_size
sed -i 's/4095/2048/g' package.json

# Kill the UI to free up memory ### WARNING THIS WILL DROP YOU TO A CONSOLE
sudo systemctl isolate multi-user

# Fetch deps, build, and create deb
yarn
yarn run gulp vscode-linux-arm64-min
yarn run gulp vscode-linux-arm64-build-deb
sudo dpkg -i ./.build/linux/deb/arm64/deb/code-oss_1.??.?-*_arm64.deb

# Reboot
code-oss

sudo nano /usr/share/code-oss/resources/app/product.json
>>> 以下を追記
	"extensionsGallery": {
		"serviceUrl": "https://marketplace.visualstudio.com/_apis/public/gallery",
		"cacheUrl": "https://vscode.blob.core.windows.net/gallery/index",
		"itemUrl": "https://marketplace.visualstudio.com/items"
	}

```


## メモ
- JetPack(Jetson Nano Developer KitのSDカードイメージ) を使用する場合は、NVIDIA SDK Managerは不要
- GPU使用率は、`tegrastats` コマンドの`GR3D_FREQ` の右のパーセンテージの数字

# Google Coral Dev Board (Edge TPU)
## インストール(Ubuntu on VirtualBox)
- Virtual Boxからでも問題なくインストールできた。
- シリアルはWindows側接続(TeraTermなど)でOK (要: CP210x_Universal_Windows_Driver)
- fastbootのときは、`FSL USB download gadget [9999]` をUbuntu側に接続する
    - 念のため、設定->USB デバイスフィルタに追加
- ファームアップ後、MDTを使うときは、`Google,LLC Mendel [0409]` をUbuntu側に接続する

Windowsからでもがんばればできそうだけど、必要なのはインストール時だけなので、素直にUbuntuでインストールした

## OpenCV
`sudo apt install libopencv-dev`

## ネットワーク関係
- `ifconfig` の代わりに`ip address`
- WiFi設定は、`nmtui`

## SSHにパスワードログインする
デフォルトだと公開鍵/秘密鍵のペアをMDTに作って、秘密鍵を登録しているホストからじゃないとSSH接続できない。

Dev Boardターミナル上で、`sudo nano /etc/ssh/sshd_config` をして、　`PasswordAuthentication yes` に書き換える
セキュリティが気になる場合は、新規ユーザを追加して、mendelを削除

`ssh mendel@192.168.1.36`

## 動作クロック最大化
```sh
sudo apt install -y cpufrequtils
sudo cpufreq-set -g performance
# sudo cpufreq-set -f 1.5GHz
cpufreq-info
sudo cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
```

## EdgeTPU
### TPU一覧と指定
```python
from edgetpu.basic.basic_engine import BasicEngine
from edgetpu.basic import edgetpu_utils
edgetpu_utils.ListEdgeTpuPaths(edgetpu_utils.EDGE_TPU_STATE_NONE)
('/dev/apex_0', '/sys/bus/usb/devices/2-1')

# engine = BasicEngine(MODEL_NAME, "/dev/apex_0")              # Internal TPU
engine = BasicEngine(MODEL_NAME, "/sys/bus/usb/devices/2-1")   # USB TPU
```

# OpenCV
## OpenCVインストール for ARMボード(native)
https://medium.com/@balaji_85683/installing-opencv-4-0-on-google-coral-dev-board-5c3a69d7f52f

```sh:OpenCVインストール全コマンド
sudo apt install -y build-essential cmake unzip pkg-config
sudo apt install -y libjpeg-dev libpng-dev libtiff-dev
sudo apt install -y libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
sudo apt install -y libavresample-dev
sudo apt install -y libxvidcore-dev libx264-dev
sudo apt install -y libgtk-3-dev
sudo apt install -y libatlas-base-dev gfortran
sudo apt install -y libtbb-dev libeigen3-dev
sudo apt install -y libhdf5-dev
sudo apt install -y python-dev python3-dev

## Create swapfile
# sudo fallocate -l 1G /swapfile
# sudo chmod 600 /swapfile
# sudo mkswap /swapfile
# sudo swapon /swapfile

## Format SD card
# sudo mkfs /dev/mmcblk1

## Mount SD card
# sudo mount /dev/mmcblk1 /mnt
# sudo chmod go+w /mnt/

# Get source code
cd /mnt
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.5.2.zip
unzip opencv.zip
cd opencv-4.5.2
mkdir build
cd build

# Build
cmake \
 -D CMAKE_BUILD_TYPE=RELEASE \
 -D CMAKE_INSTALL_PREFIX=/usr/local \
 -D ENABLE_NEON=ON \
 -D WITH_TBB=ON \
 -D WITH_LIBV4L=ON \
 -D WITH_V4L=ON \
 -D BUILD_opencv_python2=ON \
 -D BUILD_opencv_python3=ON \
 -D OPENCV_PYTHON2_INSTALL_PATH=/usr/local/lib/python2.7/dist-packages \
 -D OPENCV_PYTHON3_INSTALL_PATH=/usr/local/lib/python3.5/dist-packages \
 ..

make -j4
sudo make install
sudo ldconfig
```

## OpenCV Build for Android (Cross Compile on Windows)
- Requirements
    - Python environment (eg. Anaconda)
    - Android SDK
    - Android NDK
    - Download opencv and opencv_contrib
- Python端末上で、ダウンロードしたopencvソースの`opencv\platforms\android` へcd
- 以下コマンドを実行 (Miniconda Powershellの場合)

```sh
python .\build_sdk.py `
--ndk_path C:\Users\aaa\AppData\Local\Android\sdk\ndk\21.3.6528147 `
--sdk_path C:\Users\aaa\AppData\Local\Android\sdk `
--extra_modules_path C:\devel\opencv_contrib\modules `
--no_samples_build true
```



# VirtualBox
## 共有フォルダマウント
`sudo mount.vboxsf -o rw,uid=1000,gid=1000 devel /home/iwatake/Desktop/devel`

「自動マウント」を有効にしたら不要。権限の設定とかをしたい場合には自分でマウントした方が良いのかも。

## Windowsとの共有フォルダ内でシンボリックリンクを作れるようにする
シンボリックリンクを作ろうとすると、`ln: failed to create symbolic link xxx : Read-only file system`  というエラーが出る。

- 管理者としてコマンドプロンプトを開く
- 下記コマンドを実行する (VNの名前が`xubuntu18` 、共有フォルダの名前が `devel` の場合)

```txt:コマンドプロンプト(管理者として実行)
cd C:\Program Files\Oracle\VirtualBox
# VBoxManage setextradata VMの名前 VBoxInternal2/SharedFoldersEnableSymlinksCreate/共有フォルダの名前 1
# VBoxManage startvm VMの名前
VBoxManage setextradata xubuntu18 VBoxInternal2/SharedFoldersEnableSymlinksCreate/devel 1
VBoxManage startvm xubuntu18
```

- Windows 10 Proの場合は、ローカルグループポリシーエディター(gpedit.msc)で、一般ユーザにもシンボリックリンクの作成権限を与えることで対応可能。Homeの場合は使えないので、管理者として実行する必要がある。
- VirtualBox(GUI)を管理者として実行、だとうまく動かなかった。↑のコマンドプロンプトからだとうまくいった