Debian-Based Application Development Guide

Debian-Based Application Development Guide

1. Overview

1.1. Target Audience and Use Cases

This guide is designed for developers who want to build applications directly on the Debian system underlying RobustOS Pro devices. Compared to using the RobustOS Pro application framework, developing directly on Debian offers greater flexibility and broader community support.

This guide covers two primary development scenarios:

  1. Porting Existing Applications: Migrating applications that already run on standard Linux/Debian platforms to RobustOS Pro devices.

  2. Building New Applications: Creating custom applications from scratch specifically for RobustOS Pro devices.

1.2. Development Approach Comparison

FeatureDirect Debian DevelopmentRobustOS Pro Framework Development
FlexibilityVery high - full control over application behavior and dependenciesHigh - must follow framework conventions
Development EfficiencyDepends on developer experience - requires manual handling of service management and configurationHigh - framework automates configuration, Web UI generation, and inter-process communication
System IntegrationLow - requires interaction with system services via commands or APIsHigh - direct access to framework-provided APIs
Ideal Use CasesPorting existing apps, developing standalone services, applications requiring specific libraries or environmentsApplications requiring tight system integration, rapid development of apps with Web UIs

1.3. System Environment Introduction

RobustOS Pro is built on Debian GNU/Linux, providing a standard, stable, and feature-rich Linux environment. You can add sudo users through the RobustOS web management interface, then SSH into the system to access a full shell environment.

  • Package Manager: apt

  • Service Manager: systemd

  • Shell Environment: bash

You can check the current system version details using cat /etc/os-release. RobustOS Pro 2.x is based on Debian 11.

2. Development Environment Setup

Regardless of whether you're porting or developing a new application, you'll need to prepare your development environment first.

2.1. Setting Up the Build Environment

Since your development host (typically x86 architecture) differs from the target device (ARM architecture), you need an environment to generate binaries that can run on the device. You can choose one of two standard approaches:

2.1.1. Approach 1: Installing Cross-Compilation Toolchain

You can install a standard cross-compilation toolchain on your development host (Debian/Ubuntu recommended).

  • For arm64 (aarch64) architecture devices:
# On your Debian/Ubuntu development host
sudo apt update
sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu

After installation, you'll use aarch64-linux-gnu-gcc as your compiler.

  • For armhf (armv7) architecture devices:
# On your Debian/Ubuntu development host
sudo apt update
sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf

After installation, you'll use arm-linux-gnueabihf-gcc as your compiler.

2.1.2. Approach 2: Native Compilation Using Docker

This is a more modern approach that simplifies dependency management and ensures environment consistency. It runs an ARM architecture Docker container on an x86 host for native compilation, avoiding the complexities of cross-compilation.

  • Starting an arm64 Debian 11 container:
# -v "$(pwd):/src" mounts the current directory to /src in the container for code sharing
docker run --rm -it --platform linux/arm64 -v "$(pwd):/src" debian:11
  • Starting an armhf Debian 11 container:
docker run --rm -it --platform linux/arm/v7 -v "$(pwd):/src" debian:11
  • Inside the container, install build tools:
# Update package lists
apt update

# Install basic build tools
apt install -y build-essential gcc make

# Optional: Install other common tools
apt install -y git cmake pkg-config

# Navigate to the mounted source directory
cd /src

# Now you can start building
make

Inside the container, after installing the build tools, you can compile directly using gcc just as you would on the target device, without configuring cross-compilation toolchains.

2.2. Accessing the Device

  • SSH Login: Use an SSH client to connect to the device's command line interface. The default IP address is typically 192.168.0.1.
ssh sudouser@192.168.0.1
  • File Transfer: Use scp to transfer files between your development host and the device.
# Upload file from host to device
scp /path/to/local/file sudouser@192.168.0.1:/path/to/remote/

# Download file from device to host
scp sudouser@192.168.0.1:/path/to/remote/file /path/to/local/

2.3. Device Package Management

You can use apt directly on the device to manage packages. Ensure the device has internet connectivity.

# Update package lists
apt update

# Install a new package (e.g., git)
apt install git

# Remove a package
apt remove git

# Search for packages
apt search <package-name>

3. Scenario 1: Porting an Existing Application

This section guides you through porting an existing Linux/Debian application to RobustOS Pro devices.

3.1. Step 1: Dependency Analysis and Environment Preparation

First, analyze your application's runtime library dependencies.

  • Check Dynamic Libraries: Use ldd on the original system to view the application's shared library dependencies.
ldd ./your-application
  • Install Dependencies: Log into the device and use apt install to install all required libraries. Standard libraries (such as libcurl, libssl) are typically available directly from Debian repositories.

  • Handle Special Libraries: If your application depends on proprietary libraries or specific versions unavailable through apt, you'll need to obtain their source code, compile them for the target platform using the cross-compilation toolchain, and then deploy the compiled library files to /usr/lib or other library paths on the device.

3.2. Step 2: Configure Cross-Compilation

Next, modify your project's build system (e.g., Makefile) to use the cross-compilation toolchain.

Makefile Example:

Point the build tools to the cross-compilation toolchain.

