Comment.
[emacs.git] / admin / quick-install-emacs
blob675750a43e8d9cb263cefd95714cac7894a60247
1 #!/bin/sh
2 ### quick-install-emacs --- do a halfway-decent job of installing emacs quickly
4 ## Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 ## Free Software Foundation, Inc.
7 ## Author: Miles Bader <miles@gnu.org>
9 ## This file is part of GNU Emacs.
11 ## GNU Emacs is free software: you can redistribute it and/or modify
12 ## it under the terms of the GNU General Public License as published by
13 ## the Free Software Foundation, either version 3 of the License, or
14 ## (at your option) any later version.
16 ## GNU Emacs is distributed in the hope that it will be useful,
17 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ## GNU General Public License for more details.
21 ## You should have received a copy of the GNU General Public License
22 ## along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
25 ### Commentary:
27 ## This script is mainly intended for emacs maintainer or pretesters who
28 ## install emacs very often. See the --help output for more details.
31 PUBLIC_LIBSRC_BINARIES='b2m emacsclient etags ctags ebrowse'
32 PUBLIC_LIBSRC_SCRIPTS='grep-changelog rcs-checkin'
34 AVOID="CVS -DIC README COPYING ChangeLog ~ [.]orig$ [.]rej$ Makefile makefile stamp-subdir [.]cvsignore [.]arch-ids [{]arch[}] [.][cho]$ make-docfile testfile test-distrib"
36 # Prune old binaries lying around in the source tree
37 PRUNE=no
38 # Re-install files even if they already exist
39 FORCE=no
40 # Command verbose flag
41 VERBOSE=''
43 me="`basename $0`"
45 # Install commands (if the user specifies the `--verbose' option, it is
46 # passed to these commands, so that feature only works if these commands
47 # implement it too)
48 LINK='cp -lf'
49 COPY='cp -f'
50 REMOVE='rm -r'
51 MKDIR='mkdir -p'
53 # Used to execute commands once once we create them
54 EXEC='sh'
56 NAWK=/usr/bin/nawk
58 # avoid non-standard command output from non-C locales
59 unset LANG LC_ALL LC_MESSAGES
61 # Some messages
62 USAGE="Usage: $me [OPTION...] BUILD_TREE [PREFIX]"
63 TRY="Try "\`"$me --help' for more information."
65 # Parse command-line options
66 while :; do
67 case "$1" in
68 -n|--dry-run)
69 EXEC=cat; shift;;
70 -p|--prune)
71 PRUNE=yes; shift;;
72 -P|--no-prune)
73 PRUNE=no; shift;;
74 --prune-only)
75 PRUNE=only; shift;;
76 -f|--force)
77 FORCE=yes; shift;;
78 -v|--verbose)
79 VERBOSE="-v"; shift;;
80 --help)
81 cat <<EOF
82 $USAGE
83 Install emacs quickly
85 -n, --dry-run print installation commands instead of
86 executing them
88 -f, --force install even files that haven't changed
89 -v, --verbose print messages describing what is done
91 -p, --prune prune old generated files
92 -P, --no-prune don't prune old generated files (default)
93 --prune-only prune old generated files, but don't install
95 --help display this help and exit
96 --version output version information and exit
98 $me install emacs \`incrementally,' that is, it will
99 install only those files that have changed since the last time it was
100 invoked, and remove any obsolete files from the installation
101 directories. It also uses hard-links into the source and build trees to
102 do the install, so it uses much less space than the default Makefile
103 install target; however, this also means that $me can
104 not install onto a disk partition other than the one on which the source
105 and build directories reside.
107 Optionally, $me can also remove old versions of
108 automatically generated files that are version-specific (such as the
109 versioned emacs executables in the \`src' directory, and the DOC-* files
110 in the \`etc' directory). The latter action is called \`pruning,' and
111 can be enabled using the \`-p' or \`--prune' options.
113 exit 0
115 --version)
116 cat <<EOF
117 $me 1.6
119 Written by Miles Bader <miles@gnu.org>
121 exit 0
123 -[^-]?*)
124 # split concatenated single-letter options apart
125 FIRST="$1"; shift
126 set -- `echo $FIRST | sed 's/-\(.\)\(.*\)/-\1 -\2/'` "$@"
129 echo 1>&2 "$me: unrecognized option "\`"$1'"
130 echo 1>&2 "$TRY"
131 exit 1
134 break;
135 esac
136 done
138 LINK_CMD="$LINK $VERBOSE"
139 REMOVE_CMD="$REMOVE $VERBOSE"
141 case $# in
142 1) BUILD="$1";;
143 2) BUILD="$1"; prefix="$2";;
145 echo 1>&2 "$USAGE"
146 echo 1>&2 "$TRY"
147 exit 1
149 esac
151 if test ! -d "$BUILD"; then
152 echo 1>&2 "$me: $BUILD: Build tree not found"
153 exit 2
154 elif test ! -r "$BUILD/config.status"; then
155 echo 1>&2 "$me: $BUILD: Not a proper build tree, config.status not found"
156 exit 2
159 CONFIG_STATUS="$BUILD/config.status"
160 get_config_var ()
162 if ! sed -n "s/^s\(.\)@$1@\1\(|#_!!_#|\)*\(.*\)\1.*$/\3/p" $CONFIG_STATUS | sed q | grep ''
163 then
164 echo 1>&2 "$me: $1: Configuration variable not found in $CONFIG_STATUS"
165 exit 4
169 test x"$SRC" = x && { SRC="`get_config_var srcdir`" || exit 4 ; }
170 test x"$prefix" = x && { prefix="`get_config_var prefix`" || exit 4 ; }
171 test x"$ARCH" = x && { ARCH="`get_config_var host`" || exit 4 ; }
173 VERSION=`grep 'defconst[ ]*emacs-version' $SRC/lisp/version.el \
174 | sed -e 's/^[^"]*"\([^"]*\)".*$/\1/'`
176 DST_SHARE="$prefix/share/emacs/$VERSION"
177 DST_BIN="$prefix/bin"
178 DST_LIBEXEC="$prefix/libexec/emacs/$VERSION/$ARCH"
179 DST_INFO="$prefix/info"
181 maybe_mkdir ()
183 if ! test -d "$1"; then
184 $MKDIR $VERBOSE "$1" 2>&1 | sed "s/^mkdir:/$me:/" 1>&2
188 maybe_mkdir "$DST_BIN"
189 maybe_mkdir "$DST_SHARE"
190 maybe_mkdir "$DST_SHARE/site-lisp"
191 maybe_mkdir "$DST_LIBEXEC"
192 maybe_mkdir "$DST_INFO"
194 ( # start of command-generating sub-shell
196 PRUNED=""
197 if test x"$PRUNE" != xno; then
198 for D in `ls -1t $BUILD/etc/DOC-* | sed 1d`; do
199 echo $REMOVE_CMD $D
200 PRUNED="$PRUNED $D"
201 done
202 for D in `ls -1t $BUILD/src/emacs-$VERSION.* | sed 1d`; do
203 echo $REMOVE_CMD $D
204 PRUNED="$PRUNED $D"
205 done
208 test x"$PRUNE" = xonly && exit 0
210 maybe_emit_copy ()
212 if test "$FORCE" = yes || ! cmp -s $1 $2; then
213 echo $LINK_CMD $1 $2
217 maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs
218 maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs-$VERSION
220 for F in $PUBLIC_LIBSRC_BINARIES; do
221 maybe_emit_copy $BUILD/lib-src/$F $DST_BIN/$F
222 done
223 for F in $PUBLIC_LIBSRC_SCRIPTS; do
224 maybe_emit_copy $SRC/lib-src/$F $DST_BIN/$F
225 done
227 if test x"$SRC" = x"$BUILD"; then
228 PFXS="$BUILD"
229 else
230 PFXS="$SRC $BUILD"
233 for SUBDIR in lisp leim etc lib-src info; do
234 # defaults
235 SHARED=no
236 FORCED=''
237 AVOID_PAT="`echo "($AVOID)" | tr ' ' '|'`"
239 # Set subdir-specific values
240 case $SUBDIR in
241 lisp|leim)
242 DST="$DST_SHARE/$SUBDIR"
244 etc)
245 DST="$DST_SHARE/$SUBDIR"
246 # COPYING is in the avoid list, but there should be a copy of it in
247 # the install etc dir, so make that here.
248 FORCED="$DST/COPYING"
250 lib-src)
251 DST="$DST_LIBEXEC"
252 AVOID_PAT="`echo "($AVOID ($PUBLIC_LIBSRC_BINARIES $PUBLIC_LIBSRC_SCRIPTS)\$)" | tr ' ' '|'`"
254 info)
255 DST="$DST_INFO"
256 SHARED=yes
258 esac
260 for PFX in $PFXS; do
261 if [ -d $PFX/$SUBDIR ]; then
262 for DIR in `(cd $PFX/$SUBDIR; find . -type d -print | sed 's@^./@@')`; do
263 if [ -d $DST/$DIR ]; then
264 echo Directory $DST/$DIR exists
265 else
266 echo Directory $DST/$DIR non-existant
267 if [ "`echo $DIR | egrep -v "$AVOID_PAT"`" ]; then
268 maybe_mkdir $DST/$DIR
271 done
272 diff -sqr $PFX/$SUBDIR $DST
274 done | $NAWK '
275 BEGIN {
276 src_pat = "^'"$SRC"'/'"$SUBDIR"'/"
277 build_pat = "^'"$BUILD"'/'"$SUBDIR"'/"
278 dst_pat = "^'"$DST"'/"
279 dst_pfx = "'"$DST"'/"
280 avoid_pat = "'"$AVOID_PAT"'"
281 force = ("'"$FORCE"'" == "yes")
282 shared = ("'"$SHARED"'" == "yes")
283 init_bool_array(pruned, "'"$PRUNED"'")
284 init_bool_array(forced, "'"$FORCED"'")
286 function init_bool_array(array, string, a,k)
288 split (string, a)
289 for (k in a)
290 array[a[k]] = 1
292 function install(src, dst)
294 if (! (src in pruned)) {
295 cp[src] = dst;
296 from[dst] = src;
297 delete rm[dst];
300 function update(src, dst, copy)
302 if (src in pruned) {
303 rm[dst] = 1;
304 delete from[dst]
305 } else {
306 if (copy)
307 cp[src] = dst;
308 from[dst] = src;
309 delete rm[dst];
312 function uninstall(dst)
314 if (!(dst in from))
315 rm[dst] = 1;
317 /^Directory / {
318 if ($2 ~ avoid_pat) {
319 if ($NF == "exists")
320 uninstall($2)
321 } else
322 update(0, $2, 0)
323 next
325 /^Files / {
326 if ($4 ~ avoid_pat && !($4 in forced))
327 uninstall($4)
328 else if ($NF == "identical")
329 update($2, $4, force)
330 else
331 update($2, $4, 1)
332 next
334 /^Only / {
335 pfx = $3
336 sub (/:$/, "/", pfx)
338 if (pfx ~ dst_pat) {
339 if (! shared)
340 uninstall(pfx $4)
341 } else {
342 subdir = pfx
343 if (subdir ~ src_pat)
344 sub (src_pat, "", subdir)
345 else
346 sub (build_pat, "", subdir)
348 dst = dst_pfx subdir $4
349 if (! (dst ~ avoid_pat))
350 install(pfx $4, dst)
352 next
354 END {
355 for (f in rm)
356 print "'"$REMOVE_CMD"' " f
357 for (f in cp)
358 print "'"$LINK_CMD"' " f " " cp[f]
361 done
363 ) | eval $EXEC
365 # arch-tag: 9322b572-9755-4cf7-a67a-21e6505f1477