* customize.texi (Composite Types): Move alist/plist from Simple Types (Bug#7545).
[emacs.git] / admin / quick-install-emacs
blob1ad9c28aae23b112cc46c706db9c1553555a2824
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, 2009, 2010, 2011
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 { sed -n "s/^S[[]\"$1\"[]]=\"\([^\"]*\)\"/\1/p" $CONFIG_STATUS | sed q | grep ''; } ||
163 { sed -n "s/^s\(.\)@$1@\1\(|#_!!_#|\)*\(.*\)\1.*$/\3/p" $CONFIG_STATUS | sed q | grep ''; } ||
165 echo 1>&2 "$me: $1: Configuration variable not found in $CONFIG_STATUS"
166 exit 4
170 test x"$SRC" = x && { SRC="`get_config_var srcdir`" || exit 4 ; }
171 test x"$prefix" = x && { prefix="`get_config_var prefix`" || exit 4 ; }
172 test x"$ARCH" = x && { ARCH="`get_config_var host`" || exit 4 ; }
174 VERSION=`grep 'defconst[ ]*emacs-version' $SRC/lisp/version.el \
175 | sed -e 's/^[^"]*"\([^"]*\)".*$/\1/'`
177 DST_SHARE="$prefix/share/emacs/$VERSION"
178 DST_BIN="$prefix/bin"
179 DST_LIBEXEC="$prefix/libexec/emacs/$VERSION/$ARCH"
181 # There are various common places for the info dir to be, so try to
182 # use whatever's already there, defaulting to (and preferring)
183 # .../share/info.
185 DST_INFO=''
186 for D in "$prefix/share/info" "$prefix/info"; do
187 if test -d "$D"; then
188 DST_INFO="$D"
189 break
191 done
192 DST_INFO=${DST_INFO:-"$prefix/share/info"}
194 maybe_mkdir ()
196 if ! test -d "$1"; then
197 $MKDIR $VERBOSE "$1" 2>&1 | sed "s/^mkdir:/$me:/" 1>&2
201 maybe_mkdir "$DST_BIN"
202 maybe_mkdir "$DST_SHARE"
203 maybe_mkdir "$DST_SHARE/site-lisp"
204 maybe_mkdir "$DST_LIBEXEC"
205 maybe_mkdir "$DST_INFO"
207 ( # start of command-generating sub-shell
209 PRUNED=""
210 if test x"$PRUNE" != xno; then
211 for D in `ls -1t $BUILD/etc/DOC-* | sed 1d`; do
212 echo $REMOVE_CMD $D
213 PRUNED="$PRUNED $D"
214 done
215 for D in `ls -1t $BUILD/src/emacs-$VERSION.* | sed 1d`; do
216 echo $REMOVE_CMD $D
217 PRUNED="$PRUNED $D"
218 done
221 test x"$PRUNE" = xonly && exit 0
223 maybe_emit_copy ()
225 if test "$FORCE" = yes || ! cmp -s $1 $2; then
226 echo $LINK_CMD $1 $2
230 maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs
231 maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs-$VERSION
233 for F in $PUBLIC_LIBSRC_BINARIES; do
234 maybe_emit_copy $BUILD/lib-src/$F $DST_BIN/$F
235 done
236 for F in $PUBLIC_LIBSRC_SCRIPTS; do
237 maybe_emit_copy $SRC/lib-src/$F $DST_BIN/$F
238 done
240 if test x"$SRC" = x"$BUILD"; then
241 PFXS="$BUILD"
242 else
243 PFXS="$SRC $BUILD"
246 for SUBDIR in lisp leim etc lib-src info; do
247 # defaults
248 SHARED=no
249 FORCED=''
250 AVOID_PAT="`echo "($AVOID)" | tr ' ' '|'`"
252 # Set subdir-specific values
253 case $SUBDIR in
254 lisp|leim)
255 DST="$DST_SHARE/$SUBDIR"
257 etc)
258 DST="$DST_SHARE/$SUBDIR"
259 # COPYING is in the avoid list, but there should be a copy of it in
260 # the install etc dir, so make that here.
261 FORCED="$DST/COPYING"
263 lib-src)
264 DST="$DST_LIBEXEC"
265 AVOID_PAT="`echo "($AVOID ($PUBLIC_LIBSRC_BINARIES $PUBLIC_LIBSRC_SCRIPTS)\$)" | tr ' ' '|'`"
267 info)
268 DST="$DST_INFO"
269 SHARED=yes
271 esac
273 for PFX in $PFXS; do
274 if [ -d $PFX/$SUBDIR ]; then
275 for DIR in `(cd $PFX/$SUBDIR; find . -type d -print | sed 's@^./@@')`; do
276 if [ -d $DST/$DIR ]; then
277 echo Directory $DST/$DIR exists
278 else
279 echo Directory $DST/$DIR non-existent
280 if [ "`echo $DIR | egrep -v "$AVOID_PAT"`" ]; then
281 maybe_mkdir $DST/$DIR
284 done
285 diff -sqr $PFX/$SUBDIR $DST
287 done | $NAWK '
288 BEGIN {
289 src_pat = "^'"$SRC"'/'"$SUBDIR"'/"
290 build_pat = "^'"$BUILD"'/'"$SUBDIR"'/"
291 dst_pat = "^'"$DST"'/"
292 dst_pfx = "'"$DST"'/"
293 avoid_pat = "'"$AVOID_PAT"'"
294 force = ("'"$FORCE"'" == "yes")
295 shared = ("'"$SHARED"'" == "yes")
296 init_bool_array(pruned, "'"$PRUNED"'")
297 init_bool_array(forced, "'"$FORCED"'")
299 function init_bool_array(array, string, a,k)
301 split (string, a)
302 for (k in a)
303 array[a[k]] = 1
305 function install(src, dst)
307 if (! (src in pruned)) {
308 cp[src] = dst;
309 from[dst] = src;
310 delete rm[dst];
313 function update(src, dst, copy)
315 if (src in pruned) {
316 rm[dst] = 1;
317 delete from[dst]
318 } else {
319 if (copy)
320 cp[src] = dst;
321 from[dst] = src;
322 delete rm[dst];
325 function uninstall(dst)
327 if (!(dst in from))
328 rm[dst] = 1;
330 /^Directory / {
331 if ($2 ~ avoid_pat) {
332 if ($NF == "exists")
333 uninstall($2)
334 } else
335 update(0, $2, 0)
336 next
338 /^Files / {
339 if ($4 ~ avoid_pat && !($4 in forced))
340 uninstall($4)
341 else if ($NF == "identical")
342 update($2, $4, force)
343 else
344 update($2, $4, 1)
345 next
347 /^Only / {
348 pfx = $3
349 sub (/:$/, "/", pfx)
351 if (pfx ~ dst_pat) {
352 if (! shared)
353 uninstall(pfx $4)
354 } else {
355 subdir = pfx
356 if (subdir ~ src_pat)
357 sub (src_pat, "", subdir)
358 else
359 sub (build_pat, "", subdir)
361 dst = dst_pfx subdir $4
362 if (! (dst ~ avoid_pat))
363 install(pfx $4, dst)
365 next
367 END {
368 for (f in rm)
369 print "'"$REMOVE_CMD"' " f
370 for (f in cp)
371 print "'"$LINK_CMD"' " f " " cp[f]
374 done
376 ) | eval $EXEC
378 # arch-tag: 9322b572-9755-4cf7-a67a-21e6505f1477