# Original configuration
# CC = gcc
# CXX = g++

# Modified for cross-compilation toolchain
CROSS_COMPILE ?= aarch64-linux-gnu-
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
LD = $(CROSS_COMPILE)ld
AR = $(CROSS_COMPILE)ar
STRIP = $(CROSS_COMPILE)strip

# Compilation options
CFLAGS ?= -Wall -O2
CXXFLAGS ?= -Wall -O2
LDFLAGS ?=

# Target executable
TARGET = your-application

# Phony targets
.PHONY: all clean verify

all: $(TARGET)

$(TARGET): main.c
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
@echo "Build complete. Verifying binary..."
@file $(TARGET)

verify: $(TARGET)
@file $(TARGET)
@echo "Expected output: ELF 64-bit LSB executable, ARM aarch64"

clean:
rm -f $(TARGET) *.o

CMake Example:

Create a toolchain file (e.g., toolchain.cmake) to define the cross-compilation environment.

# toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

When running CMake, specify this file using the -DCMAKE_TOOLCHAIN_FILE parameter.

cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake ..

3.3. Step 3: Code Compatibility Adjustments

Most standard Linux applications require no code modifications. However, if you encounter issues, check the following:

  • Hardware-Specific Code: Check for code related to specific hardware (such as particular GPIO pins or serial ports) or CPU architectures.

  • Hardcoded Paths: Verify that any hardcoded filesystem paths in the code are valid on the target device.

3.4. Step 4: Build, Deploy, and Test

  1. On your development host, run make (or your build command) to cross-compile the application.

  2. After successful compilation, an ARM architecture executable will be generated. Use file to confirm.

file ./your-application
# Expected output: ... ELF 64-bit LSB executable, ARM aarch64, ...
  1. Use scp to upload the executable and related configuration files to the device.

  2. On the device, add execute permissions with chmod +x ./your-application, then run it for testing.

4. Scenario 2: Developing a New Application

This section guides you through developing a new application for RobustOS Pro devices from scratch.

4.1. Writing Your First "Hello, World!" Program

C/C++ Example

  1. Write the source code (main.c):
#include <stdio.h>

int main() {
printf("Hello, RobustOS Pro!\n");
return 0;
}
  1. Write the Makefile:
# Cross-compilation toolchain prefix (default aarch64, can be overridden via environment variable)
CROSS_COMPILE ?= aarch64-linux-gnu-
CC = $(CROSS_COMPILE)gcc

# Compilation options
CFLAGS = -Wall -O2
LDFLAGS =

# Target executable
TARGET = hello_world

# Phony targets
.PHONY: all clean verify

all: $(TARGET)

$(TARGET): main.c
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
@echo "Build complete. Verifying binary architecture..."
@file $(TARGET)

# Verify generated binary architecture
verify: $(TARGET)
@echo "Binary architecture:"
@file $(TARGET)
@echo "Expected: ARM aarch64 for arm64 devices"

clean:
rm -f $(TARGET)
  1. Build, Upload, and Run:
# Build on development host
make

# Upload to device
scp ./hello_world sudouser@192.168.0.1:/home/sudouser/

# Run on device
ssh sudouser@192.168.0.1 "/home/sudouser/hello_world"
# Expected output: Hello, RobustOS Pro!

Python Example

Python is an interpreted language and doesn't require cross-compilation.

  1. Write the script (hello.py):
#!/usr/bin/env python3
print("Hello from Python on RobustOS Pro!")
  1. Upload and Run:
# Upload to device
scp ./hello.py sudouser@192.168.0.1:/home/sudouser/

# Run on device
ssh sudouser@192.168.0.1 "python3 /home/sudouser/hello.py"
# Expected output: Hello from Python on RobustOS Pro!

4.2. Interacting with Router Hardware and System Services

Your application may need to query device status or communicate with system services.

4.2.1. Executing System Commands

In Debian applications or shell scripts, the primary tools for interacting with system services are usi (for status queries) and uci (for querying or modifying configuration). You can execute these commands from your application using system() or popen().

Common usi Command Examples:

# View LAN port IP address
sudo usi get lan_links.link_status[1].ip4_addr

# Check SIM1 status
sudo usi get cellular.status[1].modem_status

# Get device model
sudo usi get system.device_model

C Language Example - Using popen() to capture command output:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
FILE *fp;
char buffer[256];

// Execute command and capture output
fp = popen("usi get system.firmware_version", "r");
if (fp == NULL) {
fprintf(stderr, "Failed to run command\n");
return 1;
}

// Read output
printf("Firmware Version:\n");
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("%s", buffer);
}

// Close pipe
pclose(fp);
return 0;
}

Python Example:

import subprocess

# Execute command and capture output
result = subprocess.run(['usi', 'get', 'system.firmware_version'],
capture_output=True, text=True)

if result.returncode == 0:
print("Firmware Version:")
print(result.stdout)
else:
print(f"Error: {result.stderr}")

5. Application Packaging and Deployment

For easier management and distribution, we recommend packaging your application in Debian's .deb format.

5.1. Creating a Debian Package (.deb)

  1. Create the package directory structure:
