quick-install-emacs 9.0 KB

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