Skip to content

Commit d61882c

Browse files
committed
Add logic for rebuilding modules when dependencies change
1 parent 2ebf9ee commit d61882c

1 file changed

Lines changed: 166 additions & 2 deletions

File tree

dkms.in

Lines changed: 166 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

15321561
prepare_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

Comments
 (0)