# Using the Extensible SDK

This chapter describes the extensible SDK and how to use it. The extensible SDK makes it easy to add new applications and libraries to an image, modify the source for an existing component, test changes on the target hardware, and ease integration into the rest of the OpenEmbedded build system.

Information in this chapter covers features that are not part of the standard SDK. In other words, the chapter presents information unique to the extensible SDK only. For information on how to use the standard SDK, see the "Using the Standard SDK" chapter.

## Setting Up to Use the Extensible SDK

Getting set up to use the extensible SDK is identical to getting set up to use the standard SDK. You still need to locate and run the installer and then run the environment setup script. See the "Installing the SDK" and the "Running the SDK Environment Setup Script" sections for general information. The following items highlight the only differences between getting set up to use the extensible SDK as compared to the standard SDK:

- Default Installation Directory: By default, the extensible SDK installs into the `poky_sdk` folder of your home directory. As with the standard SDK, you can choose to install the extensible SDK in any location when you run the installer. However, unlike the standard SDK, the location you choose needs to be writable for whichever users need to use the SDK, since files will need to be written under that directory during the normal course of operation.

- Build Tools and Build System: The extensible SDK installer performs additional tasks as compared to the standard SDK installer. The extensible SDK installer extracts build tools specific to the SDK and the installer also prepares the internal build system within the SDK. Here is example output for running the extensible SDK installer:

           $ ./poky-glibc-x86_64-core-image-minimal-core2-64-toolchain-ext-2.1+snapshot.sh
           Poky (Yocto Project Reference Distro) Extensible SDK installer version 2.1+snapshot
           ===================================================================================
           Enter target directory for SDK (default: ~/poky_sdk):
           You are about to install the SDK to "/home/scottrif/poky_sdk". Proceed[Y/n]? Y
           Extracting SDK......................................................................done
           Setting it up...
           Extracting buildtools...
           Preparing build system...
           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/scottrif/poky_sdk/environment-setup-core2-64-poky-linux

After installing the SDK, you need to run the SDK environment setup script. Here is the output:

         $ source 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.

Once you run the environment setup script, you have `devtool` available.

## Using `devtool` in Your SDK Workflow

The cornerstone of the extensible SDK is a command-line tool called `devtool`. This tool provides a number of features that help you build, test and package software within the extensible SDK, and optionally integrate it into an image built by the OpenEmbedded build system.

The `devtool` command line is organized similarly to Git in that it has a number of sub-commands for each function. You can run `devtool --help` to see all the commands.

Two `devtool` subcommands that provide entry-points into development are:

- `devtool add`: Assists in adding new software to be built.

- `devtool modify`: Sets up an environment to enable you to modify the source of an existing component.

As with the OpenEmbedded build system, "recipes" represent software packages within `devtool`. When you use `devtool add`, a recipe is automatically created. When you use `devtool modify`, the specified existing recipe is used in order to determine where to get the source code and how to patch it. In both cases, an environment is set up so that when you build the recipe a source tree that is under your control is used in order to allow you to make changes to the source as desired. By default, both new recipes and the source go into a "workspace" directory under the SDK.

The remainder of this section presents the `devtool add` and `devtool modify` workflows.

### Use `devtool add` to Add an Application

The `devtool add` command generates a new recipe based on existing source code. This command takes advantage of the workspace layer that many `devtool` commands use. The command is flexible enough to allow you to extract source code into both the workspace or a separate local Git repository and to use existing code that does not need to be extracted.

Depending on your particular scenario, the arguments and options you use with `devtool add` form different combinations. The following diagram shows common development flows you would use with the `devtool add` command:

1. Generating the New Recipe: The top part of the flow shows three scenarios by which you could use `devtool add` to generate a recipe based on existing source code.

   In a shared development environment, it is typical where other developers are responsible for various areas of source code. As a developer, you are probably interested in using that source code as part of your development using the Yocto Project. All you need is access to the code, a recipe, and a controlled area in which to do your work.

   Within the diagram, three possible scenarios feed into the `devtool add` workflow:

   - Left: The left scenario represents a common situation where the source code does not exist locally and needs to be extracted. In this situation, you just let it get extracted to the default workspace - you do not want it in some specific location outside of the workspace. Thus, everything you need will be located in the workspace:

              $ devtool add recipe fetchuri

     With this command, `devtool` creates a recipe and an append file in the workspace as well as extracts the upstream source files into a local Git repository also within the `sources` folder.

   - Middle: The middle scenario also represents a situation where the source code does not exist locally. In this case, the code is again upstream and needs to be extracted to some local area - this time outside of the default workspace. As always, if required `devtool` creates a Git repository locally during the extraction. Furthermore, the first positional argument srctree in this case identifies where the `devtool add` command will locate the extracted code outside of the workspace:

              $ devtool add recipe srctree fetchuri

     In summary, the source code is pulled from fetchuri and extracted into the location defined by srctree as a local Git repository.

     Within workspace, `devtool` creates both the recipe and an append file for the recipe.

   - Right: The right scenario represents a situation where the source tree (srctree) has been previously prepared outside of the `devtool` workspace.

     The following command names the recipe and identifies where the existing source tree is located:

              $ devtool add recipe srctree

     The command examines the source code and creates a recipe for it placing the recipe into the workspace.

     Because the extracted source code already exists, `devtool` does not try to relocate it into the workspace - just the new the recipe is placed in the workspace.

     Aside from a recipe folder, the command also creates an append folder and places an initial `*.bbappend` within.

