]> git.proxmox.com Git - mirror_zfs.git/blob - scripts/kmodtool
cstyle: Allow URLs in C++ comments
[mirror_zfs.git] / scripts / kmodtool
1 #!/usr/bin/env bash
2 # shellcheck disable=SC2086
3
4 # kmodtool - Helper script for building kernel module RPMs
5 # Copyright (c) 2003-2012 Ville Skyttä <ville.skytta@iki.fi>,
6 # Thorsten Leemhuis <fedora@leemhuis.info>
7 # Nicolas Chauvet <kwizart@gmail.com>
8 #
9 # Permission is hereby granted, free of charge, to any person obtaining
10 # a copy of this software and associated documentation files (the
11 # "Software"), to deal in the Software without restriction, including
12 # without limitation the rights to use, copy, modify, merge, publish,
13 # distribute, sublicense, and/or sell copies of the Software, and to
14 # permit persons to whom the Software is furnished to do so, subject to
15 # the following conditions:
16 #
17 # The above copyright notice and this permission notice shall be
18 # included in all copies or substantial portions of the Software.
19 #
20 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 shopt -s extglob
29
30 myprog="kmodtool-${repo}"
31 myver="0.12.1"
32
33 kmodname=
34 build_kernels="current"
35 kernels_known_variants=
36 kernel_versions=
37 kernel_versions_to_build_for=
38 prefix=
39 filterfile=
40 target=
41 buildroot=
42 dashvariant=
43
44 error_out()
45 {
46 local errorlevel=${1}
47 shift
48 echo "Error: $*" >&2
49 # the next line is not multi-line safe -- not needed *yet*
50 echo "%global kmodtool_check echo \"kmodtool error: $*\"; exit ${errorlevel};"
51 exit "${errorlevel}"
52 }
53
54 print_rpmtemplate_header()
55 {
56 echo
57 echo "%global kmodinstdir_prefix ${prefix}/lib/modules/"
58 echo "%global kmodinstdir_postfix /extra/${kmodname}/"
59 echo "%global kernel_versions ${kernel_versions}"
60 echo
61 }
62
63 print_akmodtemplate ()
64 {
65 echo
66 cat <<EOF
67
68 %global akmod_install mkdir -p \$RPM_BUILD_ROOT/%{_usrsrc}/akmods/; \\\
69 LANG=C rpmbuild --define "_sourcedir %{_sourcedir}" \\\
70 --define "_srcrpmdir \$RPM_BUILD_ROOT/%{_usrsrc}/akmods/" \\\
71 -bs --nodeps %{_specdir}/%{name}.spec ; \\\
72 ln -s \$(ls \$RPM_BUILD_ROOT/%{_usrsrc}/akmods/) \$RPM_BUILD_ROOT/%{_usrsrc}/akmods/${kmodname}-kmod.latest
73
74 %package -n akmod-${kmodname}
75 Summary: Akmod package for ${kmodname} kernel module(s)
76 Group: System Environment/Kernel
77 Requires: kmodtool
78 Requires: akmods
79 %{?AkmodsBuildRequires:Requires: %{AkmodsBuildRequires}}
80 # same requires and provides as a kmods package would have
81 Requires: ${kmodname}-kmod-common >= %{?epoch:%{epoch}:}%{version}
82 Provides: ${kmodname}-kmod = %{?epoch:%{epoch}:}%{version}-%{release}
83 EOF
84
85 cat <<EOF
86
87 %description -n akmod-${kmodname}
88 This package provides the akmod package for the ${kmodname} kernel modules.
89
90 %posttrans -n akmod-${kmodname}
91 nohup ${prefix}/sbin/akmods --from-akmod-posttrans --akmod ${kmodname} &> /dev/null &
92
93 %files -n akmod-${kmodname}
94 %defattr(-,root,root,-)
95 %{_usrsrc}/akmods/*
96
97 EOF
98 }
99
100 print_akmodmeta ()
101 {
102 cat <<EOF
103 %package -n kmod-${kmodname}
104 Summary: Metapackage which tracks in ${kmodname} kernel module for newest kernel${dashvariant}
105 Group: System Environment/Kernel
106
107 Provides: ${kmodname}-kmod = %{?epoch:%{epoch}:}%{version}-%{release}
108 Provides: kmod-${kmodname}-xen = %{?epoch:%{epoch}:}%{version}-%{release}
109 Provides: kmod-${kmodname}-smp = %{?epoch:%{epoch}:}%{version}-%{release}
110 Provides: kmod-${kmodname}-PAE = %{?epoch:%{epoch}:}%{version}-%{release}
111 Requires: akmod-${kmodname} = %{?epoch:%{epoch}:}%{version}-%{release}
112 EOF
113
114 cat <<EOF
115
116 %description -n kmod-${kmodname}${dashvariant}
117 This is a meta-package without payload which sole purpose is to require the
118 ${kmodname} kernel module(s) for the newest kernel${dashvariant},
119 to make sure you get it together with a new kernel.
120
121 %files -n kmod-${kmodname}${dashvariant}
122 %defattr(644,root,root,755)
123 EOF
124 }
125
126 print_rpmtemplate_per_kmodpkg ()
127 {
128 if [ "${1}" = "--custom" ]; then
129 shift
130 local customkernel=true
131 elif [ "${1}" = "--redhat" ]; then
132 # this is needed for akmods
133 shift
134 local redhatkernel=true
135 fi
136
137 local kernel_uname_r=${1}
138 local kernel_variant="${2:+-${2}}"
139
140 # Detect depmod install location
141 local depmod_path=/sbin/depmod
142 if [ ! -f "${depmod_path}" ]; then
143 depmod_path=/usr/sbin/depmod
144 fi
145
146 # first part
147 cat <<EOF
148 %package -n kmod-${kmodname}-${kernel_uname_r}
149 Summary: ${kmodname} kernel module(s) for ${kernel_uname_r}
150 Group: System Environment/Kernel
151 Provides: kernel-modules-for-kernel = ${kernel_uname_r}
152 Provides: kmod-${kmodname}-uname-r = ${kernel_uname_r}
153 Provides: ${kmodname}-kmod = %{?epoch:%{epoch}:}%{version}-%{release}
154 Requires: ${kmodname}-kmod-common >= %{?epoch:%{epoch}:}%{version}
155
156 %if 0%{?rhel} == 6 || 0%{?centos} == 6
157 Requires(post): module-init-tools
158 Requires(postun): module-init-tools
159 %else
160 Requires(post): kmod
161 Requires(postun): kmod
162 %endif
163 EOF
164
165 # second part
166 if [ -z "${customkernel}" ]; then
167 cat <<EOF
168 Requires: kernel-uname-r = ${kernel_uname_r}
169 BuildRequires: kernel-devel-uname-r = ${kernel_uname_r}
170 %{?KmodsRequires:Requires: %{KmodsRequires}-uname-r = ${kernel_uname_r}}
171 %{?KmodsRequires:BuildRequires: %{KmodsRequires}-uname-r = ${kernel_uname_r}}
172 %post -n kmod-${kmodname}-${kernel_uname_r}
173 if [ -f "/boot/System.map-${kernel_uname_r}" ]; then
174 ${prefix}${depmod_path} -aeF /boot/System.map-${kernel_uname_r} ${kernel_uname_r} > /dev/null || :
175 elif [ -f "/lib/modules/${kernel_uname_r}/System.map" ]; then
176 ${prefix}${depmod_path} -aeF /lib/modules/${kernel_uname_r}/System.map ${kernel_uname_r} > /dev/null || :
177 else
178 ${prefix}${depmod_path} -ae ${kernel_uname_r} &> /dev/null || :
179 fi
180 %postun -n kmod-${kmodname}-${kernel_uname_r}
181 if [ -f "/boot/System.map-${kernel_uname_r}" ]; then
182 ${prefix}${depmod_path} -aF /boot/System.map-${kernel_uname_r} ${kernel_uname_r} &> /dev/null || :
183 elif [ -f "/lib/modules/${kernel_uname_r}/System.map" ]; then
184 ${prefix}${depmod_path} -aF /lib/modules/${kernel_uname_r}/System.map ${kernel_uname_r} &> /dev/null || :
185 else
186 ${prefix}${depmod_path} -a ${kernel_uname_r} &> /dev/null || :
187 fi
188
189 EOF
190 else
191 cat <<EOF
192 %post -n kmod-${kmodname}-${kernel_uname_r}
193 [ "\$(uname -r)" = "${kernel_uname_r}" ] && ${prefix}${depmod_path} -a > /dev/null || :
194 %postun -n kmod-${kmodname}-${kernel_uname_r}
195 [ "\$(uname -r)" = "${kernel_uname_r}" ] && ${prefix}${depmod_path} -a > /dev/null || :
196
197 EOF
198 fi
199
200 # third part
201 cat <<EOF
202 %description -n kmod-${kmodname}-${kernel_uname_r}
203 This package provides the ${kmodname} kernel modules built for the Linux
204 kernel ${kernel_uname_r} for the %{_target_cpu} family of processors.
205 %files -n kmod-${kmodname}-${kernel_uname_r}
206 %defattr(644,root,root,755)
207 %dir $prefix/lib/modules/${kernel_uname_r}/extra
208 ${prefix}/lib/modules/${kernel_uname_r}/extra/${kmodname}/
209
210
211 EOF
212 }
213
214 print_rpmtemplate_kmoddevelpkg ()
215 {
216 if [ "${1}" = "--custom" ]; then
217 shift
218 local customkernel=true
219 elif [ "${1}" = "--redhat" ]; then
220 shift
221 local redhatkernel=true
222 fi
223
224 local kernel_uname_r=${1}
225
226 cat <<EOF
227 %package -n kmod-${kmodname}-devel
228 Summary: ${kmodname} kernel module(s) devel common
229 Group: System Environment/Kernel
230 Provides: ${kmodname}-devel-kmod = %{?epoch:%{epoch}:}%{version}-%{release}
231 EOF
232
233 if [ -z "${customkernel}" ] && [ -z "${redhatkernel}" ]; then
234 echo "Requires: kmod-${kmodname}-devel-${kernel_uname_r} >= %{?epoch:%{epoch}:}%{version}-%{release}"
235 fi
236
237 cat <<EOF
238 %description -n kmod-${kmodname}-devel
239 This package provides the common header files to build kernel modules
240 which depend on the ${kmodname} kernel module. It may optionally require
241 the ${kmodname}-devel-<kernel> objects for the newest kernel.
242
243 %files -n kmod-${kmodname}-devel
244 %defattr(644,root,root,755)
245 %{_usrsrc}/${kmodname}-%{version}
246 EOF
247
248 for kernel in ${1}; do
249 local kernel_uname_r=${kernel}
250 echo "%exclude %{_usrsrc}/${kmodname}-%{version}/${kernel_uname_r}"
251 done
252
253 echo
254 echo
255 }
256
257 print_rpmtemplate_per_kmoddevelpkg ()
258 {
259 if [ "${1}" = "--custom" ]; then
260 shift
261 local customkernel=true
262 elif [ "${1}" = "--redhat" ]; then
263 # this is needed for akmods
264 shift
265 local redhatkernel=true
266 fi
267
268 local kernel_uname_r=${1}
269 local kernel_variant="${2:+-${2}}"
270
271 # first part
272 cat <<EOF
273 %package -n kmod-${kmodname}-devel-${kernel_uname_r}
274 Summary: ${kmodname} kernel module(s) devel for ${kernel_uname_r}
275 Group: System Environment/Kernel
276 Provides: kernel-objects-for-kernel = ${kernel_uname_r}
277 Provides: ${kmodname}-devel-kmod = %{?epoch:%{epoch}:}%{version}-%{release}
278 Provides: kmod-${kmodname}-devel-uname-r = ${kernel_uname_r}
279 EOF
280
281 # second part
282 if [ -z "${customkernel}" ]; then
283 cat <<EOF
284 Requires: kernel-devel-uname-r = ${kernel_uname_r}
285 BuildRequires: kernel-devel-uname-r = ${kernel_uname_r}
286 %{?KmodsDevelRequires:Requires: %{KmodsDevelRequires}-uname-r = ${kernel_uname_r}}
287 %{?KmodsDevelRequires:BuildRequires: %{KmodsDevelRequires}-uname-r = ${kernel_uname_r}}
288 EOF
289 fi
290
291 # third part
292 cat <<EOF
293 %description -n kmod-${kmodname}-devel-${kernel_uname_r}
294 This package provides objects and symbols required to build kernel modules
295 which depend on the ${kmodname} kernel modules built for the Linux
296 kernel ${kernel_uname_r} for the %{_target_cpu} family of processors.
297 %files -n kmod-${kmodname}-devel-${kernel_uname_r}
298 %defattr(644,root,root,755)
299 %{_usrsrc}/${kmodname}-%{version}/${kernel_uname_r}
300 EOF
301 }
302
303 print_rpmtemplate_kmodmetapkg ()
304 {
305 local kernel_uname_r=${1}
306 local kernel_variant="${2:+-${2}}"
307
308 cat <<EOF
309 %package -n kmod-${kmodname}${kernel_variant}
310 Summary: Metapackage which tracks in ${kmodname} kernel module for newest kernel${kernel_variant}
311 Group: System Environment/Kernel
312
313 Provides: ${kmodname}-kmod = %{?epoch:%{epoch}:}%{version}-%{release}
314 Requires: kmod-${kmodname}-${kernel_uname_r} >= %{?epoch:%{epoch}:}%{version}-%{release}
315 %{?KmodsMetaRequires:Requires: %{?KmodsMetaRequires}}
316 EOF
317
318 cat <<EOF
319
320 %description -n kmod-${kmodname}${kernel_variant}
321 This is a meta-package without payload which sole purpose is to require the
322 ${kmodname} kernel module(s) for the newest kernel${kernel_variant}.
323 to make sure you get it together with a new kernel.
324
325 %files -n kmod-${kmodname}${kernel_variant}
326 %defattr(644,root,root,755)
327
328
329 EOF
330 }
331
332 print_customrpmtemplate ()
333 {
334 for kernel in ${1}
335 do
336 if [ -e "${buildroot}/usr/src/kernels/${kernel}" ] ; then
337 # this looks like a Fedora/RH kernel -- print a normal template (which includes the proper BR) and be happy :)
338 kernel_versions="${kernel_versions}${kernel}___${buildroot}%{_usrsrc}/kernels/${kernel} "
339
340 # parse kernel versions string and print template
341 local kernel_verrelarch=${kernel%%${kernels_known_variants}}
342 print_rpmtemplate_per_kmodpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
343
344 # create development package
345 if [ -n "${devel}" ]; then
346 # create devel package including common headers
347 print_rpmtemplate_kmoddevelpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
348
349 # create devel package
350 print_rpmtemplate_per_kmoddevelpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
351 fi
352 elif [ -e "${prefix}/lib/modules/${kernel}/build/Makefile" ]; then
353 # likely a user-build-kernel with available buildfiles
354 # fixme: we should check if uname from Makefile is the same as ${kernel}
355
356 kernel_versions="${kernel_versions}${kernel}___${prefix}/lib/modules/${kernel}/build/ "
357 print_rpmtemplate_per_kmodpkg --custom "${kernel}"
358
359 # create development package
360 if [ -n "${devel}" ]; then
361 # create devel package including common headers
362 print_rpmtemplate_kmoddevelpkg --custom "${kernel}"
363
364 # create devel package
365 print_rpmtemplate_per_kmoddevelpkg --custom "${kernel}"
366 fi
367 else
368 error_out 2 "Don't know how to handle ${kernel} -- ${prefix}/lib/modules/${kernel}/build/Makefile not found"
369 fi
370 done
371
372 # well, it's no header anymore, but who cares ;-)
373 print_rpmtemplate_header
374 }
375
376
377 print_rpmtemplate ()
378 {
379 # create kernel_versions var
380 for kernel_version in ${kernel_versions_to_build_for}
381 do
382 kernel_versions="${kernel_versions}${kernel_version}___%{_usrsrc}/kernels/${kernel_version} "
383 done
384
385 # and print it and some other required stuff as macro
386 print_rpmtemplate_header
387
388 # now print the packages
389 for kernel in ${kernel_versions_to_build_for} ; do
390
391 local kernel_verrelarch=${kernel%%${kernels_known_variants}}
392
393 # create metapackage
394 print_rpmtemplate_kmodmetapkg "${kernel}" "${kernel##${kernel_verrelarch}}"
395
396 # create package
397 print_rpmtemplate_per_kmodpkg "${kernel}" "${kernel##${kernel_verrelarch}}"
398
399 if [ -n "${devel}" ]; then
400 # create devel package including common headers
401 print_rpmtemplate_kmoddevelpkg "${kernel}" "${kernel##${kernel_verrelarch}}"
402
403 # create devel package
404 print_rpmtemplate_per_kmoddevelpkg "${kernel}" "${kernel##${kernel_verrelarch}}"
405 fi
406 done
407 }
408
409 myprog_help ()
410 {
411 echo "Usage: ${0##*/} [OPTIONS]"
412 echo
413 echo "Creates a template to be used during kmod building"
414 echo
415 echo "Available options:"
416 echo " --filterfile <file> -- filter the results with grep --file <file>"
417 echo " --for-kernels <list> -- created templates only for these kernels"
418 echo " --kmodname <file> -- name of the kmod (required)"
419 echo " --devel -- make kmod-devel package"
420 echo " --noakmod -- no akmod package"
421 echo " --repo <name> -- use buildsys-build-<name>-kerneldevpkgs"
422 echo " --target <arch> -- target-arch (required)"
423 echo " --buildroot <dir> -- Build root (place to look for build files)"
424 }
425
426 while [ -n "${1}" ] ; do
427 case "${1}" in
428 --filterfile)
429 shift
430 if [ -z "${1}" ] ; then
431 error_out 2 "Please provide path to a filter-file together with --filterfile" >&2
432 elif [ ! -e "${1}" ]; then
433 error_out 2 "Filterfile ${1} not found" >&2
434 fi
435 filterfile="${1}"
436 shift
437 ;;
438 --kmodname)
439 shift
440 if [ -z "${1}" ] ; then
441 error_out 2 "Please provide the name of the kmod together with --kmodname" >&2
442 fi
443 # strip pending -kmod
444 kmodname="${1%%-kmod}"
445 shift
446 ;;
447 --devel)
448 shift
449 devel="true"
450 ;;
451 --prefix)
452 shift
453 if [ -z "${1}" ] ; then
454 error_out 2 "Please provide a prefix with --prefix" >&2
455 fi
456 prefix="${1}"
457 shift
458 ;;
459 --repo)
460 shift
461 if [ -z "${1}" ] ; then
462 error_out 2 "Please provide the name of the repo together with --repo" >&2
463 fi
464 repo=${1}
465 shift
466 ;;
467 --for-kernels)
468 shift
469 if [ -z "${1}" ] ; then
470 error_out 2 "Please provide the name of the kmod together with --kmodname" >&2
471 fi
472 for_kernels="${1}"
473 shift
474 ;;
475 --noakmod)
476 shift
477 noakmod="true"
478 ;;
479 --target)
480 shift
481 target="${1}"
482 shift
483 ;;
484 --akmod)
485 shift
486 build_kernels="akmod"
487 ;;
488 --newest)
489 shift
490 build_kernels="newest"
491 ;;
492 --current)
493 shift
494 build_kernels="current"
495 ;;
496 --buildroot)
497 shift
498 buildroot="${1}"
499 shift
500 ;;
501 --help)
502 myprog_help
503 exit 0
504 ;;
505 --version)
506 echo "${myprog} ${myver}"
507 exit 0
508 ;;
509 *)
510 echo "Error: Unknown option '${1}'." >&2
511 usage >&2
512 exit 2
513 ;;
514 esac
515 done
516
517 if [ -e ./kmodtool-kernel-variants ]; then
518 kernels_known_variants="$(cat ./kmodtool-kernel-variants)"
519 elif [ -e /usr/share/kmodtool/kernel-variants ] ; then
520 kernels_known_variants="$(cat /usr/share/kmodtool/kernel-variants)"
521 else
522 kernels_known_variants="@(smp?(-debug)|PAE?(-debug)|debug|kdump|xen|kirkwood|highbank|imx|omap|tegra)"
523 fi
524
525 # general sanity checks
526 if [ -z "${target}" ]; then
527 error_out 2 "please pass target arch with --target"
528 elif [ -z "${kmodname}" ]; then
529 error_out 2 "please pass kmodname with --kmodname"
530 elif [ -z "${kernels_known_variants}" ] ; then
531 error_out 2 "could not determine known variants"
532 fi
533
534 # go
535 if [ -n "${for_kernels}" ]; then
536 # this is easy:
537 print_customrpmtemplate "${for_kernels}"
538 elif [ "${build_kernels}" = "akmod" ]; then
539 # do only a akmod package
540 print_akmodtemplate
541 print_akmodmeta
542 else
543 # seems we are on out own to decide for which kernels to build
544
545 # we need more sanity checks in this case
546 if [ -z "${repo}" ]; then
547 error_out 2 "please provide repo name with --repo"
548 elif ! command -v "buildsys-build-${repo}-kerneldevpkgs" > /dev/null 2>&1; then
549 error_out 2 "buildsys-build-${repo}-kerneldevpkgs not found"
550 fi
551
552 # call buildsys-build-${repo}-kerneldevpkgs to get the list of kernels
553 cmdoptions="--target ${target}"
554
555 # filterfile to filter list of kernels?
556 if [ -n "${filterfile}" ] ; then
557 cmdoptions="${cmdoptions} --filterfile ${filterfile}"
558 fi
559
560 kernel_versions_to_build_for=$(buildsys-build-${repo}-kerneldevpkgs "--${build_kernels}" ${cmdoptions}) ||
561 error_out 2 "buildsys-build-${repo}-kerneldevpkgs failed: ${kernel_versions_to_build_for}"
562
563 if [ "${build_kernels}" = "current" ] && [ -z "${noakmod}" ]; then
564 print_akmodtemplate
565 fi
566
567 print_rpmtemplate
568 fi