util.sh 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. #!/bin/bash
  2. ##### -*- mode:shell-script; indent-tabs-mode:nil; sh-basic-offset:2 -*-
  3. ##### Author: Travis Cross <tc@traviscross.com>
  4. set -e
  5. ddir="."
  6. [ -n "${0%/*}" ] && ddir="${0%/*}"
  7. cd $ddir/../
  8. #### lib
  9. err () {
  10. echo "$0 error: $1" >&2
  11. exit 1
  12. }
  13. announce () {
  14. cat >&2 <<EOF
  15. ########################################################################
  16. ## $1
  17. ########################################################################
  18. EOF
  19. }
  20. xread () {
  21. local xIFS="$IFS"
  22. IFS=''
  23. read $@
  24. local ret=$?
  25. IFS="$xIFS"
  26. return $ret
  27. }
  28. mk_dver () { echo "$1" | sed -e 's/-/~/g'; }
  29. mk_uver () { echo "$1" | sed -e 's/-.*$//' -e 's/~/-/'; }
  30. dsc_source () { dpkg-parsechangelog | grep '^Source:' | awk '{print $2}'; }
  31. dsc_ver () { dpkg-parsechangelog | grep '^Version:' | awk '{print $2}'; }
  32. up_ver () { mk_uver "$(dsc_ver)"; }
  33. dsc_base () { echo "$(dsc_source)_$(dsc_ver)"; }
  34. up_base () { echo "$(dsc_source)-$(up_ver)"; }
  35. find_distro () {
  36. case "$1" in
  37. experimental) echo "sid";;
  38. unstable) echo "sid";;
  39. testing) echo "jessie";;
  40. stable) echo "wheezy";;
  41. oldstable) echo "squeeze";;
  42. *) echo "$1";;
  43. esac
  44. }
  45. find_suite () {
  46. case "$1" in
  47. sid) echo "unstable";;
  48. jessie) echo "testing";;
  49. wheezy) echo "stable";;
  50. squeeze) echo "oldstable";;
  51. *) echo "$1";;
  52. esac
  53. }
  54. #### debian/rules helpers
  55. create_dbg_pkgs () {
  56. for x in $ddir/*; do
  57. test ! -d $x && continue
  58. test "$x" = "tmp" -o "$x" = "source" && continue
  59. test ! "$x" = "${x%-dbg}" && continue
  60. test ! -d $x/usr/lib/debug && continue
  61. mkdir -p $x-dbg/usr/lib
  62. mv $x/usr/lib/debug $x-dbg/usr/lib/
  63. done
  64. }
  65. cwget () {
  66. local url="$1" f="${1##*/}"
  67. echo "fetching: $url to $f" >&2
  68. if [ -n "$FS_FILES_DIR" ]; then
  69. if ! [ -s "$FS_FILES_DIR/$f" ]; then
  70. (cd $FS_FILES_DIR && wget -N "$url")
  71. fi
  72. cp -a $FS_FILES_DIR/$f .
  73. else
  74. wget -N "$url"
  75. fi
  76. }
  77. getlib () {
  78. local url="$1" f="${1##*/}"
  79. cwget "$url"
  80. tar -xv --no-same-owner --no-same-permissions -f "$f"
  81. rm -f "$f" && mkdir -p $f && touch $f/.download-stamp
  82. }
  83. getlibs () {
  84. # get pinned libraries
  85. getlib http://downloads.mongodb.org/cxx-driver/mongodb-linux-x86_64-v1.8-latest.tgz
  86. getlib http://files.freeswitch.org/downloads/libs/soundtouch-1.7.1.tar.gz
  87. getlib http://files.freeswitch.org/downloads/libs/flite-2.0.0-release.tar.bz2
  88. getlib http://files.freeswitch.org/downloads/libs/sphinxbase-0.8.tar.gz
  89. getlib http://files.freeswitch.org/downloads/libs/pocketsphinx-0.8.tar.gz
  90. getlib http://files.freeswitch.org/downloads/libs/communicator_semi_6000_20080321.tar.gz
  91. getlib http://files.freeswitch.org/downloads/libs/celt-0.10.0.tar.gz
  92. getlib http://files.freeswitch.org/downloads/libs/opus-1.1-p2.tar.gz
  93. getlib http://files.freeswitch.org/downloads/libs/openldap-2.4.19.tar.gz
  94. getlib http://download.zeromq.org/zeromq-2.1.9.tar.gz \
  95. || getlib http://download.zeromq.org/historic/zeromq-2.1.9.tar.gz
  96. getlib http://files.freeswitch.org/downloads/libs/freeradius-client-1.1.6.tar.gz
  97. getlib http://files.freeswitch.org/downloads/libs/lame-3.98.4.tar.gz
  98. getlib http://files.freeswitch.org/downloads/libs/libshout-2.2.2.tar.gz
  99. getlib http://files.freeswitch.org/downloads/libs/mpg123-1.13.2.tar.gz
  100. getlib http://files.freeswitch.org/downloads/libs/v8-3.24.14.tar.bz2
  101. # cleanup mongo
  102. (
  103. cd mongo-cxx-driver-v1.8
  104. rm -rf config.log .sconf_temp *Test *Example
  105. find . -name "*.o" -exec rm -f {} \;
  106. )
  107. }
  108. check_repo_clean () {
  109. git diff-index --quiet --cached HEAD \
  110. || err "uncommitted changes present"
  111. git diff-files --quiet \
  112. || err "unclean working tree"
  113. git diff-index --quiet HEAD \
  114. || err "unclean repository"
  115. ! git ls-files --other --error-unmatch . >/dev/null 2>&1 \
  116. || err "untracked files or build products present"
  117. }
  118. get_last_release_ver () {
  119. grep -m1 -e '^AC_INIT' configure.ac \
  120. | cut -d, -f2 \
  121. | sed -e 's/\[//' -e 's/\]//' -e 's/ //g'
  122. }
  123. get_nightly_version () {
  124. local commit="$(git rev-list -n1 --abbrev=10 --abbrev-commit HEAD)"
  125. echo "$(get_last_release_ver)+git~$(date -u '+%Y%m%dT%H%M%SZ')~$commit"
  126. }
  127. get_nightly_revision_human () {
  128. echo "git $(git rev-list -n1 --abbrev=7 --abbrev-commit HEAD) $(date -u '+%Y-%m-%d %H:%M:%SZ')"
  129. }
  130. create_orig () {
  131. {
  132. set -e
  133. local OPTIND OPTARG
  134. local uver="" hrev="" bundle_deps=false modules_list="" zl=9e
  135. while getopts 'bm:nv:z:' o "$@"; do
  136. case "$o" in
  137. b) bundle_deps=true;;
  138. m) modules_list="$OPTARG";;
  139. n) uver="nightly";;
  140. v) uver="$OPTARG";;
  141. z) zl="$OPTARG";;
  142. esac
  143. done
  144. shift $(($OPTIND-1))
  145. if [ -z "$uver" ] || [ "$uver" = "nightly" ]; then
  146. uver="$(get_nightly_version)"
  147. hrev="$(get_nightly_revision_human)"
  148. fi
  149. local treeish="$1" dver="$(mk_dver "$uver")"
  150. local orig="../freeswitch_$dver.orig.tar.xz"
  151. [ -n "$treeish" ] || treeish="HEAD"
  152. check_repo_clean
  153. git reset --hard "$treeish"
  154. mv .gitattributes .gitattributes.orig
  155. local -a args=(-e '\bdebian-ignore\b')
  156. test "$modules_list" = "non-dfsg" || args+=(-e '\bdfsg-nonfree\b')
  157. grep .gitattributes.orig "${args[@]}" \
  158. | while xread l; do
  159. echo "$l export-ignore" >> .gitattributes
  160. done
  161. if $bundle_deps; then
  162. (cd libs && getlibs)
  163. git add -f libs
  164. fi
  165. ./build/set-fs-version.sh "$uver" "$hrev" && git add configure.ac
  166. echo "$uver" > .version && git add -f .version
  167. git commit --allow-empty -m "nightly v$uver"
  168. git archive -v \
  169. --worktree-attributes \
  170. --format=tar \
  171. --prefix=freeswitch-$uver/ \
  172. HEAD \
  173. | xz -c -${zl}v > $orig
  174. mv .gitattributes.orig .gitattributes
  175. git reset --hard HEAD^ && git clean -fdx
  176. } 1>&2
  177. echo $orig
  178. }
  179. set_modules_quicktest () {
  180. cat > debian/modules.conf <<EOF
  181. applications/mod_commands
  182. EOF
  183. }
  184. create_dsc () {
  185. {
  186. set -e
  187. local OPTIND OPTARG modules_conf="" modules_list="" speed="normal" suite_postfix="" suite_postfix_p=false zl=9
  188. local modules_add=""
  189. while getopts 'f:m:p:s:u:z:' o "$@"; do
  190. case "$o" in
  191. f) modules_conf="$OPTARG";;
  192. m) modules_list="$OPTARG";;
  193. p) modules_add="$modules_add $OPTARG";;
  194. s) speed="$OPTARG";;
  195. u) suite_postfix="$OPTARG"; suite_postfix_p=true; ;;
  196. z) zl="$OPTARG";;
  197. esac
  198. done
  199. shift $(($OPTIND-1))
  200. local distro="$(find_distro $1)" orig="$2"
  201. local suite="$(find_suite $distro)"
  202. local orig_ver="$(echo "$orig" | sed -e 's/^.*_//' -e 's/\.orig\.tar.*$//')"
  203. local dver="${orig_ver}-1~${distro}+1"
  204. $suite_postfix_p && { suite="${distro}${suite_postfix}"; }
  205. [ -x "$(which dch)" ] \
  206. || err "package devscripts isn't installed"
  207. if [ -n "$modules_conf" ]; then
  208. cp $modules_conf debian/modules.conf
  209. fi
  210. local bootstrap_args=""
  211. if [ -n "$modules_list" ]; then
  212. if [ "$modules_list" = "non-dfsg" ]; then
  213. bootstrap_args="-mnon-dfsg"
  214. else set_modules_${modules_list}; fi
  215. fi
  216. if test -n "$modules_add"; then
  217. for x in $modules_add; do
  218. bootstrap_args="$bootstrap_args -p${x}"
  219. done
  220. fi
  221. (cd debian && ./bootstrap.sh -c $distro $bootstrap_args)
  222. case "$speed" in
  223. paranoid) sed -i ./debian/rules \
  224. -e '/\.stamp-bootstrap:/{:l2 n; /\.\/bootstrap.sh -j/{s/ -j//; :l3 n; b l3}; b l2};' ;;
  225. reckless) sed -i ./debian/rules \
  226. -e '/\.stamp-build:/{:l2 n; /make/{s/$/ -j/; :l3 n; b l3}; b l2};' ;;
  227. esac
  228. [ "$zl" -ge "1" ] || zl=1
  229. git add debian/rules
  230. dch -b -m -v "$dver" --force-distribution -D "$suite" "Nightly build."
  231. git add debian/changelog && git commit -m "nightly v$orig_ver"
  232. dpkg-source -i.* -Zxz -z${zl} -b .
  233. dpkg-genchanges -S > ../$(dsc_base)_source.changes
  234. local dsc="../$(dsc_base).dsc"
  235. git reset --hard HEAD^ && git clean -fdx
  236. } 1>&2
  237. echo $dsc
  238. }
  239. fmt_debug_hook () {
  240. cat <<'EOF'
  241. #!/bin/bash
  242. export debian_chroot="cow"
  243. cd /tmp/buildd/*/debian/..
  244. /bin/bash < /dev/tty > /dev/tty 2> /dev/tty
  245. EOF
  246. }
  247. get_sources () {
  248. local tgt_distro="$1"
  249. while read type path distro components; do
  250. test "$type" = deb || continue
  251. printf "$type $path $tgt_distro $components\n"
  252. done < "$2"
  253. }
  254. get_mirrors () {
  255. file=${2-/etc/apt/sources.list}
  256. announce "Using apt sources file: $file"
  257. get_sources "$1" "$file" | tr '\n' '|' | head -c-1; echo
  258. }
  259. build_debs () {
  260. {
  261. set -e
  262. local OPTIND OPTARG debug_hook=false hookdir="" cow_build_opts=""
  263. local keep_pbuilder_config=false keyring="" custom_keyring=""
  264. local use_system_sources=false
  265. while getopts 'BbdK:kT:t' o "$@"; do
  266. case "$o" in
  267. B) cow_build_opts="--debbuildopts '-B'";;
  268. b) cow_build_opts="--debbuildopts '-b'";;
  269. d) debug_hook=true;;
  270. k) keep_pbuilder_config=true;;
  271. K) custom_keyring="$OPTARG";;
  272. t) use_system_sources=true; custom_sources_file="/etc/apt/sources.list";;
  273. T) use_custom_sources=true; custom_sources_file="$OPTARG";;
  274. esac
  275. done
  276. shift $(($OPTIND-1))
  277. local distro="$(find_distro $1)" dsc="$2" arch="$3"
  278. if [ -z "$distro" ] || [ "$distro" = "auto" ]; then
  279. if ! (echo "$dsc" | grep -e '-[0-9]*~[a-z]*+[0-9]*'); then
  280. err "no distro specified or found"
  281. fi
  282. local x="$(echo $dsc | sed -e 's/^[^-]*-[0-9]*~//' -e 's/+[^+]*$//')"
  283. distro="$(find_distro $x)"
  284. fi
  285. [ -n "$arch" ] || arch="$(dpkg-architecture | grep '^DEB_BUILD_ARCH=' | cut -d'=' -f2)"
  286. [ -x "$(which cowbuilder)" ] \
  287. || err "package cowbuilder isn't installed"
  288. local cow_img=/var/cache/pbuilder/base-$distro-$arch.cow
  289. if [ -e "$custom_keyring" ]; then
  290. keyring="$custom_keyring"
  291. else
  292. keyring="$(mktemp /tmp/keyringXXXXXXXX.asc)"
  293. apt-key exportall > "$keyring"
  294. fi
  295. cow () {
  296. if ! $use_system_sources; then
  297. cowbuilder "$@" \
  298. --distribution $distro \
  299. --architecture $arch \
  300. --basepath $cow_img
  301. else
  302. cowbuilder "$@" \
  303. --distribution $distro \
  304. --architecture $arch \
  305. --basepath $cow_img \
  306. --keyring "$keyring" \
  307. --othermirror "$(get_mirrors $distro $custom_sources_file)"
  308. fi
  309. }
  310. if [ ! -e "$custom_keyring" ]; then
  311. # Cleanup script created temporary file
  312. rm -f $keyring
  313. fi
  314. if ! [ -d $cow_img ]; then
  315. announce "Creating base $distro-$arch image..."
  316. local x=30
  317. while ! cow --create; do
  318. [ $x -lt 1 ] && break; sleep 120; x=$((x-1))
  319. done
  320. fi
  321. announce "Updating base $distro-$arch image..."
  322. local x=30
  323. local opts="--override-config"
  324. $keep_pbuilder_config && opts=""
  325. while ! cow --update $opts; do
  326. [ $x -lt 1 ] && break; sleep 120; x=$((x-1))
  327. done
  328. announce "Building $distro-$arch DEBs from $dsc..."
  329. if $debug_hook; then
  330. mkdir -p .hooks
  331. fmt_debug_hook > .hooks/C10shell
  332. chmod +x .hooks/C10shell
  333. hookdir=$(pwd)/.hooks
  334. fi
  335. cow --build $dsc \
  336. --hookdir "$hookdir" \
  337. --buildresult ../ \
  338. $cow_build_opts
  339. } 1>&2
  340. echo ${dsc%.dsc}_${arch}.changes
  341. }
  342. default_distros () {
  343. local host_distro="Debian"
  344. test -z "$(which lsb_release)" || host_distro="$(lsb_release -is)"
  345. case "$host_distro" in
  346. Debian) echo "sid jessie wheezy" ;;
  347. Ubuntu) echo "utopic trusty" ;;
  348. *) err "Unknown host distribution \"$host_distro\"" ;;
  349. esac
  350. }
  351. build_all () {
  352. local OPTIND OPTARG
  353. local orig_opts="" dsc_opts="" deb_opts="" modlist=""
  354. local archs="" distros="" orig="" depinst=false par=false
  355. while getopts 'a:bc:df:ijkl:m:no:p:s:tu:v:z:' o "$@"; do
  356. case "$o" in
  357. a) archs="$archs $OPTARG";;
  358. b) orig_opts="$orig_opts -b";;
  359. c) distros="$distros $OPTARG";;
  360. d) deb_opts="$deb_opts -d";;
  361. f) dsc_opts="$dsc_opts -f$OPTARG";;
  362. i) depinst=true;;
  363. j) par=true;;
  364. k) deb_opts="$deb_opts -k";;
  365. l) modlist="$OPTARG";;
  366. m) orig_opts="$orig_opts -m$OPTARG"; dsc_opts="$dsc_opts -m$OPTARG";;
  367. n) orig_opts="$orig_opts -n";;
  368. o) orig="$OPTARG";;
  369. p) dsc_opts="$dsc_opts -p$OPTARG";;
  370. s) dsc_opts="$dsc_opts -s$OPTARG";;
  371. t) deb_opts="$deb_opts -t";;
  372. u) dsc_opts="$dsc_opts -u$OPTARG";;
  373. v) orig_opts="$orig_opts -v$OPTARG";;
  374. z) orig_opts="$orig_opts -z$OPTARG"; dsc_opts="$dsc_opts -z$OPTARG";;
  375. esac
  376. done
  377. shift $(($OPTIND-1))
  378. [ -n "$archs" ] || archs="amd64 i386"
  379. [ -n "$distros" ] || distros="$(default_distros)"
  380. ! $depinst || aptitude install -y \
  381. rsync git less cowbuilder ccache \
  382. devscripts equivs build-essential
  383. [ -n "$orig" ] || orig="$(create_orig $orig_opts HEAD | tail -n1)"
  384. if [ -n "$modlist" ]; then
  385. local modtmp="$(mktemp /tmp/modules-XXXXXXXXXX.conf)"
  386. > $modtmp
  387. for m in "$modlist"; do printf '%s\n' "$m" >> $modtmp; done
  388. dsc_opts="$dsc_opts -f${modtmp}"; fi
  389. [ -n "$orig" ] || orig="$(create_orig $orig_opts HEAD | tail -n1)"
  390. mkdir -p ../log
  391. > ../log/changes
  392. echo; echo; echo; echo
  393. trap 'echo "Killing children...">&2; for x in $(jobs -p); do kill $x; done' EXIT
  394. if [ "${orig:0:2}" = ".." ]; then
  395. echo "true" > ../log/builds-ok
  396. for distro in $distros; do
  397. echo "Creating $distro dsc..." >&2
  398. local dsc="$(create_dsc $dsc_opts $distro $orig 2>../log/$distro | tail -n1)"
  399. echo "Done creating $distro dsc." >&2
  400. if [ "${dsc:0:2}" = ".." ]; then
  401. local lopts="-b"
  402. for arch in $archs; do
  403. {
  404. echo "Building $distro-$arch debs..." >&2
  405. local changes="$(build_debs $lopts $deb_opts $distro $dsc $arch 2>../log/$distro-$arch | tail -n1)"
  406. echo "Done building $distro-$arch debs." >&2
  407. if [ "${changes:0:2}" = ".." ]; then
  408. echo "$changes" >> ../log/changes
  409. else
  410. echo "false" > ../log/builds-ok
  411. fi
  412. } &
  413. $par || wait
  414. lopts="-B"
  415. done
  416. fi
  417. done
  418. ! $par || wait
  419. fi
  420. [ -z "$modlist" ] || rm -f $modtmp
  421. trap - EXIT
  422. cat ../log/changes
  423. test "$(cat ../log/builds-ok)" = true || exit 1
  424. }
  425. usage () {
  426. cat >&2 <<EOF
  427. $0 [opts] [cmd] [cmd-opts]
  428. options:
  429. -d Enable debugging mode.
  430. commands:
  431. archive-orig
  432. build-all
  433. [ This must be run as root! ]
  434. -a Specify architectures
  435. -b Bundle downloaded libraries in source package
  436. -c Specify distributions
  437. -d Enable cowbuilder debug hook
  438. -f <modules.conf>
  439. Build only modules listed in this file
  440. -i Auto install build deps on host system
  441. -j Build debs in parallel
  442. -k Don't override pbuilder image configurations
  443. -K [/path/to/keyring.asc]
  444. Use custom keyring file for sources.list in build environment
  445. in the format of: apt-key exportall > /path/to/file.asc
  446. -l <modules>
  447. -m [ quicktest | non-dfsg ]
  448. Choose custom list of modules to build
  449. -n Nightly build
  450. -o <orig-file>
  451. Specify existing .orig.tar.xz file
  452. -p <module>
  453. Include otherwise avoided module
  454. -s [ paranoid | reckless ]
  455. Set FS bootstrap/build -j flags
  456. -t Use system /etc/apt/sources.list in build environment
  457. -T [/path/to/sources.list]
  458. Use custom /etc/apt/sources.list in build environment
  459. -u <suite-postfix>
  460. Specify a custom suite postfix
  461. -v Set version
  462. -z Set compression level
  463. build-debs <distro> <dsc-file> <architecture>
  464. [ This must be run as root! ]
  465. -B Binary architecture-dependent build
  466. -b Binary-only build
  467. -d Enable cowbuilder debug hook
  468. -k Don't override pbuilder image configurations
  469. -K [/path/to/keyring.asc]
  470. Use custom keyring file for sources.list in build environment
  471. in the format of: apt-key exportall > /path/to/file.asc
  472. -t Use system /etc/apt/sources.list in build environment
  473. -T [/path/to/sources.list]
  474. Use custom /etc/apt/sources.list in build environment
  475. create-dbg-pkgs
  476. create-dsc <distro> <orig-file>
  477. -f <modules.conf>
  478. Build only modules listed in this file
  479. -m [ quicktest | non-dfsg ]
  480. Choose custom list of modules to build
  481. -p <module>
  482. Include otherwise avoided module
  483. -s [ paranoid | reckless ]
  484. Set FS bootstrap/build -j flags
  485. -u <suite-postfix>
  486. Specify a custom suite postfix
  487. -z Set compression level
  488. create-orig <treeish>
  489. -b Bundle downloaded libraries in source package
  490. -m [ quicktest | non-dfsg ]
  491. Choose custom list of modules to build
  492. -n Nightly build
  493. -v Set version
  494. -z Set compression level
  495. EOF
  496. exit 1
  497. }
  498. while getopts 'dh' o "$@"; do
  499. case "$o" in
  500. d) set -vx;;
  501. h) usage;;
  502. esac
  503. done
  504. shift $(($OPTIND-1))
  505. cmd="$1"; [ -n "$cmd" ] || usage
  506. shift
  507. case "$cmd" in
  508. archive-orig) archive_orig "$@" ;;
  509. build-all) build_all "$@" ;;
  510. build-debs) build_debs "$@" ;;
  511. create-dbg-pkgs) create_dbg_pkgs ;;
  512. create-dsc) create_dsc "$@" ;;
  513. create-orig) create_orig "$@" ;;
  514. *) usage ;;
  515. esac