mirror of the now-defunct rocklinux.org
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.

432 lines
14 KiB

  1. #!/bin/bash
  2. #
  3. # --- ROCK-COPYRIGHT-NOTE-BEGIN ---
  4. #
  5. # This copyright note is auto-generated by ./scripts/Create-CopyPatch.
  6. # Please add additional copyright information _after_ the line containing
  7. # the ROCK-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
  8. # the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
  9. #
  10. # ROCK Linux: rock-src/scripts/Build-Target
  11. # ROCK Linux is Copyright (C) 1998 - 2004 Clifford Wolf
  12. #
  13. # This program is free software; you can redistribute it and/or modify
  14. # it under the terms of the GNU General Public License as published by
  15. # the Free Software Foundation; either version 2 of the License, or
  16. # (at your option) any later version. A copy of the GNU General Public
  17. # License can be found at Documentation/COPYING.
  18. #
  19. # Many people helped and are helping developing ROCK Linux. Please
  20. # have a look at http://www.rocklinux.org/ and the Documentation/TEAM
  21. # file for details.
  22. #
  23. # --- ROCK-COPYRIGHT-NOTE-END ---
  24. #
  25. # Run this command from the ROCK directory as ./scripts/Build-Target
  26. # after running the ./scripts/Config and ./scripts/Download commands.
  27. #
  28. # It compiles/builds all the packages and stores them as tar balls suitable
  29. # for distribution.
  30. #
  31. # This script is the ROCK work-horse. It builds in a chroot environment
  32. # (stage 2..9) and goes through a number of build stages:
  33. #
  34. config=default
  35. build_only_this_job=
  36. stages=0123456789
  37. daemon_mode=0
  38. options="$*"
  39. while [ "$1" ] ; do
  40. case "$1" in
  41. -cfg) config=$2 ; shift ; shift ;;
  42. -stages) stages=$2 ; shift ; shift ;;
  43. -job) build_only_this_job=$2 ; shift ; shift ;;
  44. -daemon) daemon_mode=1 ; shift ;;
  45. -nodaemon) daemon_mode=0 ; shift ;;
  46. *) echo "Usage: $0 [ -daemon ] [ -cfg <config> ]" \
  47. "[ -stages <list> ] [ -job <stage>-<package> ]"
  48. echo
  49. echo " Compile/build all packages for a given configuration and store them as tar"
  50. echo " balls suitable for distribution."
  51. echo " This script is the ROCK work-horse. It builds in a chroot environment"
  52. echo " (stage 2..9) and goes through a number of build stages."
  53. echo " Run this command from the ROCK directory as ./scripts/Build-Target after"
  54. echo " running the ./scripts/Config and ./scripts/Download commands."
  55. echo
  56. echo " -cfg <config> the build configuration to use; defaults to 'default'"
  57. echo " -daemon run as daemon in the background"
  58. echo " -stages <list> only build the stages listed in the parameter"
  59. echo " -job <stage>-<package> build only one job: the given package"
  60. echo " in the given stage"
  61. exit 1 ;;
  62. esac
  63. done
  64. if [ "$daemon_mode" = 1 ] ; then
  65. . config/$config/config
  66. echo "Running $0 in the background (messages go to logfile only).."
  67. echo "Logfile: build/$ROCKCFG_ID/ROCK/logs/build_target.log"
  68. nohup $0 $options -nodaemon > /dev/null 2> /dev/null < /dev/null &
  69. exit 0
  70. fi
  71. . scripts/parse-config
  72. . scripts/functions
  73. # so we can disable stuff not available in Build-Target
  74. export ROCK_BUILD_TARGET=1
  75. build_root="$base/build/$ROCKCFG_ID"
  76. build_rock="$base/build/$ROCKCFG_ID/ROCK"
  77. build_logs="$build_rock/logs" ; mkdir -p "${build_logs}"
  78. build_pkgs="$build_rock/pkgs" ; mkdir -p "${build_root}"
  79. if [ "$ROCKCFG_PARANOIA_CHECK" = 1 ] ; then
  80. ./scripts/Check-System -paranoia || exit 1
  81. else
  82. ./scripts/Check-System || exit 1
  83. fi
  84. # Package Build loop - executed by build-target
  85. #
  86. pkgloop() {
  87. if [ "$ROCKCFG_NOBROKENDEPS" = 1 ]; then
  88. nobrokendeps="-nobrokendeps"
  89. else
  90. nobrokendeps=""
  91. fi
  92. if [ "$ROCKCFG_RETRY_BROKEN" -eq 1 -a \
  93. -z "$build_only_this_job" -a \
  94. "`ls ${build_root}/var/adm/logs/*.err 2> /dev/null`" ] ; then
  95. echo_header "Removing old error logs ..."
  96. for x in ${build_root}/var/adm/logs/*.err ; do
  97. echo_status "Removing ${x#$build_root/} ..."
  98. rm -f $x
  99. done
  100. fi
  101. if [ -z "$build_only_this_job" -a \
  102. "`ls ${build_root}/var/adm/logs/*.out 2> /dev/null`" ] ; then
  103. echo_header "Removing old output logs ..."
  104. for x in ${build_root}/var/adm/logs/*.out ; do
  105. echo_status "Removing ${x#$build_root/} ..."
  106. rm -f $x
  107. done
  108. fi
  109. if [ "$ROCKCFG_PARALLEL" = 1 -a -z "$build_only_this_job" ]
  110. then
  111. qdir="$base/build/$ROCKCFG_ID/ROCK/queue"
  112. mkdir -p $qdir
  113. if [ -z "$ROCKCFG_PARALLEL_ADDJOB" ] ; then
  114. echo "
  115. Job Queue for parallel (cluster) build created.
  116. You have not configuread a command for adding jobs. So you need to use the
  117. ROCK Linux built-in job queue. To do so, you need to login to your build
  118. nodes and execute the command:
  119. ./scripts/Build-Job -cfg $config -daemon
  120. "
  121. touch $qdir/use_build_job_daemon
  122. else
  123. echo "
  124. Job Queue for parallel (cluster) build created.
  125. You have configuread a command for adding jobs. So if everything is configured
  126. in the right way, the nodes will automatically start building the jobs.
  127. "
  128. rm -f $qdir/use_build_job_daemon
  129. fi
  130. newqueue=1 ; printstatus=1 ; printstatus_counter=30
  131. finished=0 ; trap 'rm -f $qdir/queue.txt ; exit 130' SIGINT
  132. while
  133. if [ -f $qdir/print_status ] ; then
  134. rm -f $qdir/print_status
  135. printstatus=1 ; printstatus_counter=0
  136. fi
  137. if [ "$printstatus" = 1 ] ; then
  138. if [ $printstatus_counter -le 0 ] ; then
  139. ./scripts/Create-ParaStatus -cfg "$config"
  140. printstatus=0 ; printstatus_counter=300
  141. else
  142. printstatus_counter=$(($printstatus_counter - 1))
  143. fi
  144. fi
  145. for x in $qdir/*.msg ; do
  146. if [ -f "$x" ] ; then
  147. expand -t20 < $x ; rm -f $x
  148. printstatus=1 ; newqueue=1
  149. fi
  150. done
  151. if [ "$newqueue" = 1 ] ; then
  152. ./scripts/Create-PkgQueue \
  153. -cfg $config -stages $stages \
  154. $nobrokendeps | sort -r -n -k2 | \
  155. if [ $ROCKCFG_PARALLEL_MAX -gt 0 ]
  156. then head -n $ROCKCFG_PARALLEL_MAX
  157. else cat ; fi > $qdir/queue.new
  158. mv $qdir/queue.new $qdir/queue.txt
  159. newqueue=0
  160. while read next ; do
  161. set $next ; qid="$1-$6"
  162. if [ ! -f $qdir/$qid.job ] ; then
  163. date "+%H:%M %Y-%m-%d: creating new job '$qid'" | expand -t20
  164. echo "Job $qid waiting in the job queue (priority $2)" > $qdir/$qid.todo
  165. printstatus=1
  166. # we need to remove some variables that should be uniqe per node
  167. dump_env | grep -v HOSTNAME= > $qdir/$qid.new
  168. mv $qdir/$qid.new $qdir/$qid.job
  169. if [ "$ROCKCFG_PARALLEL_ADDJOB" ] ; then
  170. x="${ROCKCFG_PARALLEL_ADDJOB//\{\}/.\/scripts\/Build-Job -cfg $config $qid}" ; sh -c "$x"
  171. fi
  172. fi
  173. done < $qdir/queue.txt
  174. fi
  175. if [ -s $qdir/queue.txt ] || \
  176. [ "`ls $qdir/*.job 2>/dev/null`" ]
  177. then
  178. finished=0
  179. else
  180. finished=$(( $finished + 1 ))
  181. newqueue=1
  182. fi
  183. [ $finished -le 3 ]
  184. do
  185. sleep 1
  186. done
  187. echo "All packages build."
  188. sleep 2 ; rm -rf $qdir ; trap - SIGINT
  189. else
  190. if [ "$build_only_this_job" ] ; then
  191. rm -f "${build_root}"/var/adm/logs/${build_only_this_job}.log"
  192. rm -f "${build_root}"/var/adm/logs/${build_only_this_job}.err"
  193. next="$( awk 'BEGIN { FS=" "; }
  194. $0 ~ /[ =]'${build_only_this_job#*-}' / && \
  195. $2 ~ /'${build_only_this_job%%-*}'/ \
  196. { $1="'${build_only_this_job%%-*}' 0";
  197. print; exit; }' < config/$config/packages )"
  198. [ "$next" ] && pkgloop_package $next
  199. exit 0
  200. else
  201. while
  202. next="`./scripts/Create-PkgQueue \
  203. -cfg "$config" -stages $stages -single $nobrokendeps`"
  204. [ "$next" ]
  205. do
  206. pkgloop_package $next
  207. done
  208. fi
  209. fi
  210. local pkglst=`mktemp` errors=0; rm -f src/invalid-files.lst
  211. echo_header "Searching for old liggering files ..."
  212. grep "^X" config/$config/packages | cut -d' ' -f5 | sed 's,.*=,,' |
  213. if [ $ROCKCFG_PKGFILE_VER = 1 ] ; then
  214. while read p; do
  215. v=$( grep -h '^Package Name and Version:' build/$ROCKCFG_ID/var/adm/packages/$p:* \
  216. build/$ROCKCFG_ID/var/adm/packages/$p 2> /dev/null | cut -f6 -d' ' | head -n1 )
  217. echo "$p-$v"
  218. done
  219. else
  220. cat
  221. fi > $pkglst
  222. for file in $( ls build/$ROCKCFG_ID/ROCK/pkgs/ ) ; do
  223. x="$file"; [ "$x" = packages.db ] && continue
  224. [ $ROCKCFG_CREATE_GEM = 0 ] || x=${x%.gem}
  225. [ $ROCKCFG_CREATE_TARBZ2 = 0 ] || x=${x%.tar.bz2}
  226. y=$( echo $x | sed 's,:[^-]*,,' )
  227. if ! grep -qx "$y" $pkglst; then
  228. file="build/$ROCKCFG_ID/ROCK/pkgs/$file"
  229. echo_error "$file [$x $y] should not be present" \
  230. "(now in src/invalid-files.lst)!"
  231. mkdir -p src; echo "$file" >> src/invalid-files.lst
  232. errors=1
  233. fi
  234. done
  235. for dir in build/$ROCKCFG_ID/var/adm/{cache,cksums,dependencies,descs,flists,md5sums,packages} ; do
  236. for file in $( ls $dir | cut -f1 -d: ) ; do
  237. if [ $ROCKCFG_PKGFILE_VER = 1 ] ; then x="$file-.*"; else x="$file"; fi
  238. if ! grep -xq "$x" $pkglst ; then
  239. echo_error "$dir/$file should not be present (now in src/invalid-files.lst)!"
  240. mkdir -p src; echo "$dir/$file" >> src/invalid-files.lst
  241. errors=1
  242. fi
  243. done
  244. done
  245. for file in $( ls build/$ROCKCFG_ID/var/adm/logs/ ) ; do
  246. x="`echo $file | sed -e 's/^.-//' -e 's/\.log//' -e 's/\.err//' -e s'/\.out//'`"
  247. if [ $ROCKCFG_PKGFILE_VER = 1 ] ; then x="$x-.*"; else x="$x"; fi
  248. if ! grep -xq "$x" $pkglst ; then
  249. file="build/$ROCKCFG_ID/var/adm/logs/$file"
  250. echo_error "$file should not be present (now in src/invalid-files.lst)!"
  251. mkdir -p src; echo "$file" >> src/invalid-files.lst
  252. errors=1
  253. fi
  254. done
  255. [ $errors = 0 ] && echo_status "No errors found."
  256. rm $pkglst
  257. }
  258. # Process one line of output generated by Create-PkgQueue
  259. #
  260. pkgloop_package() {
  261. for x in stagelevel pkg_depnr pkg_stages pkg_pri pkg_tree \
  262. pkg_name pkg_ver pkg_prefix pkg_extra
  263. do eval "$x=\$1" ; shift ; done
  264. # Maybe this is a forked package
  265. pkg_basename="${pkg_name%=*}"
  266. pkg_name="${pkg_name#*=}"
  267. [ "$build_only_this_job" -a \
  268. "$stagelevel-$pkg_name" != "$build_only_this_job" ] && return
  269. [ $(expr "$pkg_stages" : ".*$stagelevel.*") -eq 0 ] && return
  270. pkg_laststage=$(echo "$pkg_stages" | sed "s,-,,g; s,.*\(.\),\1,")
  271. cmd_root="-root auto"
  272. [ $stagelevel -gt 1 ] && cmd_root="$cmd_root -chroot"
  273. if [ "$pkg_prefix" != "/" ] ; then
  274. cmd_prefix="-prefix $pkg_prefix"
  275. else cmd_prefix="" ; fi
  276. cmd_buildpkg="./scripts/Build-Pkg -$stagelevel -cfg $config"
  277. cmd_buildpkg="$cmd_buildpkg $cmd_root $cmd_prefix $pkg_basename=$pkg_name"
  278. # Execute action handler
  279. pkgloop_action || [ "$ROCKCFG_ABORT_ON_ERROR" != 1 ] || exit 1
  280. if [ -f ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err -a \
  281. "$ROCKCFG_SENDMAIL" = 1 ]
  282. then
  283. {
  284. cat << EOT
  285. Subject: [ROCK Build-Target] $stagelevel-$pkg_name in $config failed
  286. Building package $pkg_name failed in stage $stagelevel:
  287. ----
  288. EOT
  289. echo; tail -n 200 ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err; echo
  290. } | $ROCKCFG_SENDMAIL_BIN $ROCKCFG_SENDMAIL_TO
  291. fi
  292. if [ ! -f ${build_root}/var/adm/logs/$stagelevel-$pkg_name.log -a \
  293. ! -f ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err ]
  294. then
  295. echo_header "Package build ended abnormally!"
  296. echo_error "Usually a package build creates eighter a *.log"
  297. echo_error "or a *.err file. Neither the 1st nor the 2nd is"
  298. echo_error "there. So I'm going to create a *.err file now"
  299. echo_error "and abort the build process."
  300. touch ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err
  301. exit 1
  302. fi
  303. if [ $pkg_laststage -eq $stagelevel ] && \
  304. [ "$ROCKCFG_CREATE_TARBZ2" = 1 -o "$ROCKCFG_CREATE_GEM" = 1 ]
  305. then
  306. if [ -f ${build_root}/var/adm/logs/$stagelevel-$pkg_name.err ]
  307. then echo_error "Creation of binary package isn't possible,"
  308. echo_error "because the package was not successfully"
  309. echo_error "built in (at least) the current stage."
  310. else
  311. for spkg in $( cd ${build_root}/var/adm/packages/; ls ${pkg_name} ${pkg_name}:* 2>/dev/null )
  312. do
  313. echo_header "Creating binary package file for ${spkg}."
  314. mkdir -p "${build_pkgs}"
  315. if [ "$ROCKCFG_PKGFILE_VER" = 1 ]
  316. then
  317. v="-$( grep '^Package Name and Version:' \
  318. ${build_root}/var/adm/packages/$spkg | cut -f6 -d' ' )"
  319. else
  320. v=""
  321. fi
  322. echo_status "Building build/.../pkgs/`
  323. `${spkg}${v}.tar.bz2"
  324. ( cd "$build_root/"
  325. cut -f2- -d' ' var/adm/flists/$spkg | \
  326. tar -cf- --no-recursion --files-from=- | bzip2
  327. ) > "${build_pkgs}/${spkg}${v}.tar.bz2.tmp"
  328. if [ "$ROCKCFG_CREATE_GEM" = 1 ] ; then
  329. echo_status "Building build/.../pkgs/`
  330. `${spkg}${v}.gem"
  331. mine -C "$build_root/var/adm" \
  332. "${build_pkgs}/${spkg}${v}.tar.bz2.tmp" \
  333. $spkg "$build_pkgs/${spkg}${v}.gem.tmp"
  334. fi
  335. if [ "$ROCKCFG_CREATE_TARBZ2" = 1 ] ; then
  336. mv "$build_pkgs/${spkg}${v}.tar.bz2.tmp" \
  337. "$build_pkgs/${spkg}${v}.tar.bz2"
  338. if [ "$ROCKCFG_CREATE_GEM" = 1 ] ; then
  339. mv "$build_pkgs/${spkg}${v}.gem.tmp" \
  340. "$build_pkgs/${spkg}${v}.gem"
  341. fi
  342. else
  343. echo_status "Removing temporary tar.bz2."
  344. rm -f "$build_pkgs/${spkg}${v}.tar.bz2.tmp"
  345. mv "$build_pkgs/${spkg}${v}.gem.tmp" \
  346. "$build_pkgs/${spkg}${v}.gem"
  347. fi
  348. done
  349. fi
  350. fi
  351. }
  352. # Action executed by pkgloop(). This function may be redefined
  353. # before calling pkgloop().
  354. #
  355. pkgloop_action() {
  356. $cmd_buildpkg
  357. }
  358. # Try to umount any directories mounted by Build-Pkg -chroot
  359. # if we are the last process using them.
  360. #
  361. umount_chroot() {
  362. exec 201> /dev/null
  363. if [ -z "$( fuser ${build_logs}/*.log )" ]; then
  364. umount -d -f $build_rock/{loop,config,download} 2> /dev/null
  365. umount -d -f -l $build_rock/{loop,config,download} 2> /dev/null
  366. umount -d -f $build_root/proc 2> /dev/null
  367. umount -d -f -l $build_root/proc 2> /dev/null
  368. fi
  369. }
  370. # must trap outside the group command
  371. trap 'umount_chroot' EXIT
  372. {
  373. ln -sf build_target_$$.log ${build_logs}/build_target.log
  374. ./scripts/Build-Tools -1 -cfg $config
  375. . ./target/$ROCKCFG_TARGET/build.sh
  376. echo_header "Finished building this target."
  377. } 2>&1 201>> "${build_logs}/build_target_$$.log" | \
  378. tee -a "${build_logs}/build_target_$$.log"
  379. if [ "$ROCKCFG_SENDMAIL" = 1 ]; then
  380. $ROCKCFG_SENDMAIL_BIN $ROCKCFG_SENDMAIL_TO << EOT
  381. Subject: [ROCK Build-Target] $config finished.
  382. Finished building $config.
  383. EOT
  384. fi