%kroko_kmods_dir %{_datadir}/auto-krokodil/kmods # Versioning must be the same when building both inside nvidia and kernel pkg, # but the first part will indicate a newer build, the second part will indicate from which SRPM # this module was built from and will allow to avoid same filenames of RPMs with # modules from different SRPMs even if they are built at the same time (second). # Unfortunately, if we generate release inside %%kroko_kmod_pkg, every usage of # a macro with it will cause its regeneration, so it may be incosistent across one package. # Usage example: # %%define kroko_release %%kroko_mk_release -n %%{NAME} # %%kroko_kmod_pkg -r %%kroko_mk_release <...> %kroko_mk_release(n:) %(echo $(( $(date +%%s) - $(date -d "Sep 12 00:00:00 MSK 2022" +%%s) ))).%(printf "%%d" "'$(head -c1 /dev/urandom | base64)").%(echo %{-n*} | sha1sum | head -c5) # r - Release, generated using %%kroko_mk_release # j - major Nvidia version (e.g. 390 from full version 390.13) # n - minor Nvidia version (e.g. 13 from full version 390.13) # f - kernel flavour (e.g. generic from kernel-5.10-generic) # k - kernel version (e.g. 5.10 from kernel-5.10-generic) # m - kernel patch level (71 from 5.10.71) # p - full kernel version (uname -r), e.g.: 5.10.71-generic-1rosa2021.1-x86_64) # s - source package name (e.g.: nvidia390, kernel-5.10-generic) # c - module compression (.zst, .xz, .gz or "") %kroko_kmod_pkg(r:j:n:f:k:m:p:s:c:d:) \ # e.g.: kernel-modules-nvidia390-5.10-generic \ %define pkg kernel-modules-nvidia%{-j*}-%{-k*}-%{-f*} \ # alternatives name must be unique for each kernel, but avoid \ # too long names of alternatives by using a hash of kernel name \ %define alternatives_name kmods-nvidia%{-j*}.%(echo %{-p*} | md5sum | head -c 6) \ \ %{expand: \ %package -n %{pkg} \ Summary: Binary modules of Nvidia %{-j*}.%{-n*} for kernel-%{-k*}-%{-f*} \ Group: System/Kernel and hardware \ Version: %{-j*}.%{-n*} \ Release: %{-r*} \ Supplements: (kernel-abi(%{-p*}) and nvidia%{-j*}) \ Requires: auto-krokodil-filesystem \ Provides: installonlypkg(kernel) = %{-k*}.%{-m*}.module \ # e.g.: kmod-nvidia390.13-kabi(5.10.71-generic-1rosa2021.1-x86_64) = 456.2e9d1.15 \ Provides: kmod-nvidia%{-j*}.%{-n*}-kabi(%{-p*}) = %{-r*} \ Provides: kmod-nvidia%{-j*}-kabi(%{-p*}) = %{-r*} \ # A generic provide to be able to e.g. "Conflict" with a binary module from dkms if needed \ Provides: kmod-bin-nvidia = %{-j*} \ # When nvidiaXXX is installed, this package with kernel modules is installed, # but, when nvidiaXXX is removed, this packages is not automatically removed # as an orphaned package (probably a bug in (lib)dnf) (dnf autoremove does remove it), # so, when upgrading, to a newer major (j) version of Nvidia driver, modules of both # versions will be installed, there will be modules of the same name in different # directories, a random one will be chosen, so force removing an odd module. Conflicts: kmod-bin-nvidia < %{-j*} \ Conflicts: kmod-bin-nvidia > %{-j*} \ # e.g.: kmod-nvidia390-kabi(5.10.71-generic-1rosa2021.1-x86_64) = 456.2e9d1.15 \ # Do not keep older builds for the same kernel installed via installonlypkg() \ # () and provides are not allowed in Obsoletes, only real package names work as Obsoletes, \ # so we can't write: "Obsoletes: kmod-nvidia%{-j*}.%{-n*}-kabi(%{-p*}) < %{-r*}" \\ # XXX Without Obsoletes for now, otherwise modules for e.g. 5.10.71 will be removed when updating to 5.10.72 \ #Obsoletes: %{pkg} < %{-j*}.%{-n*}-%{-r*} \ # the same files conflict \ #Conflicts: kmod-nvidia%{-j*}.%{-n*}-kabi(%{-p*}) < %{-r*} \ # e.g.: kmod-nvidia-5.10-generic(390.13) = 456.2e9d1.15 \ Provides: kmod-nvidia-%{-k*}-%{-f*}(%{-j*}.%{-n*}) = %{-r*} \ Requires: kernel-abi(%{-p*}) \ # modules dependencies must be installed when depmod is run \ Requires(post): kernel-abi(%{-p*}) \ Requires(post): update-alternatives \ Requires(post): %{_sbindir}/depmod \ Requires(postun): update-alternatives \ Requires(posttrans): %{_sbindir}/depmod \ %description -n %{pkg} \ Binary modules of Nvidia %{-j*}.%{-n*} for kernel-%{-k*}-%{-f*} \ Built from %{-s*} \ %files -n %{pkg} \ %dir %{kroko_kmods_dir}/nvidia%{-j*}.%{-r*}-%{-p*} \ %{kroko_kmods_dir}/nvidia%{-j*}.%{-r*}-%{-p*}/*.ko%{-c*} \ %ghost /lib/modules/%{-p*}/kernel/drivers/video/nvidia%{-j*} \ /var/spool/initramfs-regen/nvidia%{-j*}.%{-r*} \ %post -n %{pkg} \ update-alternatives --install \\ /lib/modules/%{-p*}/kernel/drivers/video/nvidia%{-j*} \\ %{alternatives_name} \\ %{kroko_kmods_dir}/nvidia%{-j*}.%{-r*}-%{-p*} \\ %(echo %{-r*} | awk -F '.' '{print $1}') \ %{_sbindir}/depmod -a %{-p*} || : \ %postun -n %{pkg} \ # updated version of pkg always has another -r \ update-alternatives --remove \\ %{alternatives_name} \\ %{kroko_kmods_dir}/nvidia%{-j*}.%{-r*}-%{-p*} \ %{_sbindir}/depmod -a %{-p*} || : \ %posttrans -n %{pkg} \ if [ -d /lib/modules/%{-p*} ]; then %{_sbindir}/depmod -a %{-p*} || : ; fi } # Dependencies in kernel package # Dependencies are soft ("Recommends" insted of "Requires") to do not # fail if an Nvidia kernel module cannot be installed for one # of the installed kernels which is not the newest one %kroko_req_modules_in_kernel(j:n:p:) \ %{expand: \ Recommends: (kmod-nvidia%{-j*}-kabi(%{-p*}) if nvidia%{-j*}) \ %{nil} \ } # Dependencies in nvidiaXXX package # "Requires", not "Recommends" here despite "Recommends" above # to have strong dependencies at least here and avoid accidently # and silently leaving users without Nvidia kernel modules # (force installing a binary module for at least the latest kernel) %kroko_req_modules_in_nvidia(k:f:j:n:) \ %{expand: \ # e.g.: (kmod-nvdia-5.10-generic(390.13) if kernel-5.10-generic) Requires: (kmod-nvidia-%{-k*}-%{-f*}(%{-j*}.%{-n*}) if kernel-%{-k*}-%{-f*}) \ %{nil} \ } # Extract major and minor versions of package $1 # Example: # kernel-source-nvidia390 has version 390.5 # korko_j will extract 390, kroko_n will extract 5 # See also: https://github.com/rpm-software-management/rpm/pull/1794 # p - name of package which version to extract (e.g.: kernel-source-nvidia390) # r - any number (e.g.: 0, 1, 390 etc.) # needed at SRPM stage when _j and _n cannot extract real versions to avoid duplicate subpackages %kroko_j(p:r:) %(if rpm -q %{-p*} >/dev/null 2>&1; then rpm -q --qf '%%{version}' %{-p*} | awk -F '.' '{print $1}'; else echo %{-r*}; fi) %kroko_n(p:r:) %(if rpm -q %{-p*} >/dev/null 2>&1; then rpm -q --qf '%%{version}' %{-p*} | awk -F '.' '{print $2}'; else echo %{-r*}; fi)