2. Edit the Recipe: At this point, you can use `devtool edit-recipe` to open up the editor as defined by the `$EDITOR` environment variable and modify the file:

            $ devtool edit-recipe recipe

   From within the editor, you can make modifications to the recipe that take affect when you build it later.

3. Build the Recipe or Rebuild the Image: At this point in the flow, the next step you take depends on what you are going to do with the new code.

   If you need to take the build output and eventually move it to the target hardware, you would use `devtool build`:

            $ devtool build recipe

   On the other hand, if you want an image to contain the recipe's packages for immediate deployment onto a device (e.g. for testing purposes), you can use the `devtool build-image` command:

            $ devtool build-image image

4. Deploy the Build Output: When you use the `devtool build` command to build out your recipe, you probably want to see if the resulting build output works as expected on target hardware.

   This step assumes you have a previously built image that is already either running in QEMU or running on actual hardware. Also, it is assumed that for deployment of the image to the target, SSH is installed in the image and if the image is running on real hardware that you have network access to and from your development machine.

   You can deploy your build output to that target hardware by using the `devtool deploy-target` command:

            $ devtool deploy-target recipe target

   The target is a live target machine running as an SSH server.

   You can, of course, also deploy the image you build using the `devtool build-image` command to actual hardware. However, `devtool` does not provide a specific command that allows you to do this.

5. Optionally Update the Recipe With Patch Files: Once you are satisfied with the recipe, if you have made any changes to the source tree that you want to have applied by the recipe, you need to generate patches from those changes. You do this before moving the recipe to its final layer and cleaning up the workspace area `devtool` uses. This optional step is especially relevant if you are using or adding third-party software.

   To convert commits created using Git to patch files, use the `devtool update-recipe` command.

   Any changes you want to turn into patches must be committed to the Git repository in the source tree.

            $ devtool update-recipe recipe

6. Move the Recipe to its Permanent Layer: Before cleaning up the workspace, you need to move the final recipe to its permanent layer. You must do this before using the `devtool reset` command if you want to retain the recipe.

7. Reset the Recipe: As a final step, you can restore the state such that standard layers and the upstream source is used to build the recipe rather than data in the workspace. To reset the recipe, use the `devtool reset` command:

            $ devtool reset recipe

### Use `devtool modify` to Modify the Source of an Existing Component

The `devtool modify` command prepares the way to work on existing code that already has a recipe in place. The command is flexible enough to allow you to extract code, specify the existing recipe, and keep track of and gather any patch files from other developers that are associated with the code.

Depending on your particular scenario, the arguments and options you use with `devtool modify` form different combinations. The following diagram shows common development flows you would use with the `devtool modify` command:

1. Preparing to Modify the Code: The top part of the flow shows three scenarios by which you could use `devtool modify` to prepare to work on source files. Each scenario assumes the following:

   - The recipe exists in some layer external to the `devtool` workspace.

   - The source files exist upstream in an un-extracted state or locally in a previously extracted state.

   The typical situation is where another developer has created some layer for use with the Yocto Project and their recipe already resides in that layer. Furthermore, their source code is readily available either upstream or locally.

   - Left: The left scenario represents a common situation where the source code does not exist locally and needs to be extracted. In this situation, the source is extracted into the default workspace location. The recipe, in this scenario, is in its own layer outside the workspace (i.e. `meta-`layername).

     The following command identifies the recipe and by default extracts the source files:

              $ devtool modify recipe

     Once `devtool`locates the recipe, it uses the `SRC_URI` variable to locate the source code and any local patch files from other developers are located.

     You cannot provide an URL for srctree when using the `devtool modify` command.

     With this scenario, however, since no srctree argument exists, the `devtool modify` command by default extracts the source files to a Git structure. Furthermore, the location for the extracted source is the default area within the workspace. The result is that the command sets up both the source code and an append file within the workspace with the recipe remaining in its original location.

   - Middle: The middle scenario represents a situation where the source code also does not exist locally. In this case, the code is again upstream and needs to be extracted to some local area as a Git repository. The recipe, in this scenario, is again in its own layer outside the workspace.

     The following command tells `devtool` what recipe with which to work and, in this case, identifies a local area for the extracted source files that is outside of the default workspace:

              $ devtool modify recipe srctree

     As with all extractions, the command uses the recipe's `SRC_URI` to locate the source files. Once the files are located, the command by default extracts them. Providing the srctree argument instructs `devtool` where place the extracted source.

     Within workspace, `devtool` creates an append file for the recipe. The recipe remains in its original location but the source files are extracted to the location you provided with srctree.

   - Right: The right scenario represents a situation where the source tree (srctree) exists as a previously extracted Git structure outside of the `devtool` workspace. In this example, the recipe also exists elsewhere in its own layer.

     The following command tells `devtool` the recipe with which to work, uses the "-n" option to indicate source does not need to be extracted, and uses srctree to point to the previously extracted source files:

              $ devtool modify -n recipe srctree

     Once the command finishes, it creates only an append file for the recipe in the workspace. The recipe and the source code remain in their original locations.

