Bulding with Yocto

Hello,

We would like to use MAVSDK on an ARM Cortex A9 based Companion Computer (connected to the drone’s PX4 Flight Controller) running a bare-bone Yocto-generated Linux.

As anyone tips on how to build the MAVSDK C++ library from source for this kind of platform?

Thank you!

Best regards.

Jean-Christophe MATHAE

I assume you have seen the build instructions here?

https://mavsdk.mavlink.io/main/en/cpp/guide/build.html#building

And for cross compilation, we usually use dockcross:
https://mavsdk.mavlink.io/main/en/cpp/guide/build_mavsdk_server.html#cross_compilation_dockcross

Thank you for your reply!

Clearly the MAVSDK cmake build process seems “too complex” to build with the Yocto SDK…
And I have not yet tried the dockcross process, as it seems dedicated to the server, which I do not need as we will use C++.

I could perhaps use dockcross for the C++ part with the option MAKE_INSTALL_PREFIX…

Best regards.

Jean-CHristophe MATHAE

But I must confess that I am quite new to Yocto.

After a few weeks of errance the solution seems to be:

  1. to build a Yocto SDK including cmake, that is among other things with the line
    TOOLCHAIN_HOST_TASK_append = " nativesdk-cmake"
    in the local.conf file

  2. to install this SDK properly.

Gook luck!

Best regards.

1 Like

MAVSDK mainly uses plain cmake. For Yocto, I assume you would want to build without SUPERBUILD (which is our helper to build all dependencies) and build the dependencies yourself.

Let me ping @JonasVautherin to help you.

Phew!

At long last I have been able to build and run a MAVSDK C++ library-based C++ app on my Yocto target! This target is based on an armv7 chip.

I achieved this “extraordinary” feat in two small (in retrospect) steps:

First step:
Building the library as a static one using dockcross and the macro BUILD_SHARED_LIBS=OFF in the first “configure” sub-step:
./dockcross-linux-armv7 cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=MAVSDK/install/armv7/Debug -BMAVSDK/build/armv7/Debug -H.

./dockcross-linux-armv7 cmake --build MAVSDK/build/armv7/Debug --target install -j8

Second step:
Compiling the C++ code of my app inside this dockcross bash shell, entered with
./dockcross-linux-armv7 bash
and using the cross-compiler pointed to by the bash variable $CXX, and requesting a fully statically linked executable with the gcc “-static” command line switch:

$CXX -O -IMAVSDK/install/armv7/Debug/include -IMAVSDK/install/armv7/Debug/include/mavsdk my-mavsdk-app.cpp MAVSDK/install/armv7/Debug/lib/libmavsdk.a -static

(By chance the generated executable is an ELF 32-bit LSB executable, ARM, EABI5 version 1 (GNU/Linux), statically linked, for GNU/Linux 5.4.0, and we use Yocto Dunfell which uses the kernel 5.4.142. Will this work for other kernels?)

Best regards.

Jean-Christophe MATHAE

1 Like

I wouldn’t say so. I did it here two years ago, seemed pretty trivial to me :thinking:. Is something not working anymore?

What’s complex in the MAVSDK build system is the superbuild. And the reason for the superbuild is that people generally don’t really know how to deal with dependencies. But if you do, just don’t use the superbuild and then it’s just a pretty simple CMake project handling dependencies with find_package (the way it should be done, IMO).

1 Like

I am using MAVSDK in a yocto environment with a python application for quite a while now and stumbled over this thread because I am currently running into issues when I tried to use this setup for c++ as well.

@JonasVautherin I didn’t tested your recipe but there is at least one thing which should not work any more: You need to allow internet access during the configure step with do_configure[network] = "1" as during that phase the MAVLink repo is cloned.

As @JulianOes mentioned, I disabled the superbuild and added the required libraries as dependency to the recipe.

For python I only need to get the mavsdk-server so I successfully used the following options:

EXTRA_OECMAKE = "-DCMAKE_BUILD_TYPE=Release -DBUILD_MAVSDK_SERVER=ON -DSUPERBUILD=FALSE -DBUILD_SHARED_LIBS=OFF"

But when I try to use this for a c++ application, the app can’t be configured as cmake does not find curl although curl and FindCURL.cmake are definitely available.

I tried to build mavsdk as a shared library as well but this caused trouble during linking json-cpp so that the mavsdk build task fails.

@mattes-bru: How does your recipe look like? Mine was working (a few years ago), also with jsoncpp. I don’t think it has changed fundamentally since then, except that MAVLink is not included in the MAVSDK sources anymore.

