[project @ 2002-11-13 12:21:08 by simonmar]
authorsimonmar <unknown>
Wed, 13 Nov 2002 12:21:09 +0000 (12:21 +0000)
committersimonmar <unknown>
Wed, 13 Nov 2002 12:21:09 +0000 (12:21 +0000)
Add support for gcc-style "make bootstrap" which will build the stage
1, 2 and 3 compilers in the same build tree.

The idea is to simplify building a stage 2 or 3 compiler (now you only
need one build tree), and also speed up the build: there's no need to
compile the libraries more than once, because the stage 1 libraries
are used for stages 2 & 3.

In ghc/compiler, the objects and .hi files are now placed in
subdirectories: ghc/compiler/stage1 has the stage1 objects,
ghc/compiler/stage2 has the stage2 objects, etc.

The story from the top-level (fptools) is this:

  make all    works as before (i.e. builds ghc (stage 1),
  libraries, etc.)

  make stage2     builds the stage 2 compiler
  make stage3     builds the stage 3 compiler

  make bootstrap  does 'make all' followed by 'make stage2'
  make bootstrap3 does 'make all' followed by 'make stage2; make stage3'

In ghc/compiler, the story is now:

  make all      works as before (i.e. builds stage 1 only)

  make boot          generate build dirs and dependencies for stage 1
  make boot stage=N  generate build dirs and dependencies for stage N

  make stageN
  make stage=N       builds stage N compiler.  Run it in-place using
    ./stageN/ghc-inplace.

I haven't decided what to do about 'make install' yet, and this still
needs documenting in the Building Guide.  Also, you still get the same
$(GhcHcOpts) for each stage.

Makefile
ghc/compiler/Makefile
mk/boilerplate.mk
mk/config.mk.in
mk/suffix.mk
mk/target.mk

index 3763516..d41c501 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -345,6 +345,18 @@ boot ::
        @echo "Please use \`make all' only from the top-level, or \`make boot' followed"
        @echo "by \`make all' in an individual project subdirectory (ghc, hslibs etc.)."
 
+bootstrap : bootstrap2
+bootstrap2 : all stage2
+bootstrap3 : bootstrap2 stage3
+
+stage2 :
+       $(MAKE) -C ghc/compiler boot stage=2
+       $(MAKE) -C ghc/compiler stage=2
+
+stage3 :
+       $(MAKE) -C ghc/compiler boot stage=3
+       $(MAKE) -C ghc/compiler stage=3
+
 install ::
        @case '${MFLAGS}' in *-[ik]*) x_on_err=0;; *-r*[ik]*) x_on_err=0;; *) x_on_err=1;; esac; \
        for i in $(filter-out $(ProjectsDontInstall), $(SUBDIRS)); do \
index 305399a..550125a 100644 (file)
@@ -1,5 +1,19 @@
 # -----------------------------------------------------------------------------
-# $Id: Makefile,v 1.224 2002/10/09 15:03:48 simonpj Exp $
+# Main ghc/compiler Makefile
+
+# Targets:
+#
+#      all     builds stage1 compiler
+#
+#      boot stage=N   generate build dirs and dependencies for stage N.
+#                     NB. Must be done before 'make stageN'.
+#                     NB. Cannot 'make boot stage=2' until stage1 has
+#                         been built (similarly for stage3).
+#
+#      stage1  (or stage=1) builds stage1 compiler
+#      stage2  (or stage=2) builds stage2 compiler
+#      stage3  (or stage=3) builds stage3 compiler
+#
 
 TOP = ..
 
@@ -11,15 +25,119 @@ endif
 
 include $(TOP)/mk/boilerplate.mk
 
+#-----------------------------------------------------------------------------
+# Counting source code lines
+
 USER_SRCS = $(filter-out $(DERIVED_SRCS),$(SRCS))
 count :
        ./count_lines $(USER_SRCS)
 
 #-----------------------------------------------------------------------------
 # Building ghc different ways (default is just `normal' sequential)
+
 WAYS=$(GhcCompilerWays)
 
 # -----------------------------------------------------------------------------
