Skip to main content

Build and package a software update

In this tutorial, we’ll walk through building a simple Hello World application in C and packaging it as a Debian .deb package. This serves as an introduction to creating software updates that you can later deploy to Debian Linux-based IoT devices using DigiCert® Device Trust Manager.

Notice

To deploy software updates to devices through Device Trust Manager, an Advanced plan or higher is required.

Objectives

  • Develop a basic C application: Write and compile a simple Hello World program in C for both ARM and x86 architectures, laying the groundwork for cross-platform software development.

  • Package the application into a Debian package: Learn how to create a Debian .deb package, preparing your application for easy distribution and installation on Debian-based systems.

  • Test the installation and execution: Ensure your packaged application installs correctly and runs on supported devices, verifying functionality before deployment.

Requirements

  • Linux system with Ubuntu 22.04 x64 or compatible version: Provides the necessary environment for compiling and packaging the application.

  • GCC cross-compilers for ARM64 and x86-64: Required to compile the application for multiple architectures. This tutorial uses gcc-x86-64-linux-gnu and gcc-aarch64-linux-gnu.

  • Basic knowledge of terminal commands: Familiarity with the command line will help you navigate through the tutorial steps.

  • Text editor: Such as nano or vim to write your C program and scripts. This tutorial uses nano.

To start, make sure your system is ready to compile and package the software update. This involves checking for and, if necessary, installing the required GCC cross-compilers for building applications on both ARM64 and x86-64 architectures.

Important

This tutorial has been tested on Ubuntu 22.04 x64. If you’re using a different distribution, the package names or installation commands might vary.

Verify GCC cross-compilers

Device Trust Manager supports IoT devices across various architectures, so you’ll need GCC compilers for both x86-64 and ARM64.

Check for x86-64 and ARM64 GCC compilers by running the following commands in your terminal:

x86_64-linux-gnu-gcc --version
aarch64-linux-gnu-gcc --version

If these commands return version information, the compilers are installed and you can continue to Step 2.

If needed, you can install the missing compilers with the following command:

sudo apt install gcc-x86-64-linux-gnu gcc-aarch64-linux-gnu

Now that your environment is set up with the required compilers, you’re ready to write and compile your application.

In this step, you’ll create a simple C program that outputs Hello World, and then compile it for both x86-64 and ARM64 architectures for cross-platform deployment.

Write the hello world program

To start, create a new file named helloworld.c:

nano helloworld.c

Now we're going to write a simple C program that outputs "DigiCert Hello World!" to the console. This will form the basis of our software update. Add the following code to the file:

#include <stdio.h>

int main() {
    printf("DigiCert Hello World!\n");
    return 0;
}

Save and close the file. In nano, press Ctrl + X, then Y to confirm, and Enter to save.

Compile the program

You’re ready to compile the program for both architectures to ensure compatibility with a range of devices.

Compile for x86-64 devices:

x86_64-linux-gnu-gcc helloworld.c -o hello_x86-64

Compile for ARM64 devices:

aarch64-linux-gnu-gcc helloworld.c -o hello_arm64

Test the compiled application

After compiling, it’s important to confirm that the application runs as expected on its intended architecture. Run each executable on the appropriate architecture:

For x86-64 systems:

./hello_x86-64

For ARM64 systems:

./hello_arm64

When executed correctly, the output should be:

DigiCert Hello World!

You’ve successfully written and compiled a cross-platform Hello World application. Next, you’ll package it as a Debian package to make it deployable across your devices.

Now that the application is compiled, you can package it as a Debian .deb file, making it easy to distribute and install across compatible devices. Packaging involves creating a standard structure, defining the package metadata, and adding a post-installation script to manage architecture-specific binaries.

Set Up the Debian Package Structure

To start, create the directory structure that Debian packages require.

mkdir digicert-hello-world-all
mkdir digicert-hello-world-all/DEBIAN

Define package metadata

Each Debian package includes a control file to define its metadata, such as the package name, version, and description. Open a new control file to add this information.

nano digicert-hello-world-all/DEBIAN/control

Add the following content to the control file:

Package: digicert-hello-world-all
Version: 0.1
Section: custom
Priority: optional
Architecture: all
Essential: no
Installed-Size: 1024
Maintainer: digicert.com
Description: Sample Hello World Debian package - for demo purposes

Note

The Architecture field is set to all since this package includes binaries for multiple architectures (x86 and ARM).

After adding this information, save and close the file by pressing Ctrl + X, then Y to confirm, and Enter.

Add the compiled binaries

Place the compiled application binaries into the appropriate directory within the package structure.

mkdir -p digicert-hello-world-all/usr/bin
cp hello_x86-64 hello_arm64 digicert-hello-world-all/usr/bin/

Create a post-installation script

The post-installation script will create symbolic links to the correct binary based on the device’s architecture. This ensures that the helloworld command points to the appropriate binary for each architecture.

  1. Create the postinst file:

    sudo nano digicert-hello-world-all/DEBIAN/postinst
    
  2. Add the following code to the script:

    #!/bin/bash
    ARCH=$(dpkg --print-architecture)
    if [ "$ARCH" = "arm64" ]; then
        ln -sf /usr/bin/hello_arm64 /usr/local/bin/helloworld
    elif [ "$ARCH" = "amd64" ]; then
        ln -sf /usr/bin/hello_x86-64 /usr/local/bin/helloworld
    fi
    

    Note

    The above script uses dpkg --print-architecture to detect the architecture (ARM64 or x86-64) and creates a symbolic link to the correct binary.

  3. Set the postinst file as executable to ensure it runs correctly during installation:

    sudo chmod 775 digicert-hello-world-all/DEBIAN/postinst
    

Verify the package structure

To check that the package structure is correctly set up, use the tree command. This command will list the directory contents to confirm your files are in place.

tree -L 3 digicert-hello-world-all

Your output should look like this:

digicert-hello-world-all
├── DEBIAN
│   ├── control
│   └── postinst
└── usr
    └── bin
        ├── hello_x86-64
        └── hello_arm64

Build the Debian package

Once your package structure is in place, use dpkg-deb to generate the .deb package file.

dpkg-deb --build digicert-hello-world-all

The dpkg-deb --build command creates a .deb package from the digicert-hello-world-all directory, which can be used for local testing or deployed to compatible devices.

With your .deb package ready, it’s time to install and test it on your Linux device to ensure everything functions as expected.

Install the package

To install the package, use the dpkg -i command. This command installs the digicert-hello-world-all package onto your device.

sudo dpkg -i digicert-hello-world-all.deb

Run the application

After installation, run the application to confirm it executes properly.

helloworld

If the package was installed successfully, you should see the following output:

DigiCert Hello World!