quick-install-emacs 9.2 KB

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