Implement proper recursive module dependency resolution

- Use depmod -av + modinfo -k approach for accurate dependency detection
- Copy modules to container /lib/modules for proper modinfo -k usage
- Recursive resolution until no more dependencies found
- Copy resolved modules to initramfs + run final depmod in chroot context
- Now properly finds missing core modules like virtio.ko, virtio_ring.ko
- Validates symbol dependencies with proper module database
- Fixed KERNEL_OUTPUT variable binding in build summary
This commit is contained in:
2025-09-03 18:27:06 +02:00
parent f7c67ee5dd
commit 71a824d9c4
2 changed files with 61 additions and 64 deletions

View File

@@ -346,8 +346,16 @@ function main_build_process() {
section_header "Build Complete"
log_info "Build time: ${build_minutes}m ${build_seconds}s"
log_info "Output files:"
log_info " Kernel: ${KERNEL_OUTPUT} ($(get_file_size "$KERNEL_OUTPUT"))"
log_info " Initramfs: ${INITRAMFS_ARCHIVE} ($(get_file_size "$INITRAMFS_ARCHIVE"))"
if [[ -n "${KERNEL_OUTPUT:-}" ]]; then
log_info " Kernel: ${KERNEL_OUTPUT} ($(get_file_size "$KERNEL_OUTPUT"))"
else
log_info " Kernel: ${DIST_DIR}/vmlinuz.efi ($(get_file_size "${DIST_DIR}/vmlinuz.efi" 2>/dev/null || echo "not found"))"
fi
if [[ -n "${INITRAMFS_ARCHIVE:-}" ]]; then
log_info " Initramfs: ${INITRAMFS_ARCHIVE} ($(get_file_size "$INITRAMFS_ARCHIVE"))"
else
log_info " Initramfs: ${DIST_DIR}/initramfs.cpio.xz ($(get_file_size "${DIST_DIR}/initramfs.cpio.xz" 2>/dev/null || echo "not found"))"
fi
}
# Cleanup build artifacts

View File

