update_autogen 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. #!/bin/bash
  2. ### update_autogen - update some auto-generated files in the Emacs tree
  3. ## Copyright (C) 2011-2015 Free Software Foundation, Inc.
  4. ## Author: Glenn Morris <rgm@gnu.org>
  5. ## This file is part of GNU Emacs.
  6. ## GNU Emacs is free software: you can redistribute it and/or modify
  7. ## it under the terms of the GNU General Public License as published by
  8. ## the Free Software Foundation, either version 3 of the License, or
  9. ## (at your option) any later version.
  10. ## GNU Emacs is distributed in the hope that it will be useful,
  11. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ## GNU General Public License for more details.
  14. ## You should have received a copy of the GNU General Public License
  15. ## along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ### Commentary:
  17. ## This is a helper script to update some generated files in the Emacs
  18. ## repository. This is suitable for running from cron.
  19. ## Only Emacs maintainers need use this, so it uses bash features.
  20. ##
  21. ## By default, it updates the versioned loaddefs-like files in lisp,
  22. ## except ldefs-boot.el.
  23. ### Code:
  24. die () # write error to stderr and exit
  25. {
  26. [ $# -gt 0 ] && echo "$PN: $@" >&2
  27. exit 1
  28. }
  29. PN=${0##*/} # basename of script
  30. PD=${0%/*}
  31. [ "$PD" = "$0" ] && PD=. # if PATH includes PWD
  32. ## This should be the admin directory.
  33. cd $PD
  34. cd ../
  35. [ -d admin ] || die "Could not locate admin directory"
  36. if [ -d .bzr ]; then
  37. vcs=bzr
  38. elif [ -d .git ]; then
  39. vcs=git
  40. else
  41. die "Cannot determine vcs"
  42. fi
  43. usage ()
  44. {
  45. cat 1>&2 <<EOF
  46. Usage: ${PN} [-f] [-c] [-q] [-A dir] [-I] [-L] [-C] [-- make-flags]
  47. Update some auto-generated files in the Emacs tree.
  48. By default, only does the versioned loaddefs-like files in lisp/.
  49. This requires a build. Passes any non-option args to make (eg -- -j2).
  50. Options:
  51. -f: force an update even if the source files are locally modified.
  52. -c: if the update succeeds and the generated files are modified,
  53. commit them (caution).
  54. -q: be quiet; only give error messages, not status messages.
  55. -A: only update autotools files, copying into specified dir.
  56. -I: also update info/dir.
  57. -L: also update ldefs-boot.el.
  58. -C: start from a clean state. Slower, but more correct.
  59. EOF
  60. exit 1
  61. }
  62. ## Defaults.
  63. force=
  64. commit=
  65. quiet=
  66. clean=
  67. autogendir= # was "autogen"
  68. ldefs_flag=1
  69. lboot_flag=
  70. info_flag=
  71. ## Parameters.
  72. ldefs_in=lisp/loaddefs.el
  73. ldefs_out=lisp/ldefs-boot.el
  74. sources="configure.ac lib/Makefile.am"
  75. ## Files to copy into autogendir.
  76. ## Everything:
  77. genfiles="
  78. configure aclocal.m4 src/config.in lib/Makefile.in
  79. build-aux/compile build-aux/config.guess build-aux/config.sub
  80. build-aux/depcomp build-aux/install-sh build-aux/missing
  81. "
  82. ## msdos-only:
  83. genfiles="src/config.in lib/Makefile.in"
  84. for g in $genfiles; do
  85. basegen="$basegen ${g##*/}"
  86. done
  87. [ "$basegen" ] || die "internal error"
  88. tempfile=/tmp/$PN.$$
  89. trap "rm -f $tempfile 2> /dev/null" EXIT
  90. while getopts ":hcfqA:CIL" option ; do
  91. case $option in
  92. (h) usage ;;
  93. (c) commit=1 ;;
  94. (f) force=1 ;;
  95. (q) quiet=1 ;;
  96. (A) autogendir=$OPTARG
  97. [ -d "$autogendir" ] || die "No autogen directory: $autogendir"
  98. ;;
  99. (C) clean=1 ;;
  100. (I) info_flag=1 ;;
  101. (L) lboot_flag=1 ;;
  102. (\?) die "Bad option -$OPTARG" ;;
  103. (:) die "Option -$OPTARG requires an argument" ;;
  104. (*) die "getopts error" ;;
  105. esac
  106. done
  107. shift $(( --OPTIND ))
  108. OPTIND=1
  109. ## Does not work 100% because a lot of Emacs batch output comes on stderr (?).
  110. [ "$quiet" ] && exec 1> /dev/null
  111. ## Run status on inputs, list modified files on stdout.
  112. status ()
  113. {
  114. local statflag="-S"
  115. [ "$vcs" = "git" ] && statflag="-s"
  116. $vcs status $statflag "$@" >| $tempfile || die "$vcs status error for $@"
  117. local stat file modified
  118. while read stat file; do
  119. [ "$stat" != "M" ] && \
  120. die "Unexpected status ($stat) for generated $file"
  121. modified="$modified $file"
  122. done < $tempfile
  123. echo "$modified"
  124. return 0
  125. } # function status
  126. echo "Checking input file status..."
  127. ## The lisp portion could be more permissive, eg only care about .el files.
  128. modified=$(status ${autogendir:+$sources} ${ldefs_flag:+lisp} ${info_flag:+doc}) || die
  129. [ "$modified" ] && {
  130. echo "Locally modified: $modified"
  131. [ "$force" ] || die "There are local modifications"
  132. }
  133. ## Probably this is overkill, and there's no need to "bootstrap" just
  134. ## for making autoloads.
  135. [ "$clean" ] && {
  136. echo "Running 'make maintainer-clean'..."
  137. make maintainer-clean #|| die "Cleaning error"
  138. rm -f $ldefs_in
  139. }
  140. echo "Running autoreconf..."
  141. autoreconf ${clean:+-f} -i -I m4 2>| $tempfile
  142. retval=$?
  143. ## Annoyingly, autoreconf puts the "installing `./foo' messages on stderr.
  144. if [ "$quiet" ]; then
  145. grep -v 'installing `\.' $tempfile 1>&2
  146. else
  147. cat "$tempfile" 1>&2
  148. fi
  149. [ $retval -ne 0 ] && die "autoreconf error"
  150. ## Uses global $commit.
  151. commit ()
  152. {
  153. local type=$1
  154. shift
  155. [ $# -gt 0 ] || {
  156. echo "No files were modified"
  157. return 0
  158. }
  159. echo "Modified file(s): $@"
  160. [ "$commit" ] || return 0
  161. echo "Committing..."
  162. $vcs commit -m "Auto-commit of $type files." "$@" || return $?
  163. [ "$vcs" = "git" ] && {
  164. $vcs push || return $?
  165. }
  166. echo "Committed files: $@"
  167. } # function commit
  168. ## No longer used since info/dir is now generated at install time if needed,
  169. ## and is not in the repository any more.
  170. info_dir ()
  171. {
  172. local basefile=build-aux/dir_top outfile=info/dir
  173. echo "Regenerating info/dir..."
  174. ## Header contains non-printing characters, so this is more
  175. ## reliable than using echo.
  176. rm -f $outfile
  177. cp $basefile $outfile
  178. local topic file dircat dirent
  179. ## FIXME inefficient looping.
  180. for topic in "Texinfo documentation system" "Emacs" "GNU Emacs Lisp" \
  181. "Emacs editing modes" "Emacs network features" "Emacs misc features" \
  182. "Emacs lisp libraries"; do
  183. cat - <<EOF >> $outfile
  184. $topic
  185. EOF
  186. ## Bit faster than doc/*/*.texi.
  187. for file in doc/emacs/emacs.texi doc/lispintro/*.texi \
  188. doc/lispref/elisp.texi doc/misc/*.texi; do
  189. ## FIXME do not ignore w32 if OS is w32.
  190. case $file in
  191. *-xtra.texi|*efaq-w32.texi) continue ;;
  192. esac
  193. dircat=$(sed -n -e 's/@value{emacsname}/Emacs/' -e 's/^@dircategory //p' $file)
  194. ## TODO warn about unknown topics (check-info in top-level
  195. ## Makefile does this).
  196. [ "$dircat" = "$topic" ] || continue
  197. sed -n -e 's/@value{emacsname}/Emacs/' \
  198. -e 's/@acronym{\([A-Z]*\)}/\1/' \
  199. -e '/^@direntry/,/^@end direntry/ s/^\([^@]\)/\1/p' \
  200. $file >> $outfile
  201. done
  202. done
  203. local modified
  204. modified=$(status $outfile) || die
  205. commit "info/dir" $modified || die "commit error"
  206. } # function info_dir
  207. [ "$autogendir" ] && {
  208. oldpwd=$PWD
  209. cp $genfiles $autogendir/
  210. cd $autogendir || die "cd error for $autogendir"
  211. echo "Checking status of generated files..."
  212. modified=$(status $basegen) || die
  213. commit "generated" $modified || die "commit error"
  214. exit 0
  215. } # $autogendir
  216. [ "$info_flag" ] && info_dir
  217. [ "$ldefs_flag" ] || exit 0
  218. echo "Finding loaddef targets..."
  219. find lisp -name '*.el' -exec grep '^;.*generated-autoload-file:' {} + | \
  220. sed -e '/loaddefs\|esh-groups/d' -e 's|/[^/]*: "|/|' -e 's/"//g' \
  221. >| $tempfile || die "Error finding targets"
  222. genfiles=
  223. while read genfile; do
  224. ## Or we can just use sort -u when making tempfile...
  225. case " $genfiles " in
  226. *" $genfile "*) continue ;;
  227. esac
  228. [ -r $genfile ] || die "Unable to read $genfile"
  229. genfiles="$genfiles $genfile"
  230. done < $tempfile
  231. [ "$genfiles" ] || die "Error setting genfiles"
  232. [ -e Makefile ] || {
  233. echo "Running ./configure..."
  234. ## Minimize required packages.
  235. ./configure --without-x || die "configure error"
  236. }
  237. ## Build the minimum needed to get the autoloads.
  238. echo "Running lib/ make..."
  239. make -C lib "$@" all || die "make lib error"
  240. echo "Running src/ make..."
  241. make -C src "$@" bootstrap-emacs || die "make src error"
  242. echo "Running lisp/ make..."
  243. make -C lisp "$@" autoloads EMACS=../src/bootstrap-emacs || die "make src error"
  244. ## Ignore comment differences.
  245. [ ! "$lboot_flag" ] || \
  246. diff -q -I '^;' $ldefs_in $ldefs_out || \
  247. cp $ldefs_in $ldefs_out || die "cp ldefs_boot error"
  248. echo "Checking status of loaddef files..."
  249. ## It probably would be fine to just check+commit lisp/, since
  250. ## making autoloads should not effect any other files. But better
  251. ## safe than sorry.
  252. modified=$(status $genfiles $ldefs_out) || die
  253. commit "loaddefs" $modified || die "commit error"
  254. exit 0
  255. ### update_autogen ends here