vsomeip 導入 - ビルドとサンプルアプリを作成するまで

1.概要

車載ネットワークが複雑化していき、車の中に特化した仕様である LAN や LIN などが徐々に Ethernet に置き換わる流れが存在します。上位の通信プロトコルには IP が利用されてくことになるのですが、さらにその上に SOME/IP と呼ばれる車両内の独自プロトコルが設計されています。その他にはDDS などの分散型プロトコルも採用が検討されているのですが、どういった技術が選択され、実装に落とし込まれていくかは不透明です。

ここでは上述の一つであるSOME/IP を「利用」することに着目します。具体的には 、SOME/IP そのものの説明・意義・誕生のいきさつ・仕様などは各種ドキュメントや論文に譲り、SOME/IP のサンプル実装である vsomeip の利用開始までの HOWTO を記述しようと思います。 vsomeip は SOME/IP のプロトコルを実装したオープンソースのソフトウェアで、BMWが中心となって結成したGENIVI Alliance と呼ばれる非営利団体が開発しています。SOME/IP の特徴であるサービスディスカバリも実現することが可能です。 SOME/IP のサマリや vsomeip に対して日本語で読めるリファレンスを紹介すると「次世代車載システム向けサービス志向ミドルウェア SOME/IP-SD の性能評価」と呼ばれるテクニカルレポートを読むとわかりやすいと思います。(https://jglobal.jst.go.jp/detail?JGLOBAL_ID=201802221143092759

さて話をもどして、なぜ vsomeip の利用開始までのHOWTOを記事として残そうと思い立ったかですが、Webに落ちている情報だけでは少なくとも僕はすんなりとビルドすらできなかったからです。例えば以下に示すオフィシャルのReadme だけでは舌足らずです。 github.com

さらにチュートリアルやクックブックに相当しそうな Wikiの内容は記述内容が古くて最新版の vsomeip との齟齬が存在します。 (https://github.com/GENIVI/vsomeip/wiki/vsomeip-in-10-minutes)

Web 業界のようにオープンな世界ではなく、車両内の通信という少しニッチな業界であることと、ベンダが提供する SOME/IP を実装した製品ソフトを利用している場合もあるので、困っている人は沢山はいないだろうけど、自分の備忘録のためにもビルドまでの手順を残そうというのが狙いです。

手順やコマンドは、一度実施した内容を再度プレーンな状態のUbuntu で確認しながら記述しましたが、漏れなどが生じているかもしれないです。趣味でやっている内容なので勘弁してほしいです。もっとよい手順もあるかもしれないです。あと、間違いに関して言えば連絡をもらえれば修正や加筆をしようと思います。

2.最終的な構成(必要となるもの)

以下が最終的な構成(必要となるもの)のリストです。あくまで 2020/09/01 時点の情報です。

  • ビルドマシンのホストOS:Ubuntu 18.04

  • vsomeip:3.1.16.1

  • Boost C++ Libraries :Version 1.72.0

  • Google Test:Ver 1.10.0

  • cmake : 3.10.0

  • GNU Make :4.1

  • g++:7.5.0

  • doxygen:1.8.13

  • asciidoc:8.6.10

実はdoxygen や asciidoc などは必須ではなく、vsomeip のビルド時にwarning が出なくなるだけだったりします。が、入れておいてディスクサイズ以外に損することはないと思います。

3.vsomeip のビルド手順

細かな手順の躓きを除けば、ここでの嵌るのはBoost ライブラリのバージョンだと思います。vsomeip のReadme には 1.55 の記述があるのですが、実際にそれを利用するとなぜかビルドできないです。ちなみにvsomeipのビルドスクリプトを確認したのですが、確かに 1.55 でも動作しそうな作りでした。原因がわからずじまいなのですが、今回利用するvsomeip の 3.1.16.1 が対応している最新版のBoost ライブラリを利用すればビルドが可能となりました。この章の内容を実施すると。SOME/IP プロトコル を利用するための共有ライブラリが入手できます。

3-1.apt のアップグレードを行う。

(これは別に必要ないかもしれないけど、Ubuntuだと最初にタイプしてしまう。)

sudo apt update
sudo apt upgrade

3-2.必要なソフトをインストールする

sudo apt install -y git cmake doxygen graphviz asciidoc g++

3-3.Boost ライブラリをビルドし、インストールする。

繰り返しになりますが、どういうわけか vsomeip の Readme に記載のある1.55系を利用すると必要なパッケージが見つからないようでコンパイルできなかったです。 というわけで、Boost ライブラリの Version 1.72.0 をDL します。ちなみに今回利用する vsomeip の 3.1.16.1 は 1.73.x 以上の Boost ライブラリには対応しておらず、1.72.0 が利用できる中で最新の版です。

mkdir third_party && cd third_party
wget https://dl.bintray.com/boostorg/release/1.72.0/source/boost_1_72_0.tar.gz
tar zxvf boost_1_72_0.tar.gz
cd boost_1_72_0

wget コマンドで直接指定しているファイルの URI は下記ページからアクセス可能です。 www.boost.org

Boost をビルドしてインストールします。ここではシステム領域にインストールせず、ホームディレクトリに local ディレクトリを作成し、そこにインストールします。 Boost のビルドは以下が参考になります。Boost のビルドにはそこそこ時間がかかります。 boostjp.github.io

mkdir ~/local
./bootstrap.sh
./b2 install -j2 --prefix=$HOME/local

ホームディレクトリの local を確認すると、include と lib が作成されて中に boost ライブラリが展開されているはずです。

3-4.Google Test を取得し、環境変数 GTEST_ROOT を設定する

Google Test を git で clone します。ちなみに作業はBoost のビルド時に作成したthird_party 下で実施しています。 github.com

git clone https://github.com/google/googletest.git

後の vsomeip のビルド時に、clone したディレクトリを参照する必要があります。参照は環境変数 GTEST_ROOT を用いて実施されます。 GTEST_ROOT には clone して作成されたディレクトリへのパスを指定します。

export GTEST_ROOT=$HOME/third_party/googletest

余談ですが、この環境変数は vsomeip の CMakeLists.txt の内部で利用されることになります。

3-5.vsomeip を取得し、ビルド、インストールする

vsomeip のリポジトリから clone を実施します。念押しですが、利用する vsomeip のバージョンは 3.1.16.1 です。それ以外のことは試していません。 third_party ディレクトリにて、

git clone https://github.com/GENIVI/vsomeip.git

vsomeip のビルドディレクトリを作成し、移動します。

cd vsomeip
mkdir build && build

out-of-source ビルドを実施します。ビルド時にデフォルトの設定を変えることも可能なようなのですが、今回は特に設定しません。ただし一点だけ

To compile vsomeip with signal handling (SIGINT/SIGTERM) enabled, call cmake like: cmake -DENABLE_SIGNAL_HANDLING=1 .. In the default setting, the application has to take care of shutting down vsomeip in case these signals are received.

とあるのでENABLE_SIGNAL_HANDLINGだけは変数設定した状態でビルドしようと思います。

cmake -DENABLE_SIGNAL_HANDLING=1 -DBOOST_ROOT=$HOME/local -DCMAKE_INSTALL_PREFIX=$HOME/local ../

BOOST_ROOT は先ほど作成したboost ライブラリのパスを指定し、CMAKE_INSTALL_PREFIX は コンパイルしたライブラリをインストールする先を指定しています。 作成する vsomeip ライブラリの仕様を変更する変数は ENABLE_SIGNAL_HANDLING のみです。 BOOST_ROOT に関して言えば、vsomeip のCMakeLists.txt に

set (BOOST_ROOT "$ENV{HOME}/local")

のような1行を追加してもよいかもしれないです。 cmake がうまく実行できたらmakeとインストールを実行します。

make && make install

さて、ここまで実施できたら vsomeip の共有ライブラリができているはずです。確認してみましょう。

ls -l $HOME/local/lib/libvsomeip3.so $HOME/local/lib/libvsomeip3-sd.so

シンボリックリンクが作成されていることがわかるはずです。

4.ビルドした vsomeip のライブラリを利用したアプリ作成

この章ではごくごく簡単なvsomeip を利用したアプリの開発に関して記述します。実用性のあるものを作成することが目的でなく、これまでの手順で作成したライブラリをリンクしたアプリが作成できるところまで説明します。この段階で僕がつまずいたのは、冒頭で説明したvsomeip in 10 minutes と呼ばれるWiki にアクセスしてアプリの開発したのですが、内容が古いのでそのままではアプリのビルドができなかった点です。Wikiでは現行のvsomeip はメジャーバージョンが3に上がっているのに対してWiki の内容はメジャーバージョン2 を対象にして記述されています。 (これ以降の内容はcmake や vsomeip のライブラリの使い方を伝える内容の記事ではないので、詳細は割愛します。)

4-1.作業の準備

作業用のディレクトリなどを作成します。

mkdir ~/devapp && cd ~/devapp
touch CMakeLists.txt && mkdir src && touch src/service-example.cpp

4-2.vsomeip のライブラリを利用したアプリのビルドスクリプト作成

4-1で作成した CMakeLists.txt に以下を記述します。

cmake_minimum_required (VERSION 3.10)

set (CMAKE_CXX_FLAGS "-g -std=c++0x")

PROJECT(vsomeipapp C CXX )

set(CMAKE_MODULE_PATH $ENV{HOME}/local/lib/cmake/)
set (BOOST_ROOT $ENV{HOME}/local)

find_package (vsomeip3 3.1.0 REQUIRED)
find_package( Boost 1.72 COMPONENTS system thread log REQUIRED )

add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/src/service-example.cpp)

target_include_directories(
    ${PROJECT_NAME}
    PUBLIC
    $ENV{HOME}/local/include
)

target_link_libraries(${PROJECT_NAME} vsomeip3 ${Boost_LIBRARIES})

4-3.vsomeip を利用したcpp のソースコード作成

4-1で作成した src/service-example.cpp に以下を記述します。

#include <vsomeip/vsomeip.hpp>

std::shared_ptr< vsomeip::application > app;

int main() {
    app = vsomeip::runtime::get()->create_application("World");
    app->init();
    app->start();
}

4-4.アプリのビルドと実行

ビルドディレクトリを作成し、そこでビルドを実行します。

mkdir ~/devapp/build && cd ~/devapp/build
cmake ..
make

これにより vsomeipapp という実行ファイルが出力されているはずです。この実行ファイルは実行時に vsomeip の共有ライブラリを必要とするのですが、システム領域に vsomeip の共有ライブラリをインストールしていないので、ここでは LD_LIBRARY_PATH に一時的にパス設定して実行します。

export LD_LIBRARY_PATH=$HOME/local/lib/
./vsomeipapp

実行すると、以下のような標準出力がなされます。vsomeip を利用したサービスアプリが実行されたことになります。

2020-08-02 00:51:52.714784 [info] Parsed vsomeip configuration in 0ms
2020-08-02 00:51:52.715658 [info] Configuration module loaded.
2020-08-02 00:51:52.715735 [info] Initializing vsomeip application "World".
2020-08-02 00:51:52.716253 [info] Instantiating routing manager [Host].
2020-08-02 00:51:52.716481 [info] create_local_server Routing endpoint at /tmp/vsomeip-0
2020-08-02 00:51:52.716850 [info] Service Discovery enabled. Trying to load module.
2020-08-02 00:51:52.718744 [info] Service Discovery module loaded.
2020-08-02 00:51:52.719359 [info] Application(World, 0100) is initialized (11, 100).
2020-08-02 00:51:52.719670 [info] Starting vsomeip application "World" (0100) using 2 threads I/O nice 255
2020-08-02 00:51:52.720238 [info] main dispatch thread id from application: 0100 (World) is: 7f0484081700 TID: 51986
2020-08-02 00:51:52.721131 [info] shutdown thread id from application: 0100 (World) is: 7f0483880700 TID: 51987
2020-08-02 00:51:52.721336 [info] Watchdog is disabled!
2020-08-02 00:51:52.722262 [info] io thread id from application: 0100 (World) is: 7f04860a3d00 TID: 51985
2020-08-02 00:51:52.722340 [info] io thread id from application: 0100 (World) is: 7f048287e700 TID: 51989
2020-08-02 00:51:52.723635 [info] vSomeIP 3.1.16.1 | (default)
2020-08-02 00:51:52.724215 [info] Network interface "lo" state changed: up

これで、この記事の内容は終わりです。

個人的にはこれから vsomeip のサンプルアプリを作って、なにかしらの評価をしてみたいと思っています。