Application Development with Legacy SDK

Back to Yocto Project Cookbook
This section is currently a [ Work In Process ]
== Application Development with Legacy SDK==
Welcome to the Yocto Project Test Kitchen! It can be a bit overwhelming to know where to start with the Yocto Project. You know you want to build an application that runs on embedded hardware, but where and how do you get started? A development environment can be an abstract, somewhat hard-to-imagine thing. This part of the wiki is intended to fill the knowledge gap between the Quick Start and the myriad of ways to build an image and run it on real (or emulated) hardware. So what better way to do that than with a "Test Kitchen" analogy? 
Our Test Kitchen must be Linux-powered, of course. And using one of the supported distributions in our Linux-powered kitchen means that we'll already either have or have a way to easily get everything we need to follow the recipes in our Cookbook.
For the first experiment in our Test Kitchen, let's assume you got through the Quick Start, and have already created an image that we'll use to build upon.
== Adding or Modifying Functionality of an Existing Image (QEMU) ==
===Prerequisites===
* Existing image -- The image that currently runs on your target hardware. This is the image to which you are adding new functionality or modifying existing functionality. 
* Installed SDK -- The installed Software Development Kit. It is recommended that you grab the extensible (ext4) version of the SDK, so that you can easily add new and modify existing functionality.
* An initialized SDK environment -- The properly-initialized SDK dev environment, which is set up by running the SDK environment setup script.
* Source Code: Existing source files for any new functionality or for any existing functionality you would like to add or modify, respectively. For our Test Kitchen experiment, we will add a helloworld module as new functionality and we will modify the existing multiple device administrator (mdadm) module, which is a core module included as part of the installed SDK.
===Process===
Use these steps to set up your SDK dev environment with QEMU (emulator). 
1. Locate and download QEMU-compatible images from the latest Yocto releases from http://downloads.yoctoproject.org/releases/yocto/yocto-2.1/machines/qemu/qemux86-64
2. Save the file to your machine. Our example is using core-image-sato-dev-qemux86-64.ext4
 
 $ wget http://downloads.yoctoproject.org/releases/yocto/yocto-2.1/machines/qemu/qemux86-64/core-image-sato-qemux86-64.ext4
 
3. Locate the SDK option appropriate for your target hardware from the Yocto toolchain.
4. Download and save the SDK Installer: poky-glibc-x86_64-core-image-sato-core2-64-toolchain-ext-2.1.sh. NOTE: It is very important that when you choose the SDK, you are choosing the one appropriate for the hardware or for QEMU. In this case, you need the extensible SDK that maps to the image we are going to eventually run on QEMU. For more details on selecting and installing an SDK, see the Installing the SDK section in the Yocto Project Software Development Kit (SDK) Developer’s Guide.
5. Make the installer executable:
 $ chmod +x poky-glibc-x86_64-core-image-sato-core2-64-toolchain-ext-2.1.sh
6. Install the SDK by running the script and accepting the defaults
 $ . /poky-glibc-x86_64-core-image-sato-core2-64-toolchain-ext-2.1.sh
 Poky (Yocto Project Reference Distro) Extensible SDK installer version 2.1
 Enter target directory for SDK (default: ~/poky_sdk):
 You are about to install the SDK to "/home/username/poky_sdk". Proceed[Y/n]? y
 Extracting SDK...
 .
 .
 .
 SDK has been successfully set up and is ready to be used.
NOTE: Each time you wish to use the SDK in a new shell session, you need to source the environment setup script:
 $ . /home/username/poky_sdk/environment-setup-core2-64-poky-linux
7. Initialize the SDK Development Environment
 
 $ . $HOME/poky_sdk/environment-setup-core2-64-poky-linux
 SDK environment now set up; additionally you may now run devtool to perform development tasks.
 Run devtool --help for further details.
8. Ensure your new source code is available. The only requirement for the source code is that it either exists locally or can be accessed through an URL for downloading. This example assumes the source code exists at:
 $HOME/mysource/helloworld
