Yocto Kernel Configuration - Part 2: Machine-Specific defconfig and bbappend
This is the second part of our Yocto kernel configuration series. In this article, we’ll focus on creating machine-specific defconfig files and managing bbappend files for different machines with linux-variscite.
Overview
In this part, you’ll learn how to:
- ✅ Create different defconfig files for development and production
- ✅ Manage bbappend files with machine-specific configurations
- ✅ Use conditional logic in bbappend files
- ✅ Organize your Yocto layer for multiple machine configurations
Prerequisites
Before starting this part, make sure you’ve completed:
- Part 1: Getting Started with Devshell
- You have a working Yocto build environment
- You understand basic devshell operations
Understanding Your Current bbappend Setup
If you already have a bbappend file that uses custom defconfig:
# Your existing linux-variscite_%.bbappend might look like:
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://defconfig"
do_configure:prepend () {
cp "${WORKDIR}/defconfig" "${B}/.config"
}This approach works but limits you to a single configuration for all machines.
Creating Machine-Specific defconfig Files
Step 1: Generate Different Configurations
# Start devshell
bitbake -c devshell virtual/kernel
# Create development configuration (modules for easier debugging)
make olddefconfig
make menuconfig
# Configure for development:
# - ToF drivers as modules (=m)
# - Debug options enabled
# - Additional logging enabled
make savedefconfig
BUILD_DIR="/workdir/tmp/work/imx8mp_var_som_mlx75027-poky-linux/linux-variscite/5.15.60+gitAUTOINC+740e6c7a7b-r2/build"
cp "$BUILD_DIR/defconfig" ~/defconfig-dev
# Create production configuration (built-in for performance)
make menuconfig
# Configure for production:
# - ToF drivers built-in (=y)
# - Debug options disabled
# - Optimized for size/performance
make savedefconfig
cp "$BUILD_DIR/defconfig" ~/defconfig-prod
exitStep 2: Copy defconfig Files to Your Yocto Layer
# Copy the defconfig files to your meta layer
YOCTO_LAYER="/path/to/your/meta-layer/recipes-kernel/linux/linux-variscite"
# Copy different configurations
cp ~/defconfig-dev "$YOCTO_LAYER/defconfig-dev"
cp ~/defconfig-prod "$YOCTO_LAYER/defconfig-prod"
# Keep original as fallback
cp ~/defconfig-dev "$YOCTO_LAYER/defconfig" # Use dev as defaultStep 3: Compare Configurations
# See what's different between configurations
diff -u "$YOCTO_LAYER/defconfig-dev" "$YOCTO_LAYER/defconfig-prod"
# Example output:
# -CONFIG_VIDEO_MLX7502X=m
# +CONFIG_VIDEO_MLX7502X=y
# -CONFIG_DEBUG_KERNEL=y
# +# CONFIG_DEBUG_KERNEL is not setManaging bbappend Files for Multiple Machines
Option 1: Conditional Logic (Most Flexible)
# Your linux-variscite_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
# Add all defconfig files to SRC_URI
SRC_URI += " \
file://defconfig \
file://defconfig-dev \
file://defconfig-prod \
"
# Modified configure prepend with machine detection
do_configure:prepend () {
# Use machine-specific defconfig if available
case "${MACHINE}" in
"imx8mp-var-som-dev"|"imx8mp-var-som-mlx75027-dev")
if [ -f "${WORKDIR}/defconfig-dev" ]; then
echo "Using development defconfig for ${MACHINE}"
cp "${WORKDIR}/defconfig-dev" "${B}/.config"
else
echo "Development defconfig not found, using default for ${MACHINE}"
cp "${WORKDIR}/defconfig" "${B}/.config"
fi
;;
"imx8mp-var-som-prod"|"imx8mp-var-som-mlx75027-prod")
if [ -f "${WORKDIR}/defconfig-prod" ]; then
echo "Using production defconfig for ${MACHINE}"
cp "${WORKDIR}/defconfig-prod" "${B}/.config"
else
echo "Production defconfig not found, using default for ${MACHINE}"
cp "${WORKDIR}/defconfig" "${B}/.config"
fi
;;
*)
echo "Using default defconfig for ${MACHINE}"
cp "${WORKDIR}/defconfig" "${B}/.config"
;;
esac
}Option 2: Machine Override (Cleaner)
# Your linux-variscite_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
# Base SRC_URI with default defconfig
SRC_URI += "file://defconfig"
# Machine-specific defconfig files (only added for specific machines)
SRC_URI:append:imx8mp-var-som-dev = " file://defconfig-dev"
SRC_URI:append:imx8mp-var-som-prod = " file://defconfig-prod"
# Base configure function (default behavior)
do_configure:prepend () {
cp "${WORKDIR}/defconfig" "${B}/.config"
}
# Machine-specific overrides (these override the base function)
do_configure:prepend:imx8mp-var-som-dev () {
if [ -f "${WORKDIR}/defconfig-dev" ]; then
echo "Using development defconfig for ${MACHINE}"
cp "${WORKDIR}/defconfig-dev" "${B}/.config"
else
echo "Development defconfig not found, using default"
cp "${WORKDIR}/defconfig" "${B}/.config"
fi
}
do_configure:prepend:imx8mp-var-som-prod () {
if [ -f "${WORKDIR}/defconfig-prod" ]; then
echo "Using production defconfig for ${MACHINE}"
cp "${WORKDIR}/defconfig-prod" "${B}/.config"
else
echo "Production defconfig not found, using default"
cp "${WORKDIR}/defconfig" "${B}/.config"
fi
}Option 3: Simple Machine-Specific (Recommended)
# Your linux-variscite_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
# Default defconfig for all machines
SRC_URI += "file://defconfig"
# Machine-specific defconfig files (only fetched for specific machines)
SRC_URI:append:imx8mp-var-som-dev = " file://defconfig-dev"
SRC_URI:append:imx8mp-var-som-prod = " file://defconfig-prod"
# Simple machine-specific override
do_configure:prepend:imx8mp-var-som-dev () {
cp "${WORKDIR}/defconfig-dev" "${B}/.config"
}
do_configure:prepend:imx8mp-var-som-prod () {
cp "${WORKDIR}/defconfig-prod" "${B}/.config"
}
# Default behavior for other machines (uses base defconfig)
do_configure:prepend () {
# Only run if no machine-specific override was executed
if [ ! -f "${B}/.config" ]; then
cp "${WORKDIR}/defconfig" "${B}/.config"
fi
}Version Control Your Changes
Step 1: Initialize Git in Your Meta Layer
# In your meta layer directory
cd /path/to/your/meta-layer
# Initialize git if needed
if [ ! -d ".git" ]; then
git init
git add .
git commit -m "Initial meta layer commit"
fiStep 2: Add New defconfig Files
# Add the new defconfig files
git add recipes-kernel/linux/linux-variscite/defconfig-dev
git add recipes-kernel/linux/linux-variscite/defconfig-prod
git add recipes-kernel/linux/linux-variscite_%.bbappend
# Create commit
git commit -m "linux-variscite: Add machine-specific defconfig support
Add support for different kernel configurations per machine:
- defconfig-dev: Development configuration with modules and debug
- defconfig-prod: Production configuration with built-in drivers
- Updated bbappend with machine-specific logic
This enables different kernel configurations for development
and production builds of the same hardware platform.
Signed-off-by: Your Name <your.email@example.com>"Testing Your Configuration
Step 1: Test Development Build
# Set machine to development
export MACHINE=imx8mp-var-som-dev
# Clean and rebuild
bitbake -c cleansstate linux-variscite
bitbake linux-variscite
# Verify correct defconfig was used
bitbake -c devshell linux-variscite
# In devshell:
grep -E "CONFIG_VIDEO_MLX7502X|CONFIG_DEBUG_KERNEL" .config
# Should show modules (=m) and debug enabled for dev build
exitStep 2: Test Production Build
# Set machine to production
export MACHINE=imx8mp-var-som-prod
# Clean and rebuild
bitbake -c cleansstate linux-variscite
bitbake linux-variscite
# Verify correct defconfig was used
bitbake -c devshell linux-variscite
# In devshell:
grep -E "CONFIG_VIDEO_MLX7502X|CONFIG_DEBUG_KERNEL" .config
# Should show built-in (=y) and debug disabled for prod build
exitCommon Issues and Solutions
Issue 1: Wrong defconfig Used
# Check which defconfig was actually copied
bitbake -c devshell linux-variscite
# In devshell:
echo "Current machine: ${MACHINE}"
ls -la "${WORKDIR}"/defconfig*
# Verify the correct files are presentIssue 2: Machine Override Not Working
# Check machine-specific overrides
bitbake -e linux-variscite | grep "do_configure:prepend"
# Should show the machine-specific function if override is workingIssue 3: SRC_URI Not Fetching Files
# Check SRC_URI expansion
bitbake -e linux-variscite | grep "^SRC_URI="
# Should show your defconfig files in the listBest Practices
1. Naming Conventions
# Use descriptive names for defconfig files:
defconfig-dev # Development configuration
defconfig-prod # Production configuration
defconfig-debug # Debug configuration
defconfig-minimal # Minimal configuration2. Documentation
# Document your configurations in the meta layer
# Create a README.md in recipes-kernel/linux/linux-variscite/
echo "# Kernel Configurations
## defconfig-dev
- ToF drivers as modules for easier debugging
- Debug options enabled
- Additional logging enabled
## defconfig-prod
- ToF drivers built-in for performance
- Debug options disabled
- Optimized for size/performance
" > "$YOCTO_LAYER/README.md"3. Testing Matrix
# Test all machine configurations
MACHINES="imx8mp-var-som-dev imx8mp-var-som-prod"
for machine in $MACHINES; do
echo "Testing $machine..."
export MACHINE=$machine
bitbake -c cleansstate linux-variscite
bitbake linux-variscite
echo "$machine build completed"
doneNext Steps
In the next parts of this series, we’ll cover:
- Part 3: Git-based version control and patch management
- Part 4: Advanced configuration management and automation
Quick Reference
# Machine-specific bbappend template:
SRC_URI:append:machine-dev = " file://defconfig-dev"
SRC_URI:append:machine-prod = " file://defconfig-prod"
do_configure:prepend:machine-dev () {
cp "${WORKDIR}/defconfig-dev" "${B}/.config"
}
do_configure:prepend:machine-prod () {
cp "${WORKDIR}/defconfig-prod" "${B}/.config"
}This approach gives you flexible, maintainable machine-specific kernel configurations that scale with your project needs.
