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