+# Bootstrapping
+
+# The stage1/stage2/stage3 business is quite delicate.  Here's how it works:
+# 
+#  - the variable $(stage) holds the current stage number.  To build a 
+#    particular stage, you say 'make stage=N' where N is 1, 2, or 3.
+#    N defaults to 1.
+#
+#  - for stage N, object files and .hi files are placed inside 
+#    the directory stageN, in subdirectories as per the sources.
+#
+#  - .hi-boot files are *linked* into the stageN tree, because in GHC 5.05+
+#    the .hi-boot file must reside in the same place as the .hi file.
+#
+#  - we use explicit -o and -ohi options to direct the output from C & 
+#    Haskell compilations.
+#
+#  - we generate a different .depend file for each build.  They need to be
+#    different, because each stage might include different files: stage1
+#    might not include GHCi, for example.  For each stage, a normal .depend
+#    file is generated, and then post-processed to add the correct stageN/
+#    prefix to each object and .hi filename.  The resulting .depend file
+#    is named .depend-$(stage).  See the end of this Makefile for details.
+#
+#  - normal implicit rules don't work any more, because they're of the form
+#
+#        %.o : %.hs 
+#
+#    whereas we really need 
+#
+#       stageN/%.o : %.hs
+#
+#    so suffix.mk now defines the appropriate suffix rules when
+#    $(odir) is set to a non-empty value.  Here we set $(odir) to
+#    stage1, stage2, or stage3.
+#
+#  There are other plausible designs that might work, but each has different
+#  problems:
+#
+#  - using -odir and -hidir: GHC <= 4.08 doesn't support -hidir, and
+#    anyway -odir puts all the objects in one directory (strips off the
+#    subdirectory part), which eventually forces us to use VPATH to find
+#    the sources.  I have a really bad feeling about VPATH.
+#
+#  - invoke make in the stageN subdirectory.  This probably requires VPATH
+#    too.
+#
+#  - create a link tree.  The problem with requiring link trees is that 
+#    Windows doesn't support symbolic links.
+
+boot ::
+       $(MKDIRHIER) stage$(stage)
+       for i in $(ALL_DIRS); do \
+           $(MKDIRHIER) stage$(stage)/$$i; \
+       done
+       for i in */*hi-boot*; do \
+           $(LN_S) -f ../../$$i stage$(stage)/$$i; \
+       done
+
+ifeq "$(stage)" ""
+stage=1
+endif
+
+ifeq "$(stage)" "1"
+HC=$(GHC)
+endif
+
+ifeq "$(stage)" "2"
+HC=$(GHC_STAGE1)
+endif
+
+ifeq "$(stage)" "3"
+HC=$(GHC_STAGE2)
+endif
+
+stage1 :
+       $(MAKE) stage=1
+
+stage2 : 
+       $(MAKE) stage=2
+
+stage3 : 
+       $(MAKE) stage=3
+
+odir=stage$(stage)
+
+SRC_HC_OPTS += $(patsubst %, -i$(odir)/%, $(ALL_DIRS))
+
+HS_OBJS = $(patsubst %, $(odir)/%, $(addsuffix .$(way_)o,$(basename $(HS_SRCS))))
+C_OBJS = $(patsubst %, $(odir)/%, $(addsuffix .$(way_)o,$(basename $(C_SRCS))))
+
+CLEAN_FILES += $(odir)/*/*.hi
+
+ifeq "$(stage)" "1"
+mostlyclean clean distclean maintainer-clean ::
+       $(MAKE) $@ stage=2
+       $(MAKE) $@ stage=3
+endif
+
+# -----------------------------------------------------------------------------
 #              Set HS_PROG
 
 # Note: there have been reports of people running up against the ARG_MAX limit
@@ -30,12 +148,12 @@ WAYS=$(GhcCompilerWays)
 #
 ifneq "$(way)" "dll"
 ifneq "$(TARGETPLATFORM)" "i386-unknown-mingw32"
-HS_PROG=ghc$(_way)-$(ProjectVersion)
+HS_PROG=$(odir)/ghc$(_way)-$(ProjectVersion)
 else
-HS_PROG=ghc$(_way)
+HS_PROG=$(odir)/ghc$(_way)
 endif
 else
-HS_PROG=ghc-$(ProjectVersion)
+HS_PROG=$(odir)/ghc-$(ProjectVersion)
 endif
 
 # -----------------------------------------------------------------------------
@@ -130,9 +248,14 @@ ifeq "$(BootingFromHc)" "YES"
 bootstrapped = YES
 compiling_with_4xx=NO
 else
+ifneq "$(findstring $(stage), 2 3)" ""
+bootstrapped = YES
+compiling_with_4xx = NO
+else
 bootstrapped = $(shell if (test $(GhcCanonVersion) -ge $(ProjectVersionInt) -a $(GhcPatchLevel) -ge $(ProjectPatchLevel)); then echo YES; else echo NO; fi)
 compiling_with_4xx = $(shell if (test $(GhcCanonVersion) -lt 500); then echo YES; else echo NO; fi)
 endif
+endif
 
 # Only include GHCi if we're bootstrapping with at least version 411
 ifeq "$(GhcWithInterpreter) $(bootstrapped)" "YES YES"
