update_autogen 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. #!/usr/bin/env bash
  2. ### update_autogen - update some auto-generated files in the Emacs tree
  3. ## Copyright (C) 2011-2017 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. [ -d .git ] || die "No .git directory"
  37. usage ()
  38. {
  39. cat 1>&2 <<EOF
  40. Usage: ${PN} [-f] [-c] [-q] [-A dir] [-I] [-L] [-C] [-- make-flags]
  41. Update some auto-generated files in the Emacs tree.
  42. By default, only does the versioned loaddefs-like files in lisp/.
  43. This requires a build. Passes any non-option args to make (eg -- -j2).
  44. Options:
  45. -f: force an update even if the source files are locally modified.
  46. -c: if the update succeeds and the generated files are modified,
  47. commit them (caution).
  48. -q: be quiet; only give error messages, not status messages.
  49. -A: only update autotools files, copying into specified dir.
  50. -H: also update ChangeLog.${changelog_n}
  51. -I: also update info/dir.
  52. -L: also update ldefs-boot.el.
  53. -C: start from a clean state. Slower, but more correct.
  54. EOF
  55. exit 1
  56. }
  57. ## Defaults.
  58. force=
  59. commit=
  60. quiet=
  61. clean=
  62. autogendir= # was "autogen"
  63. ldefs_flag=1
  64. lboot_flag=
  65. info_flag=
  66. changelog_flag=
  67. ## Parameters.
  68. ldefs_in=lisp/loaddefs.el
  69. ldefs_out=lisp/ldefs-boot.el
  70. changelog_n=$(sed -n 's/CHANGELOG_HISTORY_INDEX_MAX *= *//p' Makefile.in)
  71. changelog_files="ChangeLog.$changelog_n"
  72. sources="configure.ac lib/Makefile.am"
  73. ## Files to copy into autogendir.
  74. ## Everything:
  75. genfiles="
  76. configure aclocal.m4 src/config.in
  77. build-aux/config.guess build-aux/config.sub
  78. build-aux/install-sh
  79. "
  80. ## msdos-only:
  81. genfiles="src/config.in"
  82. for g in $genfiles; do
  83. basegen="$basegen ${g##*/}"
  84. done
  85. [ "$basegen" ] || die "internal error"
  86. tempfile=/tmp/$PN.$$
  87. trap "rm -f $tempfile 2> /dev/null" EXIT
  88. while getopts ":hcfqA:HCIL" option ; do
  89. case $option in
  90. (h) usage ;;
  91. (c) commit=1 ;;
  92. (f) force=1 ;;
  93. (q) quiet=1 ;;
  94. (A) autogendir=$OPTARG
  95. [ -d "$autogendir" ] || die "No autogen directory: $autogendir"
  96. ;;
  97. (C) clean=1 ;;
  98. (H) changelog_flag=1 ;;
  99. (I) info_flag=1 ;;
  100. (L) lboot_flag=1 ;;
  101. (\?) die "Bad option -$OPTARG" ;;
  102. (:) die "Option -$OPTARG requires an argument" ;;
  103. (*) die "getopts error" ;;
  104. esac
  105. done
  106. shift $(( --OPTIND ))
  107. OPTIND=1
  108. ## Does not work 100% because a lot of Emacs batch output comes on stderr (?).
  109. [ "$quiet" ] && exec 1> /dev/null
  110. ## Run status on inputs, list modified files on stdout.
  111. status ()
  112. {
  113. git status -s "$@" >| $tempfile || die "git status error for $@"
  114. local stat file modified
  115. while read stat file; do
  116. [ "$stat" != "M" ] && \
  117. die "Unexpected status ($stat) for generated $file"
  118. modified="$modified $file"
  119. done < $tempfile
  120. echo "$modified"
  121. return 0
  122. } # function status
  123. echo "Checking input file status..."
  124. ## The lisp portion could be more permissive, eg only care about .el files.
  125. modified=$(status ${autogendir:+$sources} ${ldefs_flag:+lisp} ${info_flag:+doc}) || die
  126. [ "$modified" ] && {
  127. echo "Locally modified: $modified"
  128. [ "$force" ] || die "There are local modifications"
  129. }
  130. ## Probably this is overkill, and there's no need to "bootstrap" just
  131. ## for making autoloads.
  132. [ "$clean" ] && {
  133. echo "Running 'make maintainer-clean'..."
  134. make maintainer-clean #|| die "Cleaning error"
  135. rm -f $ldefs_in
  136. }
  137. echo "Running autoreconf..."
  138. autoreconf ${clean:+-f} -i -I m4 2>| $tempfile
  139. retval=$?
  140. ## Annoyingly, autoreconf puts the "installing `./foo' messages on stderr.
  141. if [ "$quiet" ]; then
  142. grep -v 'installing `\.' $tempfile 1>&2
  143. else
  144. cat "$tempfile" 1>&2
  145. fi
  146. [ $retval -ne 0 ] && die "autoreconf error"
  147. ## Uses global $commit.
  148. commit ()
  149. {
  150. local type=$1
  151. shift
  152. [ $# -gt 0 ] || {
  153. echo "No files were modified"
  154. return 0
  155. }
  156. echo "Modified file(s): $@"
  157. [ "$commit" ] || return 0
  158. echo "Committing..."
  159. git commit -m "; Auto-commit of $type files." "$@" || return $?
  160. ## In case someone else pushed something while we were working.
  161. git pull --rebase || return $?
  162. git push || return $?
  163. echo "Committed files: $@"
  164. } # function commit
  165. ## No longer used since info/dir is now generated at install time if needed,
  166. ## and is not in the repository any more.
  167. info_dir ()
  168. {
  169. local basefile=build-aux/dir_top outfile=info/dir
  170. echo "Regenerating info/dir..."
  171. ## Header contains non-printing characters, so this is more
  172. ## reliable than using echo.
  173. rm -f $outfile
  174. cp $basefile $outfile
  175. local topic file dircat dirent
  176. ## FIXME inefficient looping.
  177. for topic in "Texinfo documentation system" "Emacs" "GNU Emacs Lisp" \
  178. "Emacs editing modes" "Emacs network features" "Emacs misc features" \
  179. "Emacs lisp libraries"; do
  180. cat - <<EOF >> $outfile
  181. $topic
  182. EOF
  183. ## Bit faster than doc/*/*.texi.
  184. for file in doc/emacs/emacs.texi doc/lispintro/*.texi \
  185. doc/lispref/elisp.texi doc/misc/*.texi; do
  186. ## FIXME do not ignore w32 if OS is w32.
  187. case $file in
  188. *-xtra.texi|*efaq-w32.texi) continue ;;
  189. esac
  190. dircat=$(sed -n -e 's/@value{emacsname}/Emacs/' -e 's/^@dircategory //p' $file)
  191. ## TODO warn about unknown topics (check-info in top-level
  192. ## Makefile does this).
  193. [ "$dircat" = "$topic" ] || continue
  194. sed -n -e 's/@value{emacsname}/Emacs/' \
  195. -e 's/@acronym{\([A-Z]*\)}/\1/' \
  196. -e '/^@direntry/,/^@end direntry/ s/^\([^@]\)/\1/p' \
  197. $file >> $outfile
  198. done
  199. done
  200. local modified
  201. modified=$(status $outfile) || die
  202. commit "info/dir" $modified || die "commit error"
  203. } # function info_dir
  204. [ "$autogendir" ] && {
  205. oldpwd=$PWD
  206. cp $genfiles $autogendir/
  207. cd $autogendir || die "cd error for $autogendir"
  208. echo "Checking status of generated files..."
  209. modified=$(status $basegen) || die
  210. commit "generated" $modified || die "commit error"
  211. exit 0
  212. } # $autogendir
  213. [ "$info_flag" ] && info_dir
  214. [ "$ldefs_flag" ] || exit 0
  215. echo "Finding loaddef targets..."
  216. find lisp -name '*.el' -exec grep '^;.*generated-autoload-file:' {} + | \
  217. sed -e '/loaddefs\|esh-groups/d' -e 's|/[^/]*: "|/|' -e 's/"//g' \
  218. >| $tempfile || die "Error finding targets"
  219. genfiles=
  220. while read genfile; do
  221. ## Or we can just use sort -u when making tempfile...
  222. case " $genfiles " in
  223. *" $genfile "*) continue ;;
  224. esac
  225. [ -r $genfile ] || die "Unable to read $genfile"
  226. genfiles="$genfiles $genfile"
  227. done < $tempfile
  228. [ "$genfiles" ] || die "Error setting genfiles"
  229. [ -e Makefile ] || {
  230. echo "Running ./configure..."
  231. ## Minimize required packages.
  232. ./configure --without-x || die "configure error"
  233. }
  234. ## Build the minimum needed to get the autoloads.
  235. echo "Running lib/ make..."
  236. make -C lib "$@" all || die "make lib error"
  237. echo "Running src/ make..."
  238. make -C src "$@" bootstrap-emacs || die "make src error"
  239. echo "Running lisp/ make..."
  240. make -C lisp "$@" autoloads EMACS=../src/bootstrap-emacs || die "make src error"
  241. ## Ignore comment differences.
  242. [ ! "$lboot_flag" ] || \
  243. diff -q -I '^;' $ldefs_in $ldefs_out || \
  244. cp $ldefs_in $ldefs_out || die "cp ldefs_boot error"
  245. echo "Checking status of loaddef files..."
  246. ## It probably would be fine to just check+commit lisp/, since
  247. ## making autoloads should not effect any other files. But better
  248. ## safe than sorry.
  249. modified=$(status $genfiles $ldefs_out) || die
  250. commit "loaddefs" $modified || die "commit error"
  251. ## Less important than the other stuff, so do it last.
  252. [ ! "$changelog_flag" ] || {
  253. make change-history-nocommit || die "make change-history error"
  254. modified=$(status $changelog_files) || die
  255. commit "ChangeLog" $modified || die "commit error"
  256. }
  257. exit 0
  258. ### update_autogen ends here