But at least on main, it now fetches MAVLink with find_package(MAVLink REQUIRED), which means that you should make a Yocto package out of MAVLink and have MAVSDK depend on it.

I am using the 1.4.7 release and my recipe is currently:

DESCRIPTION = "API and library for MAVLink compatible systems written in C++17"
HOMEPAGE = " https://mavsdk.mavlink.io"
SECTION = "libs/network"
LICENSE = "BSD-3-Clause"

inherit pkgconfig cmake python3native

LIC_FILES_CHKSUM = "file://LICENSE.md;md5=b2988a8644dbb23689bbfb7ef6b0f1da"

PR = "r0"

SRCREV = "34b0c051f70b7018e3d98c2fe0e78677d4c3af14"
SRC_URI = "\
	gitsm://github.com/mavlink/MAVSDK.git;protocol=https;branch=v1.4 \
	"

S = "${WORKDIR}/git"

DEPENDS = " \
	libtinyxml2 \
	curl \
	jsoncpp \
	grpc \
	openssl \
	protobuf-native \
	grpc-native \
	python3-native \
	protoc-gen-mavsdk-native \
	python3-protobuf-native \
	python3-jinja2-native \
	python3-future-native \
	 "


do_configure[network] = "1"

do_compile:prepend() {
	cd ${S}
	tools/generate_from_protos.sh
}

EXTRA_OECMAKE = "-DCMAKE_BUILD_TYPE=Release -DBUILD_MAVSDK_SERVER=ON -DSUPERBUILD=FALSE -DBUILD_SHARED_LIBS=OFF"

As mentioned, this recipe works fine to build the mavsdk server and use it with python3-mavsdk package but not in a c++ application as external lib.

Are you sure you need to run tools/generate_from_protos.sh at all? Seems superfluous to me.

As mentioned, this recipe works fine to build the mavsdk server and use it with python3-mavsdk package but not in a c++ application as external lib.

I would really go for -DBUILD_SHARED_LIBS=ON, such that then the mavsdk shared libs are on the system and your application can link them. I am honestly not really sure what it implies in Yocto, to build static libs. But I really wouldn’t do that.

I tried to build mavsdk as a shared library as well but this caused trouble during linking json-cpp so that the mavsdk build task fails.

It used to work in my recipe, would be interesting to understand why it doesn’t in your case :wink:.

Yes, it is actually needed. I doubled checked, because I am carrying this config around since 0.something but when I skip this step I am running into numerous errors like this:

error: 'mavsdk::rpc::telemetry::SetRateUnixEpochTimeRequest* mavsdk::rpc::telemetry::SetRateUnixEpochTimeRequest::New() const' marked 'final', but is not virtual

Building a static library in yocto wasn’t my first choice but as I was only interested in having an mavsdk_server binary in yocto I was fine with it. But after switching to an c++ application I really need to solve that. But currently I see multiple errors like the following, when I try to set -DBUILD_SHARED_LIBS=ON:

relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol _ZTVN4Json9ExceptionE' which may bind externally can not be used when making a shared object; recompile with -fPIC

dangerous relocation: unsupported relocation

I am using Yocto Kirkstone and meta-openembedded which brings jsoncpp 1.9.5

Oh, I guess that’s because your Yocto does not use the same version of protobuf/gRPC as the one that was used to generate the code upstream. That would make sense to me :+1:.

Is jsoncpp compiled with -fPIC?

This is a good question, I was expecting jsoncpp to be correct configured for being used as shared library but I don’t see that option in the CFLAGS variable. Unfortunately adding it manually does not change anything.

I checked the jsoncpp build instructions and the cmake args:

% bitbake-getvar  -r jsoncpp --value EXTRA_OECMAKE
 -DBUILD_SHARED_LIBS=ON -DBUILD_OBJECT_LIBS=OFF -DJSONCPP_WITH_TESTS=OFF 

With the shared libs enabled I think the library is build fine.

Can you try to add -DCMAKE_POSITION_INDEPENDENT_CODE=ON (we do it in the MAVSDK superbuild)?

@JonasVautherin that was the missing option. Thank you for providing this hint. I added it and now mavsdk compiles and my c++ application can be build with that version.

I had to disable the mavsdk_server for my tests as cmake was expecting that binary to be present in the sysroot. But I think I’ll find a way to make this accessible in the dev package so that I can leave this option enabled otherwise it will break the python3-mavsdk package.

1 Like