123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- #!/bin/bash
- ### update_autogen - update some auto-generated files in the Emacs tree
- ## Copyright (C) 2011-2015 Free Software Foundation, Inc.
- ## Author: Glenn Morris <rgm@gnu.org>
- ## This file is part of GNU Emacs.
- ## GNU Emacs is free software: you can redistribute it and/or modify
- ## it under the terms of the GNU General Public License as published by
- ## the Free Software Foundation, either version 3 of the License, or
- ## (at your option) any later version.
- ## GNU Emacs is distributed in the hope that it will be useful,
- ## but WITHOUT ANY WARRANTY; without even the implied warranty of
- ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ## GNU General Public License for more details.
- ## You should have received a copy of the GNU General Public License
- ## along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
- ### Commentary:
- ## This is a helper script to update some generated files in the Emacs
- ## repository. This is suitable for running from cron.
- ## Only Emacs maintainers need use this, so it uses bash features.
- ##
- ## By default, it updates the versioned loaddefs-like files in lisp,
- ## except ldefs-boot.el.
- ### Code:
- die () # write error to stderr and exit
- {
- [ $# -gt 0 ] && echo "$PN: $@" >&2
- exit 1
- }
- PN=${0##*/} # basename of script
- PD=${0%/*}
- [ "$PD" = "$0" ] && PD=. # if PATH includes PWD
- ## This should be the admin directory.
- cd $PD
- cd ../
- [ -d admin ] || die "Could not locate admin directory"
- if [ -d .bzr ]; then
- vcs=bzr
- elif [ -d .git ]; then
- vcs=git
- else
- die "Cannot determine vcs"
- fi
- usage ()
- {
- cat 1>&2 <<EOF
- Usage: ${PN} [-f] [-c] [-q] [-A dir] [-I] [-L] [-C] [-- make-flags]
- Update some auto-generated files in the Emacs tree.
- By default, only does the versioned loaddefs-like files in lisp/.
- This requires a build. Passes any non-option args to make (eg -- -j2).
- Options:
- -f: force an update even if the source files are locally modified.
- -c: if the update succeeds and the generated files are modified,
- commit them (caution).
- -q: be quiet; only give error messages, not status messages.
- -A: only update autotools files, copying into specified dir.
- -I: also update info/dir.
- -L: also update ldefs-boot.el.
- -C: start from a clean state. Slower, but more correct.
- EOF
- exit 1
- }
- ## Defaults.
- force=
- commit=
- quiet=
- clean=
- autogendir= # was "autogen"
- ldefs_flag=1
- lboot_flag=
- info_flag=
- ## Parameters.
- ldefs_in=lisp/loaddefs.el
- ldefs_out=lisp/ldefs-boot.el
- sources="configure.ac lib/Makefile.am"
- ## Files to copy into autogendir.
- ## Everything:
- genfiles="
- configure aclocal.m4 src/config.in lib/Makefile.in
- build-aux/compile build-aux/config.guess build-aux/config.sub
- build-aux/depcomp build-aux/install-sh build-aux/missing
- "
- ## msdos-only:
- genfiles="src/config.in lib/Makefile.in"
- for g in $genfiles; do
- basegen="$basegen ${g##*/}"
- done
- [ "$basegen" ] || die "internal error"
- tempfile=/tmp/$PN.$$
- trap "rm -f $tempfile 2> /dev/null" EXIT
- while getopts ":hcfqA:CIL" option ; do
- case $option in
- (h) usage ;;
- (c) commit=1 ;;
- (f) force=1 ;;
- (q) quiet=1 ;;
- (A) autogendir=$OPTARG
- [ -d "$autogendir" ] || die "No autogen directory: $autogendir"
- ;;
- (C) clean=1 ;;
- (I) info_flag=1 ;;
- (L) lboot_flag=1 ;;
- (\?) die "Bad option -$OPTARG" ;;
- (:) die "Option -$OPTARG requires an argument" ;;
- (*) die "getopts error" ;;
- esac
- done
- shift $(( --OPTIND ))
- OPTIND=1
- ## Does not work 100% because a lot of Emacs batch output comes on stderr (?).
- [ "$quiet" ] && exec 1> /dev/null
- ## Run status on inputs, list modified files on stdout.
- status ()
- {
- local statflag="-S"
- [ "$vcs" = "git" ] && statflag="-s"
- $vcs status $statflag "$@" >| $tempfile || die "$vcs status error for $@"
- local stat file modified
- while read stat file; do
- [ "$stat" != "M" ] && \
- die "Unexpected status ($stat) for generated $file"
- modified="$modified $file"
- done < $tempfile
- echo "$modified"
- return 0
- } # function status
- echo "Checking input file status..."
- ## The lisp portion could be more permissive, eg only care about .el files.
- modified=$(status ${autogendir:+$sources} ${ldefs_flag:+lisp} ${info_flag:+doc}) || die
- [ "$modified" ] && {
- echo "Locally modified: $modified"
- [ "$force" ] || die "There are local modifications"
- }
- ## Probably this is overkill, and there's no need to "bootstrap" just
- ## for making autoloads.
- [ "$clean" ] && {
- echo "Running 'make maintainer-clean'..."
- make maintainer-clean #|| die "Cleaning error"
- rm -f $ldefs_in
- }
- echo "Running autoreconf..."
- autoreconf ${clean:+-f} -i -I m4 2>| $tempfile
- retval=$?
- ## Annoyingly, autoreconf puts the "installing `./foo' messages on stderr.
- if [ "$quiet" ]; then
- grep -v 'installing `\.' $tempfile 1>&2
- else
- cat "$tempfile" 1>&2
- fi
- [ $retval -ne 0 ] && die "autoreconf error"
- ## Uses global $commit.
- commit ()
- {
- local type=$1
- shift
- [ $# -gt 0 ] || {
- echo "No files were modified"
- return 0
- }
- echo "Modified file(s): $@"
- [ "$commit" ] || return 0
- echo "Committing..."
- $vcs commit -m "Auto-commit of $type files." "$@" || return $?
- [ "$vcs" = "git" ] && {
- $vcs push || return $?
- }
- echo "Committed files: $@"
- } # function commit
- ## No longer used since info/dir is now generated at install time if needed,
- ## and is not in the repository any more.
- info_dir ()
- {
- local basefile=build-aux/dir_top outfile=info/dir
- echo "Regenerating info/dir..."
- ## Header contains non-printing characters, so this is more
- ## reliable than using echo.
- rm -f $outfile
- cp $basefile $outfile
- local topic file dircat dirent
- ## FIXME inefficient looping.
- for topic in "Texinfo documentation system" "Emacs" "GNU Emacs Lisp" \
- "Emacs editing modes" "Emacs network features" "Emacs misc features" \
- "Emacs lisp libraries"; do
- cat - <<EOF >> $outfile
- $topic
- EOF
- ## Bit faster than doc/*/*.texi.
- for file in doc/emacs/emacs.texi doc/lispintro/*.texi \
- doc/lispref/elisp.texi doc/misc/*.texi; do
- ## FIXME do not ignore w32 if OS is w32.
- case $file in
- *-xtra.texi|*efaq-w32.texi) continue ;;
- esac
- dircat=$(sed -n -e 's/@value{emacsname}/Emacs/' -e 's/^@dircategory //p' $file)
- ## TODO warn about unknown topics (check-info in top-level
- ## Makefile does this).
- [ "$dircat" = "$topic" ] || continue
- sed -n -e 's/@value{emacsname}/Emacs/' \
- -e 's/@acronym{\([A-Z]*\)}/\1/' \
- -e '/^@direntry/,/^@end direntry/ s/^\([^@]\)/\1/p' \
- $file >> $outfile
- done
- done
- local modified
- modified=$(status $outfile) || die
- commit "info/dir" $modified || die "commit error"
- } # function info_dir
- [ "$autogendir" ] && {
- oldpwd=$PWD
- cp $genfiles $autogendir/
- cd $autogendir || die "cd error for $autogendir"
- echo "Checking status of generated files..."
- modified=$(status $basegen) || die
- commit "generated" $modified || die "commit error"
- exit 0
- } # $autogendir
- [ "$info_flag" ] && info_dir
- [ "$ldefs_flag" ] || exit 0
- echo "Finding loaddef targets..."
- find lisp -name '*.el' -exec grep '^;.*generated-autoload-file:' {} + | \
- sed -e '/loaddefs\|esh-groups/d' -e 's|/[^/]*: "|/|' -e 's/"//g' \
- >| $tempfile || die "Error finding targets"
- genfiles=
- while read genfile; do
- ## Or we can just use sort -u when making tempfile...
- case " $genfiles " in
- *" $genfile "*) continue ;;
- esac
- [ -r $genfile ] || die "Unable to read $genfile"
- genfiles="$genfiles $genfile"
- done < $tempfile
- [ "$genfiles" ] || die "Error setting genfiles"
- [ -e Makefile ] || {
- echo "Running ./configure..."
- ## Minimize required packages.
- ./configure --without-x || die "configure error"
- }
- ## Build the minimum needed to get the autoloads.
- echo "Running lib/ make..."
- make -C lib "$@" all || die "make lib error"
- echo "Running src/ make..."
- make -C src "$@" bootstrap-emacs || die "make src error"
- echo "Running lisp/ make..."
- make -C lisp "$@" autoloads EMACS=../src/bootstrap-emacs || die "make src error"
- ## Ignore comment differences.
- [ ! "$lboot_flag" ] || \
- diff -q -I '^;' $ldefs_in $ldefs_out || \
- cp $ldefs_in $ldefs_out || die "cp ldefs_boot error"
- echo "Checking status of loaddef files..."
- ## It probably would be fine to just check+commit lisp/, since
- ## making autoloads should not effect any other files. But better
- ## safe than sorry.
- modified=$(status $genfiles $ldefs_out) || die
- commit "loaddefs" $modified || die "commit error"
- exit 0
- ### update_autogen ends here
|