NOTE: Several methods exist by which you can gain access to your source files. See the (http://www.yoctoproject.org/docs/2.1/sdk-manual/sdk-manual.html#sdk-use-devtool-to-add-an-application Use devtool to add an application) section in the Yocto SDK for more information. 
For this example, be sure you know the URL from which your source code can be downloaded. The source files must consist of the following files: hello.c,
Makefile.am, and configure.ac:
The helloworld/hello.c file is as follows:
 #include <stdio.h>
 main()
 {
 printf("Hello World:\n");
 }
The helloworld/Makefile.am file is as follows:
 bin_PROGRAMS = hello
 hello_SOURCES = hello.c
The helloworld/configure.ac file is as follows:
 AC_INIT(hello,0.1)
 AM_INIT_AUTOMAKE([foreign])
 AC_PROG_CC
 AC_PROG_INSTALL
 AC_OUTPUT(Makefile)
==== Adding New Functionality ====
Now that all the pieces are in place, we can use devtool to add the new "helloworld" application to the existing image. The result will be a built object that can be integrated into an image, tested using
either actual hardware or the Quick Emulator (QEMU), and ultimately deployed to the actual hardware.
Follow these steps to add the helloworld functionality to the existing image:
1. Use devtool add to locate and set up the work environment named "workspace" for development. The command automatically creates the recipe needed to build the module:
 $ devtool add helloworld $HOME/mysources/helloworld
 NOTE: Recipe home/username/poky_sdk/workspace/recipes/helloworld/helloworld.bb`
 has been automatically created; further editing may be required to make it
 fully functional
2. Use the devtool build command to run the recipe using the Yocto Project build engine, which is part of the installed SDK, and create the build output for your new module:
 $ devtool build helloworld
 Loading cache: 100% |########################################################| ETA: 00:00:00
 Loaded 1302 entries from dependency cache.
 Parsing recipes: 100% |########################################################| Time: 00:00:00
 Parsing of 872 .bb files complete (871 cached, 1 parsed). 1302 targets, 48 skipped, 0 masked, 0 errors.
 NOTE: Resolving any missing task queue dependencies
 NOTE: Preparing RunQueue
 NOTE: Executing SetScene Tasks
 NOTE: Executing RunQueue Tasks
 helloworld-0.1-r0 do_compile: NOTE: helloworld: compiling from external source tree /home/username/mysource/helloworld
 NOTE: Tasks Summary: Attempted 342 tasks of which 336 didn't need to be rerun and all succeeded.
3. Make sure the image you downloaded earlier is in the poky_sdk directory where the SDK was installed; then use the devtool runqemu command to start QEMU and boot the image:
 $ cp $HOME/Downloads/core-image-sato-dev-qemux86_64.ext4 $HOME/poky_sdk
 $ devtool runqemu core-image-sato-dev-qemux86-64.ext4
4. Because the previous step ties up the terminal, you need to open a new terminal window, get into the SDK development area, and run the SDK initialization script to continue:
 
 $ cd $HOME/poky_sdk
 $ . /home/username/poky_sdk/environment-setup-core2-64-poky-linux
5. Use the devtool deploy-target command to deploy the helloworld output you built earlier to QEMU so that you can test the module.
 
 $ devtool deploy-target helloworld root@192.168.7.2
NOTE: If you get an error message indicating the script failed to copy to root@192.168.7.2, you can run the command with -c option to turn off key-checking.
 $ devtool deploy-target -c helloworld root@192.168.7.2
6. Inside QEMU, use the GUI to open up a terminal and then run the "hello" command:
 
 sh-4.3# hello
 Hello World:
 sh-4.3#
You will see "Hello World" returned as terminal output. At this point, you have added the new functionality and proved that it works.
7. Make sure to upload the sources into a repository (e.g. Git) such that the files could be fetched by other people. This is typical practice once any new module has been created and tested and is ready for use by other developers.
8. At this point you have put the source code in a more permanent area where it can be fetched by someone using the full-blown YP development process. You need to know where the recipe is:
 $HOME/poky_sdk/workspace/recipes/helloworld
==== Modifying Existing Functionality ====
Another common scenario is to modify code that already has an existing recipe in place. This is different from adding brand new functionality, as was demonstrated in the previous section.
To help demonstrate this concept, we will use a more "real-world" example: the existing multiple device administrator (mdadm) module, which is a core module included as part of the installed Yocto Project SDK. The steps in this section will modify mdadm to change the reported version, which is 3.4.
Follow these steps to modify mdadm:
1. Run devtool modify to locate, extract, and prepare all of the mdadm files. This command locates the source based on information in the existing recipe, unpacks the source into your workspace, applies any existing patches, and parses all related recipes:
 $ devtool modify mdadm
 Parsing recipes..done.
 NOTE: Fetching mdadm…
 NOTE: Unpacking…
 NOTE: Patching…
 NOTE: Adding local source files to srctree…
 NOTE: Source tree extracted to /home/username/poky_sdk/workspace/sources/mdadm
 NOTE: Using source tree as build directory since recipe inherits autotools-brokensep
 NOTE: Recipe mdadm now set up to build from /home/username/poky_sdk/workspace/sources/mdadm.
2. In the source location $HOME/poky_sdk/workspace/sources/mdadm, use an editor to edit the Readme.c file. Change the line that specifies the version as 3.4 to say 3.4a.
 #define VERSION "3.4a"
3. Rebuild mdadm using the devtool build command:
 $ devtool build mdadm
 Parsing recipes: 100% |################################################################################################################| ETA: 00:00:00
 Parsing of 872 .bb files complete (0 cached, 872 parsed). 1302 targets, 48 skipped, 0 masked, 0 errors.
 NOTE: Resolving any missing task queue dependencies
 NOTE: Preparing RunQueue
 NOTE: Executing SetScene Tasks
 NOTE: Executing RunQueue Tasks
 mdadm-3.4-r0 do_compile: NOTE: mdadm: compiling from external source tree /home/username/poky_sdk/workspace/sources/mdadm
 NOTE: Tasks Summary: Attempted 347 tasks of which 336 didn't need to be rerun and all succeeded.
4. Take note that QEMU is still assumed to be running in the shell from the previous section; use the devtool deploy-target command to deploy the freshly-built mdadm module to the already-running image:
 $ devtool deploy-target mdadm root@192.168.7.2
 NOTE: Successfully deployed /home/username/poky_sdk/tmp/work/core2-64-poky-linux/mdadm/3.4-r0/image
5. In the shell running QEMU, verify your changes by running mdadm and providing the -V option to return the version:
 sh-4.3# mdadm -V
 mdadm - v 3.4a 21 June 2016
 sh-4.3#
NOTE: If you try to use the previous command to see the original version of mdadm, you will get a message indicating the command is not found; mdadm. is not in the image by default.
6. At this point, you have modified the source code of an existing module all within your workspace. If you want to save your work, commit those changes. You can use the following commands to see the changes that need to be staged and committed:
 $ cd /$HOME/poky_sdk/workspace/sources/mdadm
 $ git status
And these two commands to stage and commit the changed file:
 $ git add ReadMe.c
 $ git commit -m "ReadMe.c-Updated-the-version-string"
7. Turn the commit you have made into a patch:
 $ devtool update-recipe mdadm
 Parsing recipes..done.
 NOTE: Updating file run-ptest
 NOTE: Adding new patch 0001-ReadMe.c-Updated-the-version-string.patch
 NOTE: Updating recipe mdadm_3.4.bb
which will be located here:
 $HOME/poky_sdk/layers/build/meta/recipes-extended/mdadm/mdadm/0001-ReadMe.c-Updated-the-version-string.patch