* lisp/dired-aux.el (dired-do-chmod): Use `eq' to detect empty input.
[emacs.git] / admin / quick-install-emacs
blob4abef102dc48bc6ffd09ad4f07a8636ca867ddfa
1 #!/bin/sh
2 ### quick-install-emacs --- do a halfway-decent job of installing emacs quickly
4 ## Copyright (C) 2001-2012 Free Software Foundation, Inc.
6 ## Author: Miles Bader <miles@gnu.org>
8 ## This file is part of GNU Emacs.
10 ## GNU Emacs is free software: you can redistribute it and/or modify
11 ## it under the terms of the GNU General Public License as published by
12 ## the Free Software Foundation, either version 3 of the License, or
13 ## (at your option) any later version.
15 ## GNU Emacs is distributed in the hope that it will be useful,
16 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ## GNU General Public License for more details.
20 ## You should have received a copy of the GNU General Public License
21 ## along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24 ### Commentary:
26 ## This script is mainly intended for emacs maintainer or pretesters who
27 ## install emacs very often. See the --help output for more details.
30 PUBLIC_LIBSRC_BINARIES='emacsclient etags ctags ebrowse'
31 PUBLIC_LIBSRC_SCRIPTS='grep-changelog'
33 AVOID="CVS -DIC README COPYING ChangeLog ~ [.]orig$ [.]rej$ Makefile$ Makefile.in$ makefile$ makefile.w32-in$ stamp-subdir [.]cvsignore [.]arch-ids [{]arch[}] [.][cho]$ make-docfile testfile test-distrib"
35 # Prune old binaries lying around in the source tree
36 PRUNE=no
37 # Re-install files even if they already exist
38 FORCE=no
39 # Command verbose flag
40 VERBOSE=''
42 me="`basename $0`"
44 # Install commands (if the user specifies the `--verbose' option, it is
45 # passed to these commands, so that feature only works if these commands
46 # implement it too)
47 LINK='cp -lf'
48 COPY='cp -f'
49 REMOVE='rm -r'
50 MKDIR='mkdir -p'
52 # Used to execute commands once we create them
53 EXEC='sh'
55 NAWK=/usr/bin/nawk
57 # avoid non-standard command output from non-C locales
58 unset LANG LC_ALL LC_MESSAGES
60 # Some messages
61 USAGE="Usage: $me [OPTION...] BUILD_TREE [PREFIX]"
62 TRY="Try "\`"$me --help' for more information."
64 # Parse command-line options
65 while :; do
66 case "$1" in
67 -n|--dry-run)
68 EXEC=cat; shift;;
69 -p|--prune)
70 PRUNE=yes; shift;;
71 -P|--no-prune)
72 PRUNE=no; shift;;
73 --prune-only)
74 PRUNE=only; shift;;
75 -f|--force)
76 FORCE=yes; shift;;
77 -v|--verbose)
78 VERBOSE="-v"; shift;;
79 --help)
80 cat <<EOF
81 $USAGE
82 Install emacs quickly
84 -n, --dry-run print installation commands instead of
85 executing them
87 -f, --force install even files that haven't changed
88 -v, --verbose print messages describing what is done
90 -p, --prune prune old generated files
91 -P, --no-prune don't prune old generated files (default)
92 --prune-only prune old generated files, but don't install
94 --help display this help and exit
95 --version output version information and exit
97 $me install emacs \`incrementally,' that is, it will
98 install only those files that have changed since the last time it was
99 invoked, and remove any obsolete files from the installation
100 directories. It also uses hard-links into the source and build trees to
101 do the install, so it uses much less space than the default Makefile
102 install target; however, this also means that $me can
103 not install onto a disk partition other than the one on which the source
104 and build directories reside.
106 Optionally, $me can also remove old versions of
107 automatically generated files that are version-specific (such as the
108 versioned emacs executables in the \`src' directory, and the DOC-* files
109 in the \`etc' directory). The latter action is called \`pruning,' and
110 can be enabled using the \`-p' or \`--prune' options.
112 exit 0
114 --version)
115 cat <<EOF
116 $me 1.6
118 Written by Miles Bader <miles@gnu.org>
120 exit 0
122 -[!-]?*)
123 # split concatenated single-letter options apart
124 FIRST="$1"; shift
125 set -- `echo $FIRST | sed 's/-\(.\)\(.*\)/-\1 -\2/'` "$@"
128 echo 1>&2 "$me: unrecognized option "\`"$1'"
129 echo 1>&2 "$TRY"
130 exit 1
133 break;
134 esac
135 done
137 LINK_CMD="$LINK $VERBOSE"
138 REMOVE_CMD="$REMOVE $VERBOSE"
140 case $# in
141 1) BUILD="$1";;
142 2) BUILD="$1"; prefix="$2";;
144 echo 1>&2 "$USAGE"
145 echo 1>&2 "$TRY"
146 exit 1
148 esac
150 if test ! -d "$BUILD"; then
151 echo 1>&2 "$me: $BUILD: Build tree not found"
152 exit 2
153 elif test ! -r "$BUILD/config.status"; then
154 echo 1>&2 "$me: $BUILD: Not a proper build tree, config.status not found"
155 exit 2
158 CONFIG_STATUS="$BUILD/config.status"
159 get_config_var ()
161 { sed -n "s/^S[[]\"$1\"[]]=\"\([^\"]*\)\"/\1/p" $CONFIG_STATUS | sed q | grep ''; } ||
162 { sed -n "s/^s\(.\)@$1@\1\(|#_!!_#|\)*\(.*\)\1.*$/\3/p" $CONFIG_STATUS | sed q | grep ''; } ||
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=`
174 sed -n 's/^AC_INIT(emacs,[ ]*\([^ )]*\).*/\1/p' <$SRC/configure.ac
175 ` || exit 4
176 test -n "$VERSION" || { echo >&2 "$me: no version in configure.ac"; exit 4; }
178 DST_SHARE="$prefix/share/emacs/$VERSION"
179 DST_BIN="$prefix/bin"
180 DST_LIBEXEC="$prefix/libexec/emacs/$VERSION/$ARCH"
182 # There are various common places for the info dir to be, so try to
183 # use whatever's already there, defaulting to (and preferring)
184 # .../share/info.
186 DST_INFO=''
187 for D in "$prefix/share/info" "$prefix/info"; do
188 if test -d "$D"; then
189 DST_INFO="$D"
190 break
192 done
193 DST_INFO=${DST_INFO:-"$prefix/share/info"}
195 maybe_mkdir ()
197 if ! test -d "$1"; then
198 $MKDIR $VERBOSE "$1" 2>&1 | sed "s/^mkdir:/$me:/" 1>&2
202 maybe_mkdir "$DST_BIN"
203 maybe_mkdir "$DST_SHARE"
204 maybe_mkdir "$DST_SHARE/site-lisp"
205 maybe_mkdir "$DST_LIBEXEC"
206 maybe_mkdir "$DST_INFO"
208 ( # start of command-generating sub-shell
210 PRUNED=""
211 if test x"$PRUNE" != xno; then
212 for D in `ls -1t $BUILD/etc/DOC-* | sed 1d`; do
213 echo $REMOVE_CMD $D
214 PRUNED="$PRUNED $D"
215 done
216 for D in `ls -1t $BUILD/src/emacs-$VERSION.* | sed 1d`; do
217 echo $REMOVE_CMD $D
218 PRUNED="$PRUNED $D"
219 done
222 test x"$PRUNE" = xonly && exit 0
224 maybe_emit_copy ()
226 if test "$FORCE" = yes || ! cmp -s $1 $2; then
227 echo $LINK_CMD $1 $2
231 maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs
232 maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs-$VERSION
234 for F in $PUBLIC_LIBSRC_BINARIES; do
235 maybe_emit_copy $BUILD/lib-src/$F $DST_BIN/$F
236 done
237 for F in $PUBLIC_LIBSRC_SCRIPTS; do
238 maybe_emit_copy $SRC/lib-src/$F $DST_BIN/$F
239 done
241 if test x"$SRC" = x"$BUILD"; then
242 PFXS="$BUILD"
243 else
244 PFXS="$SRC $BUILD"
247 for SUBDIR in lisp leim etc lib-src info; do
248 # defaults
249 SHARED=no
250 FORCED=''
251 AVOID_PAT="`echo "($AVOID)" | tr ' ' '|'`"
253 # Set subdir-specific values
254 case $SUBDIR in
255 lisp|leim)
256 DST="$DST_SHARE/$SUBDIR"
258 etc)
259 DST="$DST_SHARE/$SUBDIR"
260 # COPYING is in the avoid list, but there should be a copy of it in
261 # the install etc dir, so make that here.
262 FORCED="$DST/COPYING"
264 lib-src)
265 DST="$DST_LIBEXEC"
266 AVOID_PAT="`echo "($AVOID ($PUBLIC_LIBSRC_BINARIES $PUBLIC_LIBSRC_SCRIPTS)\$)" | tr ' ' '|'`"
268 info)
269 DST="$DST_INFO"
270 SHARED=yes
272 esac
274 for PFX in $PFXS; do
275 if [ -d $PFX/$SUBDIR ]; then
276 for DIR in `(cd $PFX/$SUBDIR; find . -type d -print | sed 's@^./@@')`; do
277 if [ -d $DST/$DIR ]; then
278 echo Directory $DST/$DIR exists
279 else
280 echo Directory $DST/$DIR non-existent
281 if [ "`echo $DIR | egrep -v "$AVOID_PAT"`" ]; then
282 maybe_mkdir $DST/$DIR
285 done
286 diff -sqr $PFX/$SUBDIR $DST
288 done | $NAWK '
289 BEGIN {
290 src_pat = "^'"$SRC"'/'"$SUBDIR"'/"
291 build_pat = "^'"$BUILD"'/'"$SUBDIR"'/"
292 dst_pat = "^'"$DST"'/"
293 dst_pfx = "'"$DST"'/"
294 avoid_pat = "'"$AVOID_PAT"'"
295 force = ("'"$FORCE"'" == "yes")
296 shared = ("'"$SHARED"'" == "yes")
297 init_bool_array(pruned, "'"$PRUNED"'")
298 init_bool_array(forced, "'"$FORCED"'")
300 function init_bool_array(array, string, a,k)
302 split (string, a)
303 for (k in a)
304 array[a[k]] = 1
306 function install(src, dst)
308 if (! (src in pruned)) {
309 cp[src] = dst;
310 from[dst] = src;
311 delete rm[dst];
314 function update(src, dst, copy)
316 if (src in pruned) {
317 rm[dst] = 1;
318 delete from[dst]
319 } else {
320 if (copy)
321 cp[src] = dst;
322 from[dst] = src;
323 delete rm[dst];
326 function uninstall(dst)
328 if (!(dst in from))
329 rm[dst] = 1;
331 /^Directory / {
332 if ($2 ~ avoid_pat) {
333 if ($NF == "exists")
334 uninstall($2)
335 } else
336 update(0, $2, 0)
337 next
339 /^Files / {
340 if ($4 ~ avoid_pat && !($4 in forced))
341 uninstall($4)
342 else if ($NF == "identical")
343 update($2, $4, force)
344 else
345 update($2, $4, 1)
346 next
348 /^Only / {
349 pfx = $3
350 sub (/:$/, "/", pfx)
352 if (pfx ~ dst_pat) {
353 if (! shared)
354 uninstall(pfx $4)
355 } else {
356 subdir = pfx
357 if (subdir ~ src_pat)
358 sub (src_pat, "", subdir)
359 else
360 sub (build_pat, "", subdir)
362 dst = dst_pfx subdir $4
363 if (! (dst ~ avoid_pat))
364 install(pfx $4, dst)
366 next
368 END {
369 for (f in rm)
370 print "'"$REMOVE_CMD"' " f
371 for (f in cp)
372 print "'"$LINK_CMD"' " f " " cp[f]
375 done
377 ) | eval $EXEC