@@ -93,7 +93,7 @@ readonly dkms_conf_variables="PACKAGE_NAME
9393 built_module_name BUILT_MODULE_LOCATION built_module_location
9494 DEST_MODULE_NAME dest_module_name
9595 DEST_MODULE_LOCATION dest_module_location
96- STRIP strip AUTOINSTALL NO_WEAK_MODULES
96+ STRIP strip AUTOINSTALL NO_WEAK_MODULES BUILD_DEPENDS_REBUILD
9797
9898 CLEAN
9999 REMAKE_INITRD MODULES_CONF MODULES_CONF_OBSOLETES
@@ -833,6 +833,21 @@ read_conf()
833833 ;;
834834 esac
835835
836+ # Check for allowed BUILD_DEPENDS_REBUILD values: "yes", "no", ""
837+ case " $BUILD_DEPENDS_REBUILD " in
838+ " " )
839+ ;;
840+ [Yy][Ee][Ss])
841+ ;;
842+ [Nn][Oo])
843+ BUILD_DEPENDS_REBUILD=" "
844+ ;;
845+ * )
846+ echo " dkms.conf: Error! Unsupported BUILD_DEPENDS_REBUILD value '$BUILD_DEPENDS_REBUILD '" >&2
847+ return_value=1
848+ ;;
849+ esac
850+
836851 (( return_value == 0 )) && last_mvka=" $module /$module_version /$1 /$2 " && last_mvka_conf=" $( readlink -f " $read_conf_file " ) "
837852 return $return_value
838853}
@@ -1527,6 +1542,20 @@ do_build()
15271542
15281543 # Clean the build directory
15291544 rm -rf " ${build_dir:? } "
1545+
1546+ # After successful build, save dependency versions
1547+ if [[ $BUILD_DEPENDS_REBUILD ]]; then
1548+ mkdir -p " $base_dir "
1549+ for bd in " ${BUILD_DEPENDS[@]} " ; do
1550+ local dep_version
1551+ dep_version=$( module_status " $bd " " *" " $kernelver " " $arch " | while read -r status mvka; do
1552+ [[ $status ]] || continue
1553+ IFS=' /' read -r m v k a <<< " $mvka"
1554+ echo " $v "
1555+ done | sort -V | tail -n1)
1556+ [[ $dep_version ]] && echo " $dep_version " > " $base_dir /.dep_${bd} "
1557+ done
1558+ fi
15301559}
15311560
15321561prepare_kernel_and_signing ()
@@ -1740,6 +1769,11 @@ do_install()
17401769
17411770 # Restore the status of $force
17421771 force=" $tmp_force "
1772+
1773+ if [[ $BUILD_DEPENDS_REBUILD ]]; then
1774+ # First check and rebuild any modules with updated dependencies
1775+ check_and_rebuild_dependent_modules " ${kernelver[0]} " " ${arch[0]} "
1776+ fi
17431777}
17441778
17451779# List each kernel object that has been installed for a particular module.
@@ -2777,7 +2811,7 @@ autoinstall() {
27772811 continue
27782812 fi
27792813 # If the module does not want to be autoinstalled, skip it.
2780- module= $m module_version= $v read_conf_or_die " ${kernelver[0]} " " ${arch[0]} " " $dkms_tree /$m /$v /source/dkms.conf"
2814+ read_conf_or_die " ${kernelver[0]} " " ${arch[0]} " " $dkms_tree /$m /$v /source/dkms.conf"
27812815 if [[ ! $AUTOINSTALL ]]; then
27822816 continue
27832817 fi
@@ -2954,6 +2988,136 @@ kernel_prerm()
29542988 [[ ! $failed ]] || die 14 " dkms kernel_prerm for kernel ${kernelver[0]} (${arch[0]} ) failed for module(s)$failed ."
29552989}
29562990
2991+ # Check if a module's dependencies have been updated
2992+ check_dependencies_updated () {
2993+
2994+ local module=$1
2995+ local module_version=$2
2996+
2997+ # $1 = module
2998+ # $2 = module version
2999+ # $3 = kernel version
3000+ # $4 = arch
3001+
3002+ local deps_updated=0
3003+
3004+ # Read the module's configuration
3005+ set_module_suffix " $3 "
3006+ read_conf_strict_or_die " $3 " " $4 "
3007+
3008+ # Check each dependency
3009+ for bd in " ${BUILD_DEPENDS[@]} " ; do
3010+ # Get the latest version of the dependency
3011+ local dep_version
3012+ dep_version=$( module_status " $bd " " *" " $3 " " $4 " | while read -r status mvka; do
3013+ [[ $status ]] || continue
3014+ IFS=' /' read -r m v k a <<< " $mvka"
3015+ echo " $v "
3016+ done | sort -V | tail -n1)
3017+
3018+ # If dependency is not installed, skip it
3019+ [[ $dep_version ]] || continue
3020+
3021+ # Check if dependency's version has changed since last build
3022+ local dep_version_file=" $dkms_tree /$module /$module_version /$3 /$4 /.dep_${bd} "
3023+ if [[ -f " $dep_version_file " ]]; then
3024+ local old_version
3025+ old_version=$( cat " $dep_version_file " )
3026+ if [[ " $old_version " != " $dep_version " ]]; then
3027+ deps_updated=1
3028+ break
3029+ fi
3030+ else
3031+ deps_updated=1
3032+ break
3033+ fi
3034+ done
3035+
3036+ return $deps_updated
3037+ }
3038+
3039+ # Check and rebuild all modules with updated dependencies
3040+ check_and_rebuild_dependent_modules () {
3041+
3042+ # $1 = kernel version
3043+ # $2 = arch
3044+
3045+ local -a modules_to_rebuild
3046+ local -a rebuilt_modules
3047+ local progress=1
3048+
3049+ # First pass: collect all modules that need rebuilding
3050+ while read -r status mvka; do
3051+ [[ $status ]] || continue
3052+ IFS=' /' read -r m v k a <<< " $mvka"
3053+ # Skip if not built for this kernel/arch
3054+ [[ " $k " = " $1 " && " $a " = " $2 " ]] || continue
3055+
3056+ # Read module's configuration
3057+ read_conf_or_die " $1 " " $2 " " $dkms_tree /$m /$v /source/dkms.conf"
3058+
3059+ # Skip if no BUILD_DEPENDS
3060+ [[ ${# BUILD_DEPENDS[@]} -eq 0 ]] && continue
3061+
3062+ # Check if dependencies have been updated
3063+ if ! check_dependencies_updated " $m " " $v " " $1 " " $2 " ; then
3064+ modules_to_rebuild+=(" $m /$v " )
3065+ fi
3066+ done <<< " $(module_status)"
3067+
3068+ # Second pass: rebuild modules in dependency order
3069+ while (( progress > 0 )) ; do
3070+ progress=0
3071+ local -a next_rebuild
3072+
3073+ # Remove already rebuilt modules from dependency lists
3074+ for mv in " ${modules_to_rebuild[@]} " ; do
3075+ IFS=/ read -r m v <<< " $mv"
3076+ read_conf_or_die " $1 " " $2 " " $dkms_tree /$m /$v /source/dkms.conf"
3077+
3078+ # Check if all dependencies are satisfied
3079+ # shellcheck disable=SC2034
3080+ local can_rebuild=1
3081+ for bd in " ${BUILD_DEPENDS[@]} " ; do
3082+ local dep_found=0
3083+ for rm in " ${rebuilt_modules[@]} " ; do
3084+ IFS=/ read -r dm <<< " $rm"
3085+ [[ " $dm " = " $bd " ]] && dep_found=1 && break
3086+ done
3087+ if (( ! dep_found )) ; then
3088+ can_rebuild=0
3089+ break
3090+ fi
3091+ done
3092+
3093+ if (( ! can_rebuild )) ; then
3094+ module=$m module_version=$v
3095+ echo " "
3096+ echo " Rebuilding module $m /$v due to updated dependencies"
3097+ echo " "
3098+ do_uninstall " $1 " " $2 "
3099+ do_unbuild " $1 " " $2 "
3100+ if do_build; then
3101+ do_install
3102+ rebuilt_modules+=(" $m /$v " )
3103+ progress=1
3104+ fi
3105+ else
3106+ next_rebuild+=(" $m /$v " )
3107+ fi
3108+ done
3109+ modules_to_rebuild=(" ${next_rebuild[@]} " )
3110+ done
3111+
3112+ # Report any modules that couldn't be rebuilt
3113+ if (( ${# modules_to_rebuild[@]} > 0 )) ; then
3114+ echo " Warning: The following modules could not be rebuilt due to dependency cycles:"
3115+ for mv in " ${modules_to_rebuild[@]} " ; do
3116+ echo " $mv "
3117+ done
3118+ fi
3119+ }
3120+
29573121# ############################
29583122# ### ####
29593123# ### Program Starts Here ####
0 commit comments