myapp-pkg/
├── DEBIAN
│ └── control
└── usr
└── local
└── bin
└── myapp <-- Place your executable here
  1. Write the control file: This is the package metadata file.
Package: myapp
Version: 1.0.0
Section: base
Priority: optional
Architecture: arm64
Maintainer: Your Name <your.email@example.com>
Description: A brief description of my application.
A longer description can go here on multiple lines,
but each subsequent line must start with a space.

Important Note: Architecture Field

  • The Architecture field must match your target device architecture:

    • For aarch64 (arm64) devices, use Architecture: arm64

    • For armv7 (armhf) devices, use Architecture: armhf

    • For architecture-independent packages (pure scripts, documentation), use Architecture: all

  • You can confirm the device architecture by SSH'ing into the device and running dpkg --print-architecture

  1. Build the package: Use dpkg-deb to create the .deb file.
dpkg-deb --build myapp-pkg
# This will generate myapp-pkg.deb

5.2. Installing and Managing Applications on Device

  1. Upload the generated myapp-pkg.deb file to the device.

  2. Use dpkg commands to install, remove, and query packages.

# Install
dpkg -i myapp-pkg.deb

# Remove
dpkg -r myapp

# Query installed packages
dpkg -l | grep myapp

6. Configuring as an Auto-Start Service

To have your application automatically start when the device boots and be managed by the system, you can configure it as a systemd service.

6.1. Writing a systemd Service File

  1. Create a file named myapp.service.
[Unit]
Description=My Application Service
After=network.target

[Service]
ExecStart=/usr/local/bin/myapp
Restart=on-failure
# Unless the app truly requires root privileges, use a regular user
# User=myapp
# Group=myapp
User=root # Only use when hardware access is required

[Install]
WantedBy=multi-user.target
  1. Include the service file in your deb package: Place the myapp.service file in the /lib/systemd/system/ path within your package directory.
myapp-pkg/
├── DEBIAN
│ └── control
├── lib
│ └── systemd
│ └── system
│ └── myapp.service
└── usr
└── local
└── bin
└── myapp

After repackaging, installing the deb will automatically deploy the service file to the correct location.

6.2. Managing Services with systemctl

After installing the deb package containing the service file, you can use systemctl on the device to manage your service.

# Enable service to start on boot
systemctl enable myapp.service

# Start service immediately
systemctl start myapp.service

# Check service status
systemctl status myapp.service

# Stop service
systemctl stop myapp.service

# Disable auto-start on boot
systemctl disable myapp.service

Use journalctl -u myapp.service to view standard output and error logs from your application service.

7. Debugging and Troubleshooting

7.1. Remote Debugging

You can use gdbserver to run your program on the device, then use gdb from your development host's cross-compilation toolchain for remote debugging.

Note: If gdbserver is not installed on your device, install it first with:

sudo apt-get update
sudo apt-get install gdbserver
  1. Start gdbserver on the device:
gdbserver :1234 ./your-application
  1. Start gdb on your development host:
# Start gdb client
aarch64-linux-gnu-gdb ./your-application

# Inside gdb, connect to remote gdbserver
(gdb) target remote 192.168.0.1:1234

Once connected, you can debug just as you would locally - setting breakpoints, stepping through code, etc.

7.2. Log Analysis

  • systemd Service Logs: Use journalctl -u your-app.service -f to view service logs in real-time.

  • System Logs: Use dmesg or journalctl to view system-level logs for troubleshooting environment-related issues.

7.3. Common Diagnostic Tools

The device comes preinstalled with standard Linux diagnostic tools to help you identify issues:

  • top: View system resource usage and process status.

  • strace: Trace system calls and signals for analyzing program behavior.

  • netstat / ss: View network connection status.

  • tcpdump: Perform network packet capture and analysis.

    • Related Articles

    • RobustOS Pro Third-Party Application Development Guide

      1. Quick Overview What is RobustOS Pro? RobustOS Pro is an embedded Linux distribution based on Debian 11 (bullseye), designed specifically to meet the demanding requirements of industrial IoT gateways, providing a high degree of customization and ...
    • RobustOS Pro Application Development Getting Started

      Preface Welcome to RobustOS Pro! This guide provides a step-by-step roadmap for understanding, developing, and deploying applications on the platform. This document is only applicable to RobustOS Pro 2.4.x firmware versions. System Architecture ...
    • RobustOS Pro SDK - Quick Start Guide

      Prerequisites Before you begin, ensure you have: Hardware: One of the supported RobustOS Pro devices (EG5100, LG5100, R1520LG, EV8100, EG5101, EG5200, EG5120, or EG3110) Network Access: SSH access to your device User Account: A sudo user account on ...
    • How to Install Grafana on Debian 11

      To install Grafana on Debian 11, follow the steps below. Grafana provides its own APT repository for Debian-based distributions, which ensures you get the latest version. This guide will show you how to install Grafana from the official repository. ...
    • NetworkManager Integration Guide

      1. Overview This document provides guidance for third-party application developers working on network-related development on RobustOS Pro devices. RobustOS Pro uses NetworkManager (NM) as its core network management service and provides two primary ...