]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - scripts/kmodtool
zfs get: add '-t fs' and '-t vol' options
[FreeBSD/FreeBSD.git] / scripts / kmodtool
1 #!/usr/bin/env bash
2 # shellcheck disable=SC2086,SC2295
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 "${prefix}/lib/modules/${kernel}/build/Makefile" ]]; then
337                         # likely a user-build-kernel with available buildfiles
338                         # fixme: we should check if uname from Makefile is the same as ${kernel}
339
340                         kernel_versions="${kernel_versions}${kernel}___${prefix}/lib/modules/${kernel}/build/ "
341                         print_rpmtemplate_per_kmodpkg --custom "${kernel}"
342
343                         # create development package
344                         if [[ -n "${devel}" ]]; then
345                                 # create devel package including common headers
346                                 print_rpmtemplate_kmoddevelpkg --custom "${kernel}"
347
348                                 # create devel package
349                                 print_rpmtemplate_per_kmoddevelpkg --custom "${kernel}"
350                         fi
351                 elif [[ -e "${buildroot}/usr/src/kernels/${kernel}" ]]; then
352                         # this looks like a Fedora/RH kernel -- print a normal template (which includes the proper BR) and be happy :)
353                         kernel_versions="${kernel_versions}${kernel}___${buildroot}%{_usrsrc}/kernels/${kernel} "
354
355                         # parse kernel versions string and print template
356                         local kernel_verrelarch=${kernel%%${kernels_known_variants}}
357                         print_rpmtemplate_per_kmodpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
358
359                         # create development package
360                         if [[ -n "${devel}" ]]; then
361                                 # create devel package including common headers
362                                 print_rpmtemplate_kmoddevelpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
363
364                                 # create devel package
365                                 print_rpmtemplate_per_kmoddevelpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
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