]> code.delx.au - gnu-emacs/blob - admin/quick-install-emacs
Sign-off on sending.texi.
[gnu-emacs] / 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, 2008, 2009
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 of the License, or
14 ## (at your option) 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. If not, see <http://www.gnu.org/licenses/>.
23
24
25 ### Commentary:
26
27 ## This script is mainly intended for emacs maintainer or pretesters who
28 ## install emacs very often. See the --help output for more details.
29
30
31 PUBLIC_LIBSRC_BINARIES='b2m emacsclient etags ctags ebrowse'
32 PUBLIC_LIBSRC_SCRIPTS='grep-changelog rcs-checkin'
33
34 AVOID="CVS -DIC README COPYING ChangeLog ~ [.]orig$ [.]rej$ Makefile makefile stamp-subdir [.]cvsignore [.]arch-ids [{]arch[}] [.][cho]$ make-docfile testfile test-distrib"
35
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=''
42
43 me="`basename $0`"
44
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'
52
53 # Used to execute commands once once we create them
54 EXEC='sh'
55
56 NAWK=/usr/bin/nawk
57
58 # avoid non-standard command output from non-C locales
59 unset LANG LC_ALL LC_MESSAGES
60
61 # Some messages
62 USAGE="Usage: $me [OPTION...] BUILD_TREE [PREFIX]"
63 TRY="Try "\`"$me --help' for more information."
64
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
84
85 -n, --dry-run print installation commands instead of
86 executing them
87
88 -f, --force install even files that haven't changed
89 -v, --verbose print messages describing what is done
90
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
94
95 --help display this help and exit
96 --version output version information and exit
97
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.
106
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.
112 EOF
113 exit 0
114 ;;
115 --version)
116 cat <<EOF
117 $me 1.6
118
119 Written by Miles Bader <miles@gnu.org>
120 EOF
121 exit 0
122 ;;
123 -[^-]?*)
124 # split concatenated single-letter options apart
125 FIRST="$1"; shift
126 set -- `echo $FIRST | sed 's/-\(.\)\(.*\)/-\1 -\2/'` "$@"
127 ;;
128 -*)
129 echo 1>&2 "$me: unrecognized option "\`"$1'"
130 echo 1>&2 "$TRY"
131 exit 1
132 ;;
133 *)
134 break;
135 esac
136 done
137
138 LINK_CMD="$LINK $VERBOSE"
139 REMOVE_CMD="$REMOVE $VERBOSE"
140
141 case $# in
142 1) BUILD="$1";;
143 2) BUILD="$1"; prefix="$2";;
144 *)
145 echo 1>&2 "$USAGE"
146 echo 1>&2 "$TRY"
147 exit 1
148 ;;
149 esac
150
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
157 fi
158
159 CONFIG_STATUS="$BUILD/config.status"
160 get_config_var ()
161 {
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
166 fi
167 }
168
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 ; }
172
173 VERSION=`grep 'defconst[ ]*emacs-version' $SRC/lisp/version.el \
174 | sed -e 's/^[^"]*"\([^"]*\)".*$/\1/'`
175
176 DST_SHARE="$prefix/share/emacs/$VERSION"
177 DST_BIN="$prefix/bin"
178 DST_LIBEXEC="$prefix/libexec/emacs/$VERSION/$ARCH"
179
180 # There are various common places for the info dir to be, so try to
181 # use whatever's already there, defaulting to (and preferring)
182 # .../share/info.
183 #
184 DST_INFO=''
185 for D in "$prefix/share/info" "$prefix/info"; do
186 if test -d "$D"; then
187 DST_INFO="$D"
188 break
189 fi
190 done
191 DST_INFO=${DST_INFO:-"$prefix/share/info"}
192
193 maybe_mkdir ()
194 {
195 if ! test -d "$1"; then
196 $MKDIR $VERBOSE "$1" 2>&1 | sed "s/^mkdir:/$me:/" 1>&2
197 fi
198 }
199
200 maybe_mkdir "$DST_BIN"
201 maybe_mkdir "$DST_SHARE"
202 maybe_mkdir "$DST_SHARE/site-lisp"
203 maybe_mkdir "$DST_LIBEXEC"
204 maybe_mkdir "$DST_INFO"
205
206 ( # start of command-generating sub-shell
207
208 PRUNED=""
209 if test x"$PRUNE" != xno; then
210 for D in `ls -1t $BUILD/etc/DOC-* | sed 1d`; do
211 echo $REMOVE_CMD $D
212 PRUNED="$PRUNED $D"
213 done
214 for D in `ls -1t $BUILD/src/emacs-$VERSION.* | sed 1d`; do
215 echo $REMOVE_CMD $D
216 PRUNED="$PRUNED $D"
217 done
218 fi
219
220 test x"$PRUNE" = xonly && exit 0
221
222 maybe_emit_copy ()
223 {
224 if test "$FORCE" = yes || ! cmp -s $1 $2; then
225 echo $LINK_CMD $1 $2
226 fi
227 }
228
229 maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs
230 maybe_emit_copy $BUILD/src/emacs $DST_BIN/emacs-$VERSION
231
232 for F in $PUBLIC_LIBSRC_BINARIES; do
233 maybe_emit_copy $BUILD/lib-src/$F $DST_BIN/$F
234 done
235 for F in $PUBLIC_LIBSRC_SCRIPTS; do
236 maybe_emit_copy $SRC/lib-src/$F $DST_BIN/$F
237 done
238
239 if test x"$SRC" = x"$BUILD"; then
240 PFXS="$BUILD"
241 else
242 PFXS="$SRC $BUILD"
243 fi
244
245 for SUBDIR in lisp leim etc lib-src info; do
246 # defaults
247 SHARED=no
248 FORCED=''
249 AVOID_PAT="`echo "($AVOID)" | tr ' ' '|'`"
250
251 # Set subdir-specific values
252 case $SUBDIR in
253 lisp|leim)
254 DST="$DST_SHARE/$SUBDIR"
255 ;;
256 etc)
257 DST="$DST_SHARE/$SUBDIR"
258 # COPYING is in the avoid list, but there should be a copy of it in
259 # the install etc dir, so make that here.
260 FORCED="$DST/COPYING"
261 ;;
262 lib-src)
263 DST="$DST_LIBEXEC"
264 AVOID_PAT="`echo "($AVOID ($PUBLIC_LIBSRC_BINARIES $PUBLIC_LIBSRC_SCRIPTS)\$)" | tr ' ' '|'`"
265 ;;
266 info)
267 DST="$DST_INFO"
268 SHARED=yes
269 ;;
270 esac
271
272 for PFX in $PFXS; do
273 if [ -d $PFX/$SUBDIR ]; then
274 for DIR in `(cd $PFX/$SUBDIR; find . -type d -print | sed 's@^./@@')`; do
275 if [ -d $DST/$DIR ]; then
276 echo Directory $DST/$DIR exists
277 else
278 echo Directory $DST/$DIR non-existant
279 if [ "`echo $DIR | egrep -v "$AVOID_PAT"`" ]; then
280 maybe_mkdir $DST/$DIR
281 fi
282 fi
283 done
284 diff -sqr $PFX/$SUBDIR $DST
285 fi
286 done | $NAWK '
287 BEGIN {
288 src_pat = "^'"$SRC"'/'"$SUBDIR"'/"
289 build_pat = "^'"$BUILD"'/'"$SUBDIR"'/"
290 dst_pat = "^'"$DST"'/"
291 dst_pfx = "'"$DST"'/"
292 avoid_pat = "'"$AVOID_PAT"'"
293 force = ("'"$FORCE"'" == "yes")
294 shared = ("'"$SHARED"'" == "yes")
295 init_bool_array(pruned, "'"$PRUNED"'")
296 init_bool_array(forced, "'"$FORCED"'")
297 }
298 function init_bool_array(array, string, a,k)
299 {
300 split (string, a)
301 for (k in a)
302 array[a[k]] = 1
303 }
304 function install(src, dst)
305 {
306 if (! (src in pruned)) {
307 cp[src] = dst;
308 from[dst] = src;
309 delete rm[dst];
310 }
311 }
312 function update(src, dst, copy)
313 {
314 if (src in pruned) {
315 rm[dst] = 1;
316 delete from[dst]
317 } else {
318 if (copy)
319 cp[src] = dst;
320 from[dst] = src;
321 delete rm[dst];
322 }
323 }
324 function uninstall(dst)
325 {
326 if (!(dst in from))
327 rm[dst] = 1;
328 }
329 /^Directory / {
330 if ($2 ~ avoid_pat) {
331 if ($NF == "exists")
332 uninstall($2)
333 } else
334 update(0, $2, 0)
335 next
336 }
337 /^Files / {
338 if ($4 ~ avoid_pat && !($4 in forced))
339 uninstall($4)
340 else if ($NF == "identical")
341 update($2, $4, force)
342 else
343 update($2, $4, 1)
344 next
345 }
346 /^Only / {
347 pfx = $3
348 sub (/:$/, "/", pfx)
349
350 if (pfx ~ dst_pat) {
351 if (! shared)
352 uninstall(pfx $4)
353 } else {
354 subdir = pfx
355 if (subdir ~ src_pat)
356 sub (src_pat, "", subdir)
357 else
358 sub (build_pat, "", subdir)
359
360 dst = dst_pfx subdir $4
361 if (! (dst ~ avoid_pat))
362 install(pfx $4, dst)
363 }
364 next
365 }
366 END {
367 for (f in rm)
368 print "'"$REMOVE_CMD"' " f
369 for (f in cp)
370 print "'"$LINK_CMD"' " f " " cp[f]
371 }
372 '
373 done
374
375 ) | eval $EXEC
376
377 # arch-tag: 9322b572-9755-4cf7-a67a-21e6505f1477