BeagleBoneBlackで学ぶYoctoLinuxの基礎 (3) ~helloworldとCMake環境の作成~

## あらまし

[BeagleBoneBlackで学ぶYoctoLinuxの基礎 (2)]()にて、BeagleBoneBlack上でLinuxが動作していることが確認できたため、次にCMkakeを使ったクロスビルド、Gdbを利用したリモートデバッグの環境を整える。

数年前にYoctoを触った時はEclipseのPluginがYoctoから[公式](https://downloads.yoctoproject.org/releases/eclipse-plugin/)で配布されていたが、最近は配布されていないらしい。Google先生に問い合わせたところ、最新のYocto環境に合わせてPluginをビルドするか、VSCodeを使うのが一般的らしく、今回はVSCodeを利用することとした。

## 環境の設定

VSCodeからすべて実行するために、ExtensionをVSCodeにインストールした。

- C/C++ `ms-vscode.cpptools` 
- CMake Tools `ms-vscode.cmake-tools`
- CMake `twxs.cmake`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198826/73db0198-2b65-f196-c1ed-8278824b8fd6.png)

## CMake環境の作成

こちらの[cmake基礎](https://qiita.com/quiqui59911225/items/17fc874cf209c955417d)を参考に、動作検証用の環境を用意した。

### Helloworldの作成

helloworld(`main.cpp`,`hello.cpp`,`hello.hpp`)環境として、以下の3つのファイルを作成した。

```cpp:main.cpp
#include "hello.hpp"

int main() {
    hello();
}
```

```cpp:hello.cpp
#ifndef HELLO_H
#define HELLO_H

void hello();

#endif
```

```cpp:hello.hpp
#include <iostream>
#include "hello.hpp"

void hello() {
    std::cout << "Hello!" << std::endl;
}
```

### CMakeList.txtの作成

まずは、`CMakeLists.txt`を作成した。

将来的にターゲットボードを変更可能とするため、ボードごとに変わらない部分を`common.cmake`、ボードごとに変わる部分は`{ボード名}.cmake`という構成とした。また、__CMakeLists.txt__はCソースと同一ディレクトリに配置した。

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 2.8)

project(test_cmake CXX)
add_executable(a.out main.cpp hello.cpp)

#set(BUILD_TARGET template)
set(BUILD_TARGET bbb)

include(cmake/common.cmake)

if(${BUILD_TARGET} STREQUAL bbb)
    message("BUILD for BBB")
    include(cmake/bbb.cmake)
elseif(${BUILD_TARGET} STREQUAL template)
    message("This is template for Yocto cmake build")
    include(cmake/template.cmake)
endif()
```

### common.cmake

```cmake:common.cmake
# Common CFLAG
set(CMAKE_C_FLAGS "-Wall")
set(CMAKE_C_FLAGS_DEBUG "-g -O0")
set(CMAKE_C_FLAGS_RELEASE "-O3 -s")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})
```

### bbb.cmake

| パラメータ | 設定根拠・パス |
| :--- | :--- |
| CMAKE_SYSTEM_PROCESSOR | ARM 32Bitの場合は`arm`、ARM 64Bitの場合は`aarch64`を指定 |
| CMAKE_SYSROOT | SDKのインストール先を指定 |
| TOOLCHAIN_PREFIX | 各クロスコンパイラの指定に使う |
| COMPILER_FLAG | コンパイラの引数 |

コンパイラの引数は、`source /opt/poky/3.1.6/environment-setup-cortexa8hf-neon-poky-linux-gnueabi`実行後の環境変数等から導出して、`-g -O0`等をデバッグ時につける構成とした。

```console:Ubuntu
> :/opt/poky/3.1.6$ source environment-setup-cortexa8hf-neon-poky-linux-gnueabi 
> :/opt/poky/3.1.6$ echo ${CC}
arm-poky-linux-gnueabi-gcc -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a8 -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/3.1.6/sysroots/cortexa8hf-neon-poky-linux-gnueabi
```

このうち、`arm-poky-linux-gnueabi-gcc`は利用するクロスコンパイラを指定しており、`--sysroot=/opt/poky/3.1.6/sysroots/cortexa8hf-neon-poky-linux-gnueabi`はSYSROOTを指定する部分ではあるが、SYSROOTはCMake上の別のパラメータで設定されるらしく、`CMAKE_C_FLAGS`では指定しない。

```cmake:bbb.cmake
# For BBB
#set(CMAKE_BUILD_TYPE release)
set(CMAKE_BUILD_TYPE debug)

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_SYSROOT /opt/poky/3.1.6/sysroots/cortexa8hf-neon-poky-linux-gnueabi)
set(TOOLCHAIN_PREFIX /opt/poky/3.1.6/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux/arm-poky-linux-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)

set(COMPILER_FLAG " -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a8 -fstack-protector-strong -Wformat -Wformat-security -Werror=format-security")
set(CMAKE_C_FLAGS "${COMPILER_FLAG} ${CMAKE_C_FLAGS}" CACHE STRINGS "" FORCE)
set(CMAKE_CXX_FLAGS "${COMPILER_FLAG} ${CMAKE_CXX_FLAGS}" CACHE STRINGS "" FORCE)

set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
```

その後、__CMakeList.txt__及びCソールのディレクトリにて、以下の通りBuildを実行すると、__a.out__が生成される。同様のことは、VSCodeのExtension (CMake `twxs.cmake`)でも実施可能である。

```console
> mkdir build
> cd build
> cmake ..
> make
```

## まとめ

- 動作確認用の環境を作成した
- あまり組み込みLinux特有の内容はない (sysrootさえ変更すれば、普通のLinuxにも利用可能なはず)