Subject: Re: bug#2151: 23.0.90; Building the 23.0.90 pretest recompiles Lisp files

From: Stefan Monnier <[email-masked]>
Date: Mon, 02 Feb 2009 11:02:49 -0500

> Building the pretest recompiles many Lisp files, which it shouldn't IMO.
> Looking at the Makefile's, I think the problem is in this snippet from
> src/Makefile.in (near the end):

>   /* Since the .el.elc rule cannot specify an extra dependency, we do it here.  */
>   ${lisp} ${SOME_MACHINE_LISP}: $(BOOTSTRAPEMACS)

>   ${lispsource}loaddefs.el: $(BOOTSTRAPEMACS)
> 	  cd ../lisp; $(MAKE) $(MFLAGS) autoloads EMACS=../src/bootstrap-emacs${EXEEXT}

>   /* Dump an Emacs executable named bootstrap-emacs containing the
>      files from loadup.el in source form.  */

>   bootstrap-emacs${EXEEXT}: temacs${EXEEXT}
> 	  cd ../lisp; $(MAKE) $(MFLAGS) update-subdirs
>   #ifdef CANNOT_DUMP
> 	  ln -f temacs${EXEEXT} bootstrap-emacs${EXEEXT}
>   #else
> 	  $(RUN_TEMACS) --batch --load loadup bootstrap
> 	  mv -f emacs${EXEEXT} bootstrap-emacs${EXEEXT}
>   #endif /* ! defined (CANNOT_DUMP) */
> 	  @: Compile some files earlier to speed up further compilation.
> 	  cd ../lisp; $(MAKE) $(MFLAGS) compile-first EMACS=../src/bootstrap-emacs${EXEEXT}

> It goes like this: since temacs is built, the last rule says to
> produce bootstrap-emacs${EXEEXT}.  The new bootstrap-emacs then
> triggers the 2 rules before it, which rebuild loaddefs.el and
> recompile the Lisp files in ${lisp} and ${SOME_MACHINE_LISP}.

I think we have to live with this for now.
Getting make to understand the nature of the dependencies here is pretty
tricky, so you can get it to work right for the tarball or you can get
it to work right for the "cvs update" case, but it's pretty painful
to get it to work right in both cases.

I'd be tempted to remove the .elc files that get rebuilt anyway.
This will bring the two cases closer to each other, which can only help
us waste less time on this.

        Stefan

PS: Part of the problem, as far as I understand it, is that we need
the .elc files to depend on bootstrap-emacs so as to tell `make' to
build bootstrap-emacs when needed, but we don't actually need the .elc
files to be newer than bootstrap-emacs (in some rare cases a newer
bootstrap-emacs will compile the .el differently, but in general it's
not the case).  But `make' doesn't have such a concept of a dependency
that "needs to exist, but doesn't need to be older".

PPS: I guess we could get it to work better if the toplevel Makefile.in
were changed so as to call "cd src; make bootstrap-emacs" first and then
"cd src; make" as a separate step.  E.g. along the lines of the barely
tested patch below.

=== modified file 'Makefile.in'
--- Makefile.in	2009-01-09 16:56:04 +0000
+++ Makefile.in	2009-02-02 16:01:10 +0000
@@ -320,6 +320,12 @@
 # We need to build `emacs' in `src' to compile the *.elc files in `lisp'.
 lisp: src
 
+# These targets should be "${SUBDIR} without `src'".
+lib-src lisp: Makefile FRC
+	cd $@; $(MAKE) all $(MFLAGS)                           \
+	  CC='${CC}' CFLAGS='${CFLAGS}' CPPFLAGS='${CPPFLAGS}' \
+	  LDFLAGS='${LDFLAGS}' MAKE='${MAKE}'
+
 # Pass to src/Makefile.in an additional BOOTSTRAPEMACS variable which
 # is either set to bootstrap-emacs (in case bootstrap-emacs has not been
 # constructed yet) or the empty string (otherwise).
@@ -329,12 +335,16 @@
 # file src/foo.c forces dumping a new bootstrap-emacs, then re-byte-compiling
 # all preloaded elisp files, and only then dump the actual src/emacs, which
 # is not wrong, but is overkill in 99.99% of the cases.
-${SUBDIR}: Makefile FRC
+src: Makefile FRC
 	boot=bootstrap-emacs$(EXEEXT);                         \
-	if [ -x "src/$$boot" ]; then boot=""; fi;                   \
+	if [ ! -x "src/$$boot" ]; then                                     \
+	    cd $@; $(MAKE) all $(MFLAGS)                                   \
+	      CC='${CC}' CFLAGS='${CFLAGS}' CPPFLAGS='${CPPFLAGS}'         \
+	      LDFLAGS='${LDFLAGS}' MAKE='${MAKE}' BOOTSTRAPEMACS="$$boot"; \
+	fi;                                                                \
 	cd $@; $(MAKE) all $(MFLAGS)                           \
 	  CC='${CC}' CFLAGS='${CFLAGS}' CPPFLAGS='${CPPFLAGS}' \
-	  LDFLAGS='${LDFLAGS}' MAKE='${MAKE}' BOOTSTRAPEMACS="$$boot"
+	  LDFLAGS='${LDFLAGS}' MAKE='${MAKE}' BOOTSTRAPEMACS=""
 
 blessmail: Makefile src FRC
 	cd lib-src; $(MAKE) maybe-blessmail $(MFLAGS) \