You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
358 lines
8.6 KiB
358 lines
8.6 KiB
#!/bin/bash |
|
# |
|
# akmodbuild - Helper script for building kernel module SRPMs |
|
# Copyright (c) 2007 Thorsten Leemhuis <fedora@leemhuis.info> |
|
# |
|
# Permission is hereby granted, free of charge, to any person obtaining |
|
# a copy of this software and associated documentation files (the |
|
# "Software"), to deal in the Software without restriction, including |
|
# without limitation the rights to use, copy, modify, merge, publish, |
|
# distribute, sublicense, and/or sell copies of the Software, and to |
|
# permit persons to whom the Software is furnished to do so, subject to |
|
# the following conditions: |
|
# |
|
# The above copyright notice and this permission notice shall be |
|
# included in all copies or substantial portions of the Software. |
|
# |
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
# |
|
myprog="akmodsbuild" |
|
myver="0.5.6" |
|
|
|
# defaults that might get overwritten by user: |
|
kernels="$(uname -r)" |
|
target="$(uname -m)" |
|
if [[ "${target}" == "armv7l" ]] ; then |
|
target="armv7hl" |
|
fi |
|
numberofjobs=$(grep -c processor /proc/cpuinfo 2> /dev/null) |
|
verboselevel=2 |
|
outputdir="${PWD}" |
|
srpms= |
|
|
|
init () |
|
{ |
|
## startup checks |
|
# prevent root-usage |
|
if [[ -w /var ]] ; then |
|
echo "ERROR: Not to be used as root; start as user or '${myprog}' instead." >&2 |
|
exit 1 |
|
fi |
|
|
|
# do we have everything we need to build for the kernels in question? |
|
for kernel in ${kernels}; do |
|
if [[ ! -e /usr/src/kernels/${kernel}/Makefile ]] && [[ ! -e /usr/lib/modules/${kernel}/build/Makefile ]] ; then |
|
echo "ERROR: Files needed for building modules against kernel" >&2 |
|
echo " ${kernel} could not be found as the following" >&2 |
|
echo " directories are missing:" |
|
echo " /usr/src/kernels/${kernel}/" >&2 |
|
echo " /usr/lib/modules/${kernel}/build/" >&2 |
|
exit 2 |
|
fi |
|
done |
|
|
|
if [[ ! -n "${srpms}" ]] ; then |
|
echo "ERROR: Please provide a list of SRPM-files to build." |
|
exit 2 |
|
fi |
|
|
|
# SRPMS available? |
|
for srpm in ${srpms}; do |
|
if [[ ! -r ${srpm} ]] ; then |
|
echo "ERROR: Can't find SRPM ${srpm}" |
|
exit 1 |
|
fi |
|
done |
|
|
|
# room to save things |
|
if [[ ! -d "${outputdir}" ]] ; then |
|
echo "ERROR: ${outputdir} is not a directory" >&2 |
|
exit 1 |
|
elif [[ ! -w "${outputdir}" ]] ; then |
|
echo "ERROR: ${outputdir} is not a writable" >&2 |
|
exit 1 |
|
fi |
|
|
|
|
|
# make sure this is a number |
|
if ! (( ${numberofjobs} > 0 )) ; then |
|
echo "Warning: using hardcoded defaut value for number of jobs" |
|
numberofjobs=2 |
|
fi |
|
|
|
## preparations |
|
# tmpdir |
|
if ! tmpdir="$(mktemp -d -p /tmp ${myprog}.XXXXXXXX)" ; then |
|
echo "ERROR: Could create tempdir." |
|
exit 1 |
|
fi |
|
|
|
# buildtreee |
|
mkdir "${tmpdir}"/{BUILD,SOURCES,SPECS,SRPMS,RPMS,RPMS/"${target}"} |
|
|
|
# logfile |
|
if [[ ! -n "${logfile}" ]] ; then |
|
logfile="${tmpdir}/logfile" |
|
fi |
|
|
|
if ( [[ -e "${logfile}" ]] && [[ ! -w "${logfile}" ]] ) || ! touch "${logfile}" ; then |
|
echo "ERROR: Could not write logfile." |
|
finally |
|
exit 1 |
|
fi |
|
} |
|
|
|
|
|
finally() |
|
{ |
|
# kill background jobs if needed |
|
if [[ -n "${watch_jobid}" ]] ; then |
|
kill "${watch_jobid}" |
|
fi |
|
if [[ -n "${rpmbuild_jobid}" ]] ; then |
|
kill "${rpmbuild_jobid}" |
|
fi |
|
|
|
# remove tmpfiles |
|
if [[ -d "${tmpdir}" ]] ; then |
|
rm -rf "${tmpdir}" |
|
fi |
|
} |
|
trap "finally" 2 |
|
|
|
|
|
akmods_echo() |
|
{ |
|
# where to output |
|
local this_fd=${1} |
|
shift |
|
|
|
# verboselevel |
|
local this_verbose=${1} |
|
shift |
|
|
|
if [[ "${1}" == "--not-logfile" ]] ; then |
|
local notlogfile=true |
|
shift |
|
fi |
|
|
|
# output to console |
|
if (( ${verboselevel} >= ${this_verbose} )) ; then |
|
echo "$@" >&${this_fd} |
|
fi |
|
|
|
# global logfile |
|
if [[ ! -n ${notlogfile} ]] ; then |
|
echo "$@" >> "${logfile}" |
|
fi |
|
} |
|
|
|
|
|
watch_rpmbuild() |
|
{ |
|
# background function to show rpmbuild progress |
|
# does't use akmods_echo here; this stage handles the output on its own |
|
# (seperate process and there is no need to log this) |
|
if (( ${verboselevel} == 2 )) ; then |
|
tail --pid ${1} -n +1 -s 0.1 -f ${2} 2>/dev/null | grep --line-buffered -e '%prep' -e '%build' -e '%install' -e '%clean' | while read line ; do |
|
if [[ "${line}" != "${line##*prep}" ]] ; then |
|
echo -n "prep " |
|
elif [[ "${line}" != "${line##*build}" ]] ; then |
|
echo -n "build " |
|
elif [[ "${line}" != "${line##*install}" ]] ; then |
|
echo -n "install " |
|
elif [[ "${line}" != "${line##*clean}" ]] ; then |
|
echo -n "clean; " |
|
# last linefeed is done by the caller |
|
fi |
|
done |
|
elif (( ${verboselevel} > 2 )) ; then |
|
tail --pid ${1} -n +1 -s 0.1 -f ${2} |
|
fi |
|
} |
|
|
|
process_srpm() |
|
{ |
|
local source_rpm="${1}" |
|
|
|
# status info |
|
akmods_echo 1 2 -n "* Rebuilding ${source_rpm} for kernel(s) ${kernels}: " |
|
|
|
# kick off rebuild into background |
|
/usr/bin/time --format='%x' --output="${tmpdir}/.jobexit" rpmbuild \ |
|
--define "_topdir ${tmpdir}/" \ |
|
--define "_buildtree ${tmpdir}/BUILD" \ |
|
--define "_specdir ${tmpdir}/SPECS" \ |
|
--define "_sourcedir ${tmpdir}/SOURCES" \ |
|
--define "_srcrpmdir ${tmpdir}/SRPMS" \ |
|
--define "_rpmdir ${tmpdir}/RPMS" \ |
|
--define "_smp_mflags -j${numberofjobs}" \ |
|
--define "kernels ${kernels}" \ |
|
--target ${target} \ |
|
--rebuild "${source_rpm}" 2>&1 | tee -a "${logfile}" > "${tmpdir}/.joblog" & |
|
|
|
local rpmbuild_jobid=$! |
|
|
|
# show progress |
|
if (( ${verboselevel} >= 2 )) ; then |
|
watch_rpmbuild ${rpmbuild_jobid} "${tmpdir}/.joblog" 2> /dev/null & |
|
local watch_jobid=$! |
|
fi |
|
|
|
# wait for rpmbuild |
|
wait ${rpmbuild_jobid} |
|
local rpmbuild_returncode=$(tail -n 1 "${tmpdir}/.jobexit") |
|
unset rpmbuild_jobid |
|
|
|
# give watch_rpmbuild a moment to catch up; kill it if it does not |
|
if (( ${verboselevel} >= 2 )) ; then |
|
sleep 0.5 |
|
kill ${watch_jobid} &> /dev/null |
|
unset watch_jobid |
|
fi |
|
|
|
# did rpmbuild succeed? |
|
if (( ${rpmbuild_returncode} != 0 )) ; then |
|
# linefeed: |
|
akmods_echo 1 2 "" |
|
|
|
akmods_echo 2 2 --not-logfile "rpmbuild failed with errorcode ${rpmbuild_returncode}; last 35 Lines of log:" |
|
akmods_echo 2 2 --not-logfile "--- " |
|
tail -n 35 "${tmpdir}/.joblog" >&2 |
|
akmods_echo 2 2 --not-logfile "---" |
|
return ${rpmbuild_returncode} |
|
fi |
|
|
|
# finish status for watch_rpmbuild |
|
if (( ${verboselevel} >= 2 )) ; then |
|
akmods_echo 1 2 -n "Successfull; " |
|
fi |
|
|
|
local rpms_built="$(cd "${tmpdir}"/RPMS/"${target}" ; echo *)" |
|
|
|
if ! mv "${tmpdir}/RPMS/${target}/"* "${outputdir}" ; then |
|
# linefeed: |
|
akmods_echo 1 2 "" |
|
|
|
akmods_echo 2 2 "Failed to move ${tmpdir}/RPMS/${target}/"* "to ${outputdir}" |
|
return 128 |
|
fi |
|
|
|
if (( ${verboselevel} == 1 )) ; then |
|
for rpm in ${rpms_built}; do |
|
echo "${outputdir%%/}/${rpm}" |
|
done |
|
elif (( ${verboselevel} >= 2 )) ; then |
|
akmods_echo 1 2 "Saved ${rpms_built} in ${outputdir%%/}/" |
|
fi |
|
|
|
|
|
# finished |
|
return 0 |
|
} |
|
|
|
myprog_help () |
|
{ |
|
echo "Rebuilds kmod SRPM(s)" |
|
echo $'\n'"Usage: ${myprog} [OPTIONS] <SRPMS>" |
|
echo $'\n'"Options:" |
|
echo " -k, --kernels -- build for kernel-versions (output from 'uname -r')" |
|
echo " -l, --logfile <file> -- save rpmbuild output to <file>" |
|
echo " -o, --outputdir <dir> -- save rpms and logs here (current directory)" |
|
echo " -t, --target -- target-arch (output from 'uname -m')" |
|
echo " -v, --verbose -- increase verboseness" |
|
echo " -q, --quiet -- be more quiet" |
|
echo " -h, --help -- show usage" |
|
echo " -V, --version -- show version" |
|
} |
|
|
|
while [ "${1}" ] ; do |
|
case "${1}" in |
|
-k|--kernels) |
|
shift |
|
if [[ ! -n "${1}" ]] ; then |
|
echo "ERROR: Please provide kernel-version(s) to build for together with --kernel" >&2 |
|
exit 1 |
|
fi |
|
kernels="${1}" |
|
shift |
|
;; |
|
-l|--logfile) |
|
shift |
|
if [[ ! -n "${1}" ]] ; then |
|
echo "ERROR: Please provide a filename together with --logfile" >&2 |
|
exit 1 |
|
fi |
|
logfile="${1}" |
|
shift |
|
;; |
|
-o|--outputdir) |
|
shift |
|
if [[ ! -n "${1}" ]] ; then |
|
echo "ERROR: Please provide the output directory together with --outputdir" >&2 |
|
exit 1 |
|
fi |
|
outputdir="${1}" |
|
shift |
|
;; |
|
-t|--target) |
|
shift |
|
if [[ ! -n "${1}" ]] ; then |
|
echo "ERROR: Please provide the target-arch together with --target" >&2 |
|
exit 1 |
|
fi |
|
target="${1}" |
|
shift |
|
;; |
|
-v|--verbose) |
|
let verboselevel++ |
|
shift |
|
;; |
|
-q|--quiet) |
|
let verboselevel-- |
|
shift |
|
;; |
|
-h|--help) |
|
myprog_help |
|
exit 0 |
|
;; |
|
-V|--version) |
|
echo "${myprog} ${myver}" |
|
exit 0 |
|
;; |
|
--*) |
|
echo "Error: Unknown option '${1}'." >&2 |
|
myprog_help >&2 |
|
exit 2 |
|
;; |
|
*) |
|
srpms="${srpms} ${1}" |
|
shift |
|
;; |
|
esac |
|
done |
|
|
|
# sanity checks |
|
init |
|
|
|
# go |
|
for srpm in ${srpms}; do |
|
process_srpm ${srpm} |
|
returncode=$? |
|
|
|
if (( ${returncode} != 0 )) ; then |
|
finally |
|
exit ${returncode} |
|
fi |
|
done |
|
|
|
# finished |
|
finally |
|
|
|
exit 0
|
|
|