@@ -183,114 +183,95 @@ function initramfs_setup_modules() {
log_info " Total modules: ${stage1_count}"
}
# Resolve module dependencies using built modules from initramfs
# Resolve module dependencies using proper depmod + modinfo -k approach
function initramfs_resolve_module_dependencies() {
local modules=("$@")
local resolved_modules=()
local processed_modules=()
log_debug "Resolving dependencies for modules using built modules: ${modules[*]}"
log_debug "Resolving dependencies recursively using modinfo -k: ${modules[*]}"
# Use full kernel version from build process, not host kernel (uname -r)
# Use full kernel version from build process
local kernel_version="${KERNEL_FULL_VERSION:-${FULL_KERNEL_VERSION:-}}"
if [[ -z "$kernel_version" ]]; then
# Fallback: calculate from KERNEL_VERSION + LOCALVERSION
source "${LIB_SCRIPT_DIR}/kernel.sh"
kernel_version=$(kernel_get_full_version "${KERNEL_VERSION:-6.12.44}" "${PROJECT_ROOT}/config/kernel.config")
fi
# Use the built modules from initramfs directory (host path)
local modules_path="${PROJECT_ROOT}/initramfs/lib/modules/${kernel_version}"
# Set up container modules directory for proper modinfo -k usage
local container_modules_path="/lib/modules/${kernel_version}"
local source_modules_path="${PROJECT_ROOT}/initramfs/lib/modules/${kernel_version}"
log_debug "Using target kernel version: ${kernel_version}"
log_debug "Looking for built modules at: ${modules_path}"
log_debug "Using kernel version: ${kernel_version}"
log_debug "Source modules: ${source_modules_path}"
log_debug "Container modules: ${container_modules_path}"
if [[ ! -d "$modules_path" ]]; then
log_warn "Built modules not found at: $modules_path"
log_warn "Falling back to simple module list without dependencies"
# Verify source modules exist
if [[ ! -d "$source_modules_path" ]]; then
log_warn "Built modules not found at: $source_modules_path"
log_warn "Falling back to simple module list"
printf '%s\n' "${modules[@]}"
return 0
fi
# Ensure depmod has been run on the built modules
if [[ ! -f "${modules_path}/modules.dep" ]]; then
log_info "Running depmod on built modules"
depmod -a -b "${PROJECT_ROOT}/initramfs" "$kernel_version" 2>/dev/null || {
log_warn "depmod failed, using simple module list"
printf '%s\n' "${modules[@]}"
return 0
}
fi
# Copy modules to container /lib/modules for proper modinfo -k usage
log_info "Setting up container modules for dependency resolution"
safe_mkdir "$container_modules_path"
safe_execute cp -r "${source_modules_path}"/* "$container_modules_path/"
log_debug "Using built modules from: $modules_path"
# Run depmod to build dependency database
log_info "Running depmod -av for dependency resolution"
safe_execute depmod -av "$kernel_version" >/dev/null
# Function to recursively resolve a single module's dependencies (with depth limit)
# Recursive dependency resolution function
function resolve_single_module() {
local module="$1"
local depth="${2:-0}"
local max_depth=3 # Limit dependency depth to prevent explosion
local max_depth=5 # Allow deeper recursion for proper resolution
# Skip if already processed
if printf '%s\n' "${processed_modules[@]}" | grep -q "^${module}$"; then
return 0
fi
# Skip if we've gone too deep
# Skip if too deep (prevent infinite loops)
if [[ $depth -gt $max_depth ]]; then
log_debug "Skipping $module - dependency depth limit ($max_depth) reached"
log_debug "Skipping $module - depth limit ($max_depth) reached"
return 0
fi
processed_modules+=("$module")
# Get module dependencies using modinfo from built modules
# Use modinfo -k for proper dependency resolution
local deps=()
if command_exists "modinfo"; then
local modinfo_output
local module_found=false
# Find the actual module file
local module_file=$(find "$modules_path" -name "${module}.ko*" -type f | head -1)
if [[ -n "$module_file" && -f "$module_file" ]]; then
# Use direct file path for modinfo
if modinfo_output=$(modinfo "$module_file" 2>/dev/null); then
module_found=true
# Extract depends line and parse comma-separated dependencies
local depends_line=$(echo "$modinfo_output" | grep '^depends:' | head -1 | cut -d: -f2- | tr -d ' ')
if [[ -n "$depends_line" && "$depends_line" != "-" ]]; then
IFS=',' read -ra deps <<< "$depends_line"
if [[ ${#deps[@]} -gt 0 ]]; then
log_debug "Module $module (depth $depth) depends on: ${deps[*]}"
fi
local depends_line
# Use modinfo -k to query the properly indexed modules
if depends_line=$(modinfo -k "$kernel_version" "$module" 2>/dev/null | grep '^depends:' | head -1 | cut -d: -f2- | tr -d ' '); then
if [[ -n "$depends_line" && "$depends_line" != "-" ]]; then
IFS=',' read -ra deps <<< "$depends_line"
if [[ ${#deps[@]} -gt 0 ]]; then
log_debug "Module $module (depth $depth) depends on: ${deps[*]}"
fi
fi
else
# Check if module might be built-in
if grep -q "^$module\$" "${modules_path}/modules.builtin" 2>/dev/null; then
log_debug "Module $module is built-in (no .ko file needed)"
module_found=true
elif [[ "$module" == "virtio" || "$module" == "virtio_ring" ]]; then
# Special case: virtio core components may be integrated into virtio_pci in newer kernels
log_debug "Module $module is likely integrated into virtio subsystem (skipping dependency)"
module_found=true
# Check if module is built-in
if modinfo -k "$kernel_version" "$module" >/dev/null 2>&1; then
log_debug "Module $module found but no dependencies"
else
log_debug "Module $module not found - may be built-in or integrated"
log_debug "Module $module not found - likely built-in"
fi
fi
else
log_warn "modinfo not available, skipping dependency resolution"
fi
# Recursively resolve dependencies first (with incremented depth)
# Recursively resolve dependencies first (depth-first)
for dep in "${deps[@]}"; do
if [[ -n "$dep" ]]; then
resolve_single_module "$dep" $((depth + 1))
fi
done
# Add current module to resolved list (after dependencies)
# Add current module to resolved list (after dependencies for correct load order)
resolved_modules+=("$module")
}
@@ -299,7 +280,7 @@ function initramfs_resolve_module_dependencies() {
resolve_single_module "$module"
done
# Remove duplicates while preserving order
# Remove duplicates while preserving dependency order
local unique_modules=()
local seen_modules=()
@@ -310,7 +291,7 @@ function initramfs_resolve_module_dependencies() {
fi
done
log_debug "Resolved ${#unique_modules[@]} unique modules with dependencies from container"
log_debug "Resolved ${#unique_modules[@]} unique modules with recursive dependencies"
printf '%s\n' "${unique_modules[@]}"
}
@@ -776,10 +757,18 @@ function initramfs_copy_resolved_modules() {
log_info "Module copy complete: ${copied_count} copied, ${failed_count} failed"
# Run depmod in initramfs context if we have the tools
# Run depmod in initramfs context (chroot-like) for final dependency resolution
if command_exists "depmod" && [[ $copied_count -gt 0 ]]; then
log_info "Running depmod for initramfs modules"
safe_execute depmod -a -b "$initramfs_dir" "$kernel_version"
log_info "Running depmod in initramfs context for final module database"
safe_execute depmod -av -b "$initramfs_dir" "$kernel_version"
# Verify modules.dep was created properly
if [[ -f "${initramfs_modules_dir}/modules.dep" ]]; then
local dep_count=$(wc -l < "${initramfs_modules_dir}/modules.dep")
log_info "✓ Initramfs modules.dep created with ${dep_count} entries"
else
log_warn "modules.dep not created in initramfs"
fi
fi
return 0