Skip to main content

Install Packages from a Development Host

Runtime package installation is useful for quickly testing and debugging software without rebuilding and flashing a complete image. This tutorial uses nano to demonstrate two methods:

  1. Copy one package to the board with ADB and install it locally.
  2. Install the package by name from an indexed HTTP feed on the development host.

These changes are temporary development changes. A package installed at runtime is not automatically included after flashing a new image. Add required production packages to the image configuration instead.

danger

The HTTP example uses unsigned packages on a trusted development network. Bind the server only to the relevant LAN address and do not use this setup as a production update service.

Before You Start

You need a completed image build, the matching image running on the board, ADB access, and a network connection between the development host and target for the HTTP method.

The package backend determines the generated package format and target package manager. It can vary between BSPs, image configurations, and releases, so check the selected build configuration instead of assuming a particular backend. This tutorial provides IPK with opkg and DEB with apt examples.

note

The current default Grinn Genio BSP and Grinn Astra BSP image configurations enable the package-management image feature. A custom image or configuration can change or remove it, so confirm that the expected package manager is available on the running target before continuing.

If the package manager is absent, add the following setting to the image or kas configuration, rebuild the image, and flash it before continuing:

EXTRA_IMAGE_FEATURES:append = " package-management"

The leading space in the appended value is required.

Confirm ADB and the expected package manager:

Development host
adb devices -l
Development host
adb shell 'command -v opkg && opkg --version'

1. Configure the BSP Workspace

Run host build commands from the root of the selected BSP workspace. The IPK (opkg) examples below use Grinn Genio BSP, and the DEB (apt) examples use Grinn Astra BSP.

Development host
export KAS_CONFIG="meta-grinn-genio/kas/default.yml"
export KAS_MACHINE=grinn-genio-700-sbc
export KAS_CONTAINER_IMAGE_DISTRO=debian-bookworm
export PACKAGE=nano

If the running image was built with kas extensions, include the same extensions in KAS_CONFIG.

This tutorial uses nano as the example and assumes it is not already installed on the target.

2. Build the Package

Build the recipe using the same configuration as the running image:

Development host
kas-container build --target "$PACKAGE" "$KAS_CONFIG"

Here, --target nano selects the BitBake recipe. It does not refer to the physical board, rebuild the complete image, or install anything on the board.

Yocto places generated packages under build/tmp/deploy. List the package for the selected backend:

Development host
ls -1 build/tmp/deploy/ipk/*/"${PACKAGE}"_*.ipk

Example output:

build/tmp/deploy/ipk/armv8a/nano_7.2-r0_armv8a.ipk

Copy the displayed path into PACKAGE_FILE:

Development host
export PACKAGE_FILE="$PWD/build/tmp/deploy/ipk/armv8a/<selected-package>.ipk"
tip

If the package is not under the expected deployment directory, search the current build as a fallback:

Development host
find build/tmp/deploy -type f \
\( -name "${PACKAGE}_*.ipk" -o -name "${PACKAGE}_*.deb" \) -print

3. Method 1: Install One Local Package through ADB

This method is useful for one package whose required dependencies are already installed. ADB copies the file; the target package manager performs and records the installation.

Development host
adb push "$PACKAGE_FILE" /tmp/nano.ipk
adb shell 'opkg install /tmp/nano.ipk
nano --version | sed -n "1p"'

Example output:

GNU nano, version 7.2

Remove the test package and transferred file before continuing to the HTTP method:

Development host
adb shell 'opkg remove nano
rm -f /tmp/nano.ipk'

4. Generate the Package Feed

Generate package indexes after the package build finishes:

Development host
kas-container shell "$KAS_CONFIG" -c 'bitbake package-index'

package-index scans packages already present in the deployment directory. It does not build every available recipe.

Set the feed root and list its indexes:

Development host
export FEED_ROOT="$PWD/build/tmp/deploy/ipk"
ls -1 "$FEED_ROOT"/*/Packages.gz

The Grinn Genio BSP example uses the all, armv8a, and grinn_genio_700_sbc feed directories. Do not use x86_64-nativesdk; it contains SDK host packages rather than target packages.

5. Serve the Feed over HTTP

The development host and board must be connected to the same trusted LAN. Replace <target-ip> with the board's address, then use the address after src as <host-lan-ip>:

Development host
ip -4 route get <target-ip>

From the feed root, start the HTTP server on that host address:

Development host
cd "$FEED_ROOT"
python3 -m http.server 8000 --bind <host-lan-ip>

Keep this terminal open while installing the package. The target must be able to reach TCP port 8000, and the host firewall must permit the connection on the selected interface.

Direct Ethernet

If an existing LAN is unavailable, a direct Ethernet cable can also carry the feed. Configure non-conflicting static addresses on the host and target, bind the server to the host's direct-cable address, and allow TCP port 8000 through the host firewall when required. Remove temporary network and firewall settings after the exercise. This tutorial assumes an existing LAN and does not change network configuration.

Before configuring the package manager, verify HTTP access from the target. Replace <feed-directory> with one of the directories containing Packages.gz:

Target device
timeout 15 wget -O /tmp/Packages.gz \
http://<host-lan-ip>:8000/<feed-directory>/Packages.gz
gzip -t /tmp/Packages.gz
rm -f /tmp/Packages.gz

6. Install from the HTTP Feed

Open a shell on the target in another terminal:

Development host
adb shell

Configure only the feed directories required by the selected target.

First, set the feed address and paths for the temporary configuration. Keeping the downloaded package lists under /tmp avoids replacing the target's existing feed metadata:

Target device
export FEED_BASE_URL=http://<host-lan-ip>:8000
export LOCAL_CONF=/tmp/grinn-opkg-local.conf
export LOCAL_LISTS=/tmp/grinn-opkg-lists
mkdir -p "$LOCAL_LISTS"

Next, create the isolated opkg configuration. It reuses the target's installed package database and architecture definitions, but reads packages only from the development feed. The feed directory names are Grinn Genio BSP examples:

Target device
{
printf '%s\n' 'dest root /'
printf 'option lists_dir %s\n' "$LOCAL_LISTS"
printf '%s\n' 'option info_dir /var/lib/opkg/info'
printf '%s\n' 'option status_file /var/lib/opkg/status'
cat /etc/opkg/arch.conf
printf 'src/gz local-all %s/all\n' "$FEED_BASE_URL"
printf 'src/gz local-arm %s/armv8a\n' "$FEED_BASE_URL"
printf 'src/gz local-machine %s/grinn_genio_700_sbc\n' \
"$FEED_BASE_URL"
} >"$LOCAL_CONF"

Download the feed indexes and confirm that nano is available:

Target device
opkg -f "$LOCAL_CONF" update
opkg -f "$LOCAL_CONF" list | grep '^nano - '

Finally, install and verify the package:

Target device
opkg -f "$LOCAL_CONF" install nano
nano --version | sed -n '1p'

The package manager reads the indexes, selects the package for the target, and downloads compatible dependencies available in the configured feeds. The installation fails if a required dependency is absent from those feeds.

7. Clean Up

Stop the HTTP server with Ctrl+C. Then remove the package and temporary package-manager configuration from the target:

Target device
opkg remove nano
rm -rf /tmp/grinn-opkg-lists
rm -f /tmp/grinn-opkg-local.conf

Runtime installation is intended for development and testing. To include a package in every newly flashed image, see Add Packages to a Yocto Image.