3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ROS2講座03 colconでの実行ファイルのビルド

Last updated at Posted at 2023-07-17

環境

この記事は以下の環境で動いています。

項目
CPU Core i5-8250U
Ubuntu 22.04
ROS2 Humble

概要

ROS2ではCmakeListに記述をすることで「ビルド」の設定をして、colcon buildでビルドを行うことが出来ます。
しかし「ビルド」は複数のツールにまたがって行われるためにエラー時の解決や、目的の動作をする記述を調べることは容易ではありません。
ここではこの「ビルド」の設定について順を追って解説します。まず注釈として

  • C++パッケージのビルドの設定のみを扱います。pythonパッケージやpure cmakeパッケージの話は扱いません
  • ROS2パッケージの話のみを扱います。ROS1パッケージの話は扱いません。
  • Ubuntu上でのビルドのみを扱います。Win/Mac対応の話はしません。

今回は一番基本的な「実行ファイル」のビルドを見ていきます。

ビルド処理の区分け

ビルド処理は以下の4つに分かれます。

  • (1)プリプロセッサ
    #include等のプリプロセッサを処理します。
  • (2)コンパイラ
    C++のコードをアセンブル言語に変換します。
  • (3)アセンブラ
    アセンブル言語を機械語に変換します。これによって1つのcppファイルから1つのオブジェクトファイルが生成されます。
  • (4)リンカ
    関数呼び出しを買い替えつして複数のオブジェクトファイルを結合します。これによって実行ファイルやライブラリファイルを作成します。

また厳密には「ビルド」に含めませんが生成されたファイルや既存のファイルを再配置する「インストール」のステップがこの後に続きます。

シンプルな実行ファイルをビルド

以下のようなmain関数でprintfを実行するだけの例をビルドしてみましょう。

build_lecture/
├ src/
│ └ exec_sample1/
│ └ main.cpp
└ CMakeList.txt

build_lecture/src/exec_sample1/main.cpp
#include <stdio.h>
int main(int argc, char *argv[])
{
  printf("hello\n");
  return 0;
}

c++コマンドでビルド

c++のソースファイルをビルドする基本はc++コマンドです。以下のcmakeでも最終的には内部的にc++コマンドを実行しています。

cd build_lecture/src/exec_sample1/
c++ main.cpp -o exec_sample1
./exec_sample1 

今回のc++コマンドでは(1)プリプロセッサ~(4)リンカまでの処理を1発で行っています。exec_sample1という実行ファイルが作成されます。

cmakeでビルド

純粋なcmakeだけで先ほどのソースをビルドします。

build_lecture/CMakeList.txt
cmake_minimum_required(VERSION 3.8)
project(build_lecture)

add_executable(exec_sample1
  src/exec_sample1/main.cpp)

install(
  TARGETS exec_sample1
  DESTINATION lib/${PROJECT_NAME}
)
  • add_executableで実行ファイルの作成の指示をします。
  • installは実行ファイルをフォルダに配置する指示です。今回の記述ではexec_sample1をlib/${PROJECT_NAME}に配置することになります。後ほどのcolconでの例で使います。
cd build_lecture/
mkdir build
cd build/
cmake ..
make
./exec_sample1 

colconでビルド

cmakeのプロジェクトはそのままcolconで使えるので上記の「cmakeでビルド」のまま実行可能です。

cd ros2_ws
colcon build
ros2 run build_lecture exec_sample1

colcon buildを実行するとros2_ws/install/build_lecture/lib/build_lecture/exec_sample1の実行ファイルが生成・配置されます。ros2 runではこのファイルを実行しています。

複数のcppファイルからなる実行ファイルをビルド

build_lecture/
├ include/
│ └ build_lecture/
│ └ exec_sample2/
│ └ printer.hpp
├ src/
│ └ exec_sample2/
│ ├ printer.cpp
│ └ main.cpp
└ CMakeList.txt

build_lecture/include/build_lecture/exec_sample2/printer.hpp
#include <stdio.h>
void print_data(void);
build_lecture/src/exec_sample2/printer.cpp
#include <build_lecture/exec_sample2/printer.hpp>
void print_data(void) {
  printf("execute print_data\n");
}
build_lecture/src/exec_sample2/main.cpp
#include <build_lecture/exec_sample2/printer.hpp>
int main(int argc, char *argv[])
{
  print_data();
  return 0;
}

c++コマンドでビルド

複数のソースファイルからなるコードについては、cppファイルを1つずつビルドしてオブジェクトファイルを作成して、それらを最後にリンクします。

c++ -c src/exec_sample2/main.cpp -I include/ 
c++ -c src/exec_sample2/printer.cpp -I include/
c++ main.o printer.o -o main
./main
  • 1,2行目でそれぞれのソースファイルについて(1)プリプロセッサ~(3)アセンブラの作業をします。これによってmain.oprinter.oの2つの実行ファイルを得ます
    • -I#includeでの探索フォルダの追加の指定をします。
    • 例えば1行目の処理の指定ファイルだけでは、print_data()の実装が不十分です。このようにオブジェクトファイルでは実装が不十分でも処理は進みます。
    • それぞれのオブジェクトファイルにどのようなシンボルがあるかはnmコマンドで分かります。ざっくり解説するとTが定義済みのシンボル、Uが未定義のシンボルです。
      • シンボル名は関数名の前後に引数や返り値に対応する文字が追加されたものになります。これを名前修飾と呼びます。(ちなみに名前修飾のルールはコンパイラごとに違います)
シンボル情報の表示
$ nm main.o 
0000000000000000 T main
                 U _Z10print_datav
$ nm printer.o 
                 U puts
0000000000000000 T _Z10print_datav
  • 3行目で(4)リンカの作業をしています。
    • この時に実装が不十分にならないように必要なだけのオブジェクトファイルを取り込む必要があります。
    • オフジェクトファイルが足りないと以下のように未定義シンボルが残るエラーが出ます。
未定義シンボルが残る例
$ c++ main.o 
/usr/bin/ld: main.o: in function `main':
main.cpp:(.text+0x14): undefined reference to `print_data()'
collect2: error: ld returned 1 exit status

cmakeでビルド

純粋なcmakeだけで先ほどのソースをビルドします。

build_lecture/CMakeList.txt
cmake_minimum_required(VERSION 3.8)
project(build_lecture)

add_executable(exec_sample2
  src/exec_sample2/main.cpp
  src/exec_sample2/printer.cpp
)
target_include_directories(exec_sample2
  PUBLIC include
)

install(
  TARGETS exec_sample2
  DESTINATION lib/${PROJECT_NAME}
)
cd build_lecture/
mkdir build
cd build/
cmake ..
make
./exec_sample1 

colconでビルド

前の例と同じようにcmakeの例をそのままcolconでビルドできます。

cd ros2_ws
colcon build
ros2 run build_lecture exec_sample2

参考

目次ページへのリンク

ROS2講座の目次へのリンク

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?