How to create and use the Yocto SDK

Published on October 10, 2023

In this post we will provide instructions on how to create and use the Yocto SDK. The Yocto SDK is extremely useful as it allows for quick application development without having to build and maintain massive yocto builds.  It provides a cross-development toolchain and also libraries that are specific to a particular yocto image i.e. a specific hardware architecture.

Building the SDK Installer

In this example, we will use our boundary-image-multimedia-full image to base the SDK on. First, follow the instructions in the "Build Procedure" section of our latest Yocto Mickledore release, but stop after setting up the build environment and before the bitbake of the boundary-image-multimedia-full image. Instead, we need to bitbake so that the SDK can be built, which can be done via:

~$ bitbake boundary-image-multimedia-full -c populate_sdk

Make sure to replace the target (boundary-image-multimedia-full) with the one matching your Yocto release as it might be different.

Run the SDK Installer

We now need to run the generated SDK Installer, which is an executable shell (.sh) script. It can found in the current working build directory -> "build/tmp/deploy/sdk" Using the yocto mickledore image as an example, the sdk installer will be called "fsl-imx-xwayland-boundary-glibc-x86_64-boundary-image-multimedia-full-armv8a-nitrogen8mp-toolchain-6.1-mickledore.sh", but of course depending on the distro, machine, host machine, target arch and image name, this will vary. Note: The script will prompt you to select a target directory of your choosing .

~$ cd build/tmp/deploy/sdk
~/build/tmp/deploy/sdk$ ./fsl-imx-xwayland-boundary-glibc-x86_64-boundary-image-multimedia-full-armv8a-nitrogen8mp-toolchain-6.1-mickledore.sh
NXP i.MX Release Distro SDK installer version 6.1-mickledore
============================================================
Enter target directory for SDK (default: /opt/fsl-imx-xwayland-boundary/6.1-mickledore): /home/Yocto_SDK
You are about to install the SDK to "/home/Yocto_SDK". Proceed [Y/n]? y
Extracting SDK.....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................done
Setting it up...done
SDK has been successfully set up and is ready to be used.
Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g.
$ . /home/Yocto_SDK/environment-setup-armv8a-poky-linux

Using the SDK

We can now use the SDK to develop applications. Below we will show how to use the SDK with Makefile, CMake,  and Autotools based applications

Run the SDK environment setup script

Create a working directory for an example app to use with the SDK. Then in a shell/terminal navigate to that directory and source the environment script using the target directory from the SDK install:

~$ source /home/Yocto_SDK/environment-setup-armv8a-poky-linux

The script essentially sets up environment variables in the current shell that are used for cross compilation application development. You can see all variables set by the installer with the "printenv" command.

Create Sample Hello World application

Create a hello world application to use as an example for each three build systems. Create the file "helloworld.c" with the following lines:

#include 
int main(void)
{
printf("Hello, World!\n");
return 0;
}

Now we are ready to use the SDK to build the hello world app.

Makefile based applications using the SDK

First, create the Makefile with the following lines:

all: helloworld

helloworld: helloworld.c
${CC} -o helloworld helloworld.c

clean:
rm helloworld

Next run "make" to compile our helloworld app:

~$ make
aarch64-poky-linux-gcc -march=armv8-a+crc+crypto -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/home/chris/Work/Yocto_Mickledore_SDK/sysroots/armv8a-poky-linux -o helloworld helloworld.c

You will notice from the make command that cross compilation is occurring because the CC compiler and arch is set for aarch64. This is because the SDK environment script sets the CC environemnt variable.

~$ printenv CC
aarch64-poky-linux-gcc -march=armv8-a+crc+crypto -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/home/chris/Work/Yocto_Mickledore_SDK/sysroots/armv8a-poky-linux

Finally, we can see it cross compiled for the correct architecture with file command:

~$ file helloworld
helloworld: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=135e97d99cfa7f122a30a1ef7aad4035da1a7852, for GNU/Linux 3.14.0, with debug_info, not stripped

CMake based applications using the SDK

First,  create the CMakeLists.txt file with the following lines:

project(helloworld)
add_executable(helloworld helloworld.c)
set(CMAKE_TOOLCHAIN_FILE $ENV{OE_CMAKE_TOOLCHAIN_FILE})

You will notice that we are setting the toolchain file for cmake to be the environment variable OE_CMAKE_TOOLCHAIN_FILE, which is set by the yocto SDK environment setup script.

~$ printenv | grep OE_CMAKE_TOOLCHAIN_FILE
OE_CMAKE_TOOLCHAIN_FILE=/home/Yocto_SDK/sysroots/x86_64-pokysdk-linux/usr/share/cmake/OEToolchainConfig.cmake

Next, we can run cmake to generate our makefile:

~$ cmake .
-- Toolchain file defaulted to '/home/Yocto_SDK/sysroots/x86_64-pokysdk-linux/usr/share/cmake/OEToolchainConfig.cmake'
-- The C compiler identification is GNU 12.2.0
-- The CXX compiler identification is GNU 12.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /home/Yocto_SDK/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /home/Yocto_SDK/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: '/home/yocto/'

Then, we can make our helloworld app:

~$ make
[ 50%] Building C object CMakeFiles/helloworld.dir/helloworld.c.o
[100%] Linking C executable helloworld
[100%] Built target helloworld

Finally, we can see it cross compiled for the correct architecture with file command:

~$ file helloworld
helloworld: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=63a68c6fad3a0c27be411a08ce131429c199d71a, for GNU/Linux 3.14.0, with debug_info, not stripped

Autotools based applications using the SDK

Using the same helloworld.c file, we need need to create the remaining files required for autotools which are configure.ac and Makefile.am. Create a "configure.ac" file with the following lines:

AC_INIT(hello,0.1)
AM_INIT_AUTOMAKE([foreign])
AC_PROG_CC
AC_CONFIG_FILES(Makefile)
AC_OUTPUT

Then create the "Makefile.am" file with the following lines:

bin_PROGRAMS = hello
hello_SOURCES = helloworld.c

Run "autoreconf" with the "-i" option to copy missing auxiliary files:

~$ autoreconf -i

Now we can cross compile helloworld using the "CONFIGURE_FLAGS" environment variable provided by the SDK environment script:

./configure ${CONFIGURE_FLAGS}

Finally, run make to generate the hello binary:

~$ make

and then see it is meant for the correct architecture with file command:

$ file hello
hello: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=b43562f742cfb06bf16269364ff766aa43b8a5c1, for GNU/Linux 3.14.0, with debug_info, not stripped

There you have it! You now know how to create and use the Yocto SDK in your application development!