@@ -161,21 +284,9 @@ SRC_MKDEPENDC_OPTS += -D__GLASGOW_HASKELL__=$(ProjectVersionInt) -I$(GHC_INCLUDE
 # -----------------------------------------------------------------------------
 #              Haskell compilations
 
-#
-# Compiler to use for building ghc, use the build tree
-# driver when booting.
-#
-HC=$(GHC)
-
-# magic from GNU make manual to convert a list of values
-# into a colon-separated list
-empty:=
-space:= $(empty) $(empty)
-
 SRC_HC_OPTS += \
   -cpp -fglasgow-exts -Rghc-timing \
-  -I. -IcodeGen -InativeGen -Iparser \
-  $(patsubst %, -i%, $(ALL_DIRS))
+  -I. -IcodeGen -InativeGen -Iparser
 
 # Omitted:     -I$(GHC_INCLUDE_DIR)
 # We should have -I$(GHC_INCLUDE_DIR) in SRC_HC_OPTS, 
@@ -344,15 +455,18 @@ SRC_LD_OPTS += -no-link-chk
 # -----------------------------------------------------------------------------
 # create ghc-inplace, a convenient way to run ghc from the build tree...
 
-all :: ghc-inplace
+all :: $(odir)/ghc-inplace ghc-inplace
 
-ghc-inplace : $(HS_PROG)
+$(odir)/ghc-inplace : $(HS_PROG)
        @$(RM) $@
        echo '#!/bin/sh' >>$@
        echo exec $(FPTOOLS_TOP_ABS)/ghc/compiler/$(HS_PROG) '-B$(subst \,\\,$(FPTOOLS_TOP_ABS_PLATFORM))' '"$$@"' >>$@
        chmod 755 $@
 
-CLEAN_FILES += ghc-inplace
+ghc-inplace : stage1/ghc-inplace
+       $(LN_S) $< $@
+
+CLEAN_FILES += $(odir)/ghc-inplace ghc-inplace
 
 #-----------------------------------------------------------------------------
 #              install
@@ -391,4 +505,23 @@ MAINTAINER_CLEAN_FILES += parser/Parser.info main/ParsePkgConf.info
 #-----------------------------------------------------------------------------
 #              Include target-rule boilerplate
 
+# Don't use the default MKDEPENDHS stuff... we'll do our own, below
+MKDEPENDHS_SRCS =
+MKDEPENDC_SRCS =
+
 include $(TOP)/mk/target.mk
+
+# -----------------------------------------------------------------------------
+# Dependencies
+
+MKDEPENDHS_HC_OPTS = $(shell echo $(HC_OPTS) | sed -e s@$(odir)/@@g)
+
+MKDEPENDHS=$(HC)
+
+# Must do this *after* including target.mk, because $(HS_SRCS) isn't set yet.
+depend :: $(HS_SRCS) $(C_SRCS)
+       $(MKDEPENDHS) -M -optdep-f -optdep.depend-BASE $(foreach way,$(WAYS),-optdep-s -optdep$(way)) $(foreach obj,$(MKDEPENDHS_OBJ_SUFFICES),-osuf $(obj)) $(MKDEPENDHS_OPTS) $(filter-out -split-objs, $(MKDEPENDHS_HC_OPTS)) $(HS_SRCS)
+       $(MKDEPENDC) -f .depend-BASE $(MKDEPENDC_OPTS) $(foreach way,$(WAYS),-s $(way)) -- $(CC_OPTS) -- $(C_SRCS) 
+       $(PERL) -pe 's@^(\S*\.o)@stage$(stage)/$$1@g; s@(\S*\.hi)@stage$(stage)/$$1@g' <.depend-BASE >.depend-$(stage)
+
+-include .depend-$(stage)
index 145f6ee..3790d7e 100644 (file)
@@ -61,9 +61,6 @@ include $(TOP)/mk/opts.mk
 # Variables that control the option flags for all the
 # language processors
 
-include $(TOP)/mk/suffix.mk
-# Suffix rules for Haskell, C and literate 
-
 ifeq "$(BootingFromHc)" "YES"
 include $(TOP)/mk/bootstrap.mk
 endif
index 4e8790f..e693b2d 100644 (file)
@@ -646,6 +646,9 @@ MKDEPENDHS  = $(GHC)
 # tree).  We can refer to "this ghc" as $(GHC_INPLACE):
 
 GHC_INPLACE    = $(FPTOOLS_TOP)/ghc/compiler/ghc-inplace
+GHC_STAGE1     = $(FPTOOLS_TOP)/ghc/compiler/stage1/ghc-inplace
+GHC_STAGE2     = $(FPTOOLS_TOP)/ghc/compiler/stage2/ghc-inplace
+GHC_STAGE3     = $(FPTOOLS_TOP)/ghc/compiler/stage3/ghc-inplace
 
 #-----------------------------------------------------------------------------
 # C compiler
index ade0255..96834fc 100644 (file)
@@ -41,40 +41,48 @@ endif
 # this case.
 ifneq "$(BootingFromHc)" "YES"
 
-%.$(way_)o : %.hs
+# The $(odir) support is for building GHC, where we need to build three
+# different versions from the same sources.  See ghc/compiler/Makefile.
+ifneq "$(odir)" ""
+odir_ = $(odir)/
+else
+odir_ =
+endif
+
+$(odir_)%.$(way_)o : %.hs
        $(HC_PRE_OPTS)
-       $(HC) $(HC_OPTS) -c $< -o $@
+       $(HC) $(HC_OPTS) -c $< -o $@  -ohi $(basename $@).$(way_)hi
        $(HC_POST_OPTS)
 
-%.$(way_)o : %.lhs      
+$(odir_)%.$(way_)o : %.lhs      
        $(HC_PRE_OPTS)
-       $(HC) $(HC_OPTS) -c $< -o $@
+       $(HC) $(HC_OPTS) -c $< -o $@  -ohi $(basename $@).$(way_)hi
        $(HC_POST_OPTS)
 
-%.$(way_)hc : %.lhs     
+$(odir_)%.$(way_)hc : %.lhs     
        $(RM) $@
        $(HC) $(HC_OPTS) -C $< -o $@
 
-%.$(way_)hc : %.hs      
+$(odir_)%.$(way_)hc : %.hs      
        $(RM) $@
        $(HC) $(HC_OPTS) -C $< -o $@
 
-%.$(way_)o : %.$(way_)hc 
+$(odir_)%.$(way_)o : %.$(way_)hc 
        $(HC_PRE_OPTS)
        $(HC) $(HC_OPTS) -c $< -o $@
        $(HC_POST_OPTS)
 
-%.$(way_)o : %.hc 
+$(odir_)%.$(way_)o : %.hc 
        $(HC_PRE_OPTS)
        $(HC) $(HC_OPTS) -c $< -o $@
        $(HC_POST_OPTS)
 
-%.$(way_)s : %.$(way_)hc 
+$(odir_)%.$(way_)s : %.$(way_)hc 
        $(HC_PRE_OPTS)
        $(HC) $(HC_OPTS) -S $< -o $@
        $(HC_POST_OPTS)
 
-%.$(way_)hc : %.lhc
+$(odir_)%.$(way_)hc : %.lhc
        @$(RM) $@
        $(UNLIT) $< $@
        @chmod 444 $@
@@ -95,7 +103,7 @@ ifneq "$(BootingFromHc)" "YES"
        else exit 0 ; \
        fi                                                      
 
-%.$(way_)hi : %.$(way_)hc
+$(odir_)%.$(way_)hi : %.$(way_)hc
        @if [ ! -f $@ ] ; then \
            echo Panic! $< exists, but $@ does not.; \
            exit 1; \
@@ -151,37 +159,37 @@ endif
 
 ifeq "$(UseGhcForCc)" "YES"
 
-%.$(way_)o : %.$(way_)s
+$(odir_)%.$(way_)o : %.$(way_)s
        @$(RM) $@
        $(HC) $(GHC_CC_OPTS) -c $< -o $@
 
-%.$(way_)o : %.c
+$(odir_)%.$(way_)o : %.c
        @$(RM) $@
        $(HC) $(GHC_CC_OPTS) -c $< -o $@
 
-%.$(way_)o : %.S
+$(odir_)%.$(way_)o : %.S
        @$(RM) $@
        $(HC) $(GHC_CC_OPTS) -c $< -o $@
 
-%.$(way_)s : %.c
+$(odir_)%.$(way_)s : %.c
        @$(RM) $@
        $(HC) $(GHC_CC_OPTS) -S $< -o $@
 
 else
 
-%.$(way_)o : %.$(way_)s
+$(odir_)%.$(way_)o : %.$(way_)s
        @$(RM) $@
        $(AS) $(AS_OPTS) -o $@ $<
 
-%.$(way_)o : %.c
+$(odir_)%.$(way_)o : %.c
        @$(RM) $@
        $(CC) $(CC_OPTS) -c $< -o $@
 
-%.$(way_)o : %.S
+$(odir_)%.$(way_)o : %.S
        @$(RM) $@
        $(CC) $(CC_OPTS) -c $< -o $@
 
-%.$(way_)s : %.c
+$(odir_)%.$(way_)s : %.c
        @$(RM) $@
        $(CC) $(CC_OPTS) -S $< -o $@
 
index baaaeb3..252d331 100644 (file)
@@ -44,6 +44,11 @@ PRE_SRCS := $(ALL_SRCS)
 
 include $(TOP)/mk/package.mk
 
+###################################################################
+# Suffix rules for Haskell, C and literate 
+
+include $(TOP)/mk/suffix.mk
+
 ##################################################################
 #              FPtools standard targets
 #