2. Edit the Source: Once you have used the `devtool modify` command, you are free to make changes to the source files. You can use any editor you like to make and save your source code modifications.

3. Build the Recipe: Once you have updated the source files, you can build the recipe.

4. Deploy the Build Output: When you use the `devtool build` command to build out your recipe, you probably want to see if the resulting build output works as expected on target hardware.

   This step assumes you have a previously built image that is already either running in QEMU or running on actual hardware. Also, it is assumed that for deployment of the image to the target, SSH is installed in the image and if the image is running on real hardware that you have network access to and from your development machine.

   You can deploy your build output to that target hardware by using the `devtool deploy-target` command:

            $ devtool deploy-target recipe target

   The target is a live target machine running as an SSH server.

   You can, of course, also deploy the image you build using the `devtool build-image` command to actual hardware. However, `devtool` does not provide a specific command that allows you to do this.

5. Optionally Create Patch Files for Your Changes: After you have debugged your changes, you can use `devtool update-recipe` to generate patch files for all the commits you have made.

   Patch files are generated only for changes you have committed.

            $ devtool update-recipe recipe

   By default, the `devtool update-recipe` command creates the patch files in a folder named the same as the recipe beneath the folder in which the recipe resides, and updates the recipe's `SRC_URI` statement to point to the generated patch files.

   You can use the "--append LAYERDIR" option to cause the command to create append files in a specific layer rather than the default recipe layer.

6. Restore the Workspace: The `devtool reset` restores the state so that standard layers and upstream sources are used to build the recipe rather than what is in the workspace.

            $ devtool reset recipe

## Installing Additional Items Into the Extensible SDK

The extensible SDK typically only comes with a small number of tools and libraries out of the box. If you have a minimal SDK, then it starts mostly empty and is populated on-demand. However, sometimes you will need to explicitly install extra items into the SDK. If you need these extra items, you can first search for the items using the `devtool search` command. For example, suppose you need to link to libGL but you are not sure which recipe provides it. You can use the following command to find out:

         $ devtool search libGL
         mesa                  A free implementation of the OpenGL API

Once you know the recipe (i.e. `mesa` in this example), you can install it:

         $ devtool sdk-install mesa

By default, the `devtool sdk-install` assumes the item is available in pre-built form from your SDK provider. If the item is not available and it is acceptable to build the item from source, you can add the "-s" option as follows:

         $ devtool sdk-install -s mesa

It is important to remember that building the item from source takes significantly longer than installing the pre-built artifact. Also, if no recipe exists for the item you want to add to the SDK, you must instead add it using the `devtool add` command.

## Updating the Extensible SDK

If you are working with an extensible SDK that gets occasionally updated (e.g. typically when that SDK has been provided to you by another party), then you will need to manually pull down those updates to your installed SDK.

To update your installed SDK, run the following:

         $ devtool sdk-update

The previous command assumes your SDK provider has set the default update URL for you. If that URL has not been set, you need to specify it yourself as follows:

         $ devtool sdk-update path_to_update_directory

The URL needs to point specifically to a published SDK and not an SDK installer that you would download and install.

## Creating a Derivative SDK With Additional Components

You might need to produce an SDK that contains your own custom libraries for sending to a third party (e.g., if you are a vendor with customers needing to build their own software for the target platform). If that is the case, then you can produce a derivative SDK based on the currently installed SDK fairly easily. Use these steps:

1. If necessary, install an extensible SDK that you want to use as a base for your derivative SDK.

2. Source the environment script for the SDK.

3. Add the extra libraries or other components you want by using the `devtool add` command.

4. Run the `devtool build-sdk` command.

The above procedure takes the recipes added to the workspace and constructs a new SDK installer containing those recipes and the resulting binary artifacts. The recipes go into their own separate layer in the constructed derivative SDK, leaving the workspace clean and ready for users to add their own recipes.