# An explanation of how the build is structured: # # There are multiple build stages (0-3) needed to verify that the # compiler is properly self-hosting. Each stage is divided between # 'host' artifacts and 'target' artifacts, where the stageN host # compiler builds artifacts for 1 or more stageN target architectures. # Once the stageN target compiler has been built for the host # architecture it is promoted (copied) to a stageN+1 host artifact. # # The stage3 host compiler is a compiler that successfully builds # itself and should (in theory) be bitwise identical to the stage2 # host compiler. The process is bootstrapped using a stage0 host # compiler downloaded from a previous snapshot. # # At no time should stageN artifacts be interacting with artifacts # from other stages. For consistency, we use the 'promotion' logic # for all artifacts, even those that don't make sense on non-host # architectures. # # The directory layout for a stage is intended to match the layout # of the installed compiler, and looks like the following: # # stageN - this is the system root, corresponding to, e.g. /usr # bin - binaries compiled for the host # lib - libraries used by the host compiler # rustc - rustc's own place to organize libraries # $(target) - target-specific artifacts # bin - binaries for target architectures # lib - libraries for target architectures # # A note about host libraries: # # The only libraries that get promoted to stageN/lib are those needed # by rustc. In general, rust programs, even those compiled for the # host architecture will use libraries from the target # directories. This gives rust some freedom to experiment with how # libraries are managed and versioned without polluting the common # areas of the filesystem. # # General rust binaries may stil live in the host bin directory; they # will just link against the libraries in the target lib directory. # # Admittedly this is a little convoluted. ###################################################################### # Residual auto-configuration ###################################################################### include config.mk OUR_MKFILES := Makefile config.mk $(wildcard $(CFG_SRC_DIR)/mk/*.mk) 3RDPARTY_MKFILES := $(CFG_SRC_DIR)/src/rt/libuv/Makefile \ $(wildcard $(CFG_SRC_DIR)/src/rt/libuv/*.mk) GEN_MKFILES := $(wildcard $(CFG_SRC_DIR)/mk/libuv/*/*/*) \ $(wildcard $(CFG_SRC_DIR)/mk/libuv/mac/src/rt/libuv/*) \ $(wildcard $(CFG_SRC_DIR)/mk/libuv/mac/src/rt/libuv/*) \ $(wildcard $(CFG_SRC_DIR)/mk/libuv/mac/src/rt/libuv/*) MKFILES := $(OUR_MKFILES) $(3RDPARTY_MKFILES) $(GEN_MKFILES) ifneq ($(MAKE_RESTARTS),) CFG_INFO := $(info cfg: make restarts: $(MAKE_RESTARTS)) endif CFG_INFO := $(info cfg: shell host triple $(CFG_HOST_TRIPLE)) ifdef CFG_DISABLE_OPTIMIZE $(info cfg: disabling rustc optimization (CFG_DISABLE_OPTIMIZE)) CFG_RUSTC_FLAGS := else CFG_RUSTC_FLAGS := -O endif ifdef SAVE_TEMPS CFG_RUSTC_FLAGS += --save-temps endif ifdef TIME_PASSES CFG_RUSTC_FLAGS += --time-passes endif ifdef TIME_LLVM_PASSES CFG_RUSTC_FLAGS += --time-llvm-passes endif ifdef NO_TYPESTATE CFG_RUSTC_FLAGS += --no-typestate endif ifdef DEBUG CFG_RUSTC_FLAGS += -g endif # platform-specific auto-configuration include $(CFG_SRC_DIR)/mk/platform.mk # Run the stage1/2 compilers under valgrind ifdef VALGRIND_COMPILE CFG_VALGRIND_COMPILE :=$(CFG_VALGRIND) else CFG_VALGRIND_COMPILE := endif CFG_RUNTIME :=$(call CFG_LIB_NAME,rustrt) CFG_RUSTLLVM :=$(call CFG_LIB_NAME,rustllvm) CFG_STDLIB :=$(call CFG_LIB_NAME,ruststd) CFG_LIBRUSTC :=$(call CFG_LIB_NAME,rustc) # version-string calculation CFG_GIT_DIR := $(CFG_SRC_DIR).git CFG_VERSION = prerelease ifneq ($(wildcard $(CFG_GIT)),) ifneq ($(wildcard $(CFG_GIT_DIR)),) CFG_VERSION += $(shell git --git-dir=$(CFG_GIT_DIR) log -1 \ --pretty=format:'(%h %ci)') endif endif ifdef CFG_DISABLE_VALGRIND $(info cfg: disabling valgrind (CFG_DISABLE_VALGRIND)) CFG_VALGRIND := endif ifdef CFG_BAD_VALGRIND $(info cfg: disabling valgrind due to its unreliability on this platform) CFG_VALGRIND := endif DOCS := ifeq ($(CFG_MAKEINFO),) $(info cfg: no makeinfo found, omitting doc/rust.html) else DOCS += doc/rust.html endif ifeq ($(CFG_TEXI2PDF),) $(info cfg: no texi2pdf found, omitting doc/rust.pdf) else ifeq ($(CFG_TEX),) $(info cfg: no tex found, omitting doc/rust.pdf) else DOCS += doc/rust.pdf endif endif ifeq ($(CFG_NATURALDOCS),) $(info cfg: no naturaldocs found, omitting doc/std/index.html) else DOCS += doc/std/index.html endif ifdef CFG_DISABLE_DOCS $(info cfg: disabling doc build (CFG_DISABLE_DOCS)) DOCS := endif ###################################################################### # Target-and-rule "utility variables" ###################################################################### ifdef VERBOSE Q := E = else Q := @ E = echo $(1) endif S := $(CFG_SRC_DIR) X := $(CFG_EXE_SUFFIX) # Look in doc and src dirs. VPATH := $(S)doc $(S)src # "Source" files we generate in builddir along the way. GENERATED := # Delete the built-in rules. .SUFFIXES: %:: %,v %:: RCS/%,v %:: RCS/% %:: s.% %:: SCCS/s.% ###################################################################### # Standard library variables ###################################################################### STDLIB_CRATE := $(S)src/lib/std.rc STDLIB_INPUTS := $(wildcard $(addprefix $(S)src/lib/,*.rc *.rs */*.rs)) ###################################################################### # rustc crate variables ###################################################################### COMPILER_CRATE := $(S)src/comp/rustc.rc COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/comp/, \ rustc.rc *.rs */*.rs */*/*.rs)) ###################################################################### # LLVM macros ###################################################################### LLVM_CONFIG:=$(CFG_LLVM_INST_DIR)/bin/llvm-config LLVM_VERSION=$(shell "$(LLVM_CONFIG)" --version) LLVM_BINDIR=$(shell "$(LLVM_CONFIG)" --bindir) LLVM_INCDIR=$(shell "$(LLVM_CONFIG)" --includedir) LLVM_LIBDIR=$(shell "$(LLVM_CONFIG)" --libdir) LLVM_LIBS=$(shell "$(LLVM_CONFIG)" --libs) LLVM_LDFLAGS=$(shell "$(LLVM_CONFIG)" --ldflags) LLVM_CXXFLAGS=$(shell "$(LLVM_CONFIG)" --cxxflags) LLVM_HOST_TRIPLE=$(shell "$(LLVM_CONFIG)" --host-target) LLVM_AS=$(CFG_LLVM_BINDIR)/llvm-as$(X) LLC=$(CFG_LLVM_BINDIR)/llc$(X) ###################################################################### # Exports for sub-utilities ###################################################################### # Note that any variable that re-configure should pick up needs to be # exported export CFG_SRC_DIR export CFG_BUILD_DIR export CFG_VERSION export CFG_HOST_TRIPLE export CFG_LLVM_ROOT export CFG_ENABLE_MINGW_CROSS export CFG_PREFIX ###################################################################### # Subprograms ###################################################################### ###################################################################### # Per-stage targets and runner ###################################################################### define SREQ # Destinations of artifacts for the host compiler HOST_ROOT$(1) = stage$(1) HOST_BIN$(1) = $$(HOST_ROOT$(1))/bin HOST_LIB$(1) = $$(HOST_ROOT$(1))/lib # Destinations of artifacts for target architectures TARGET_ROOT$(1)$(2) = $$(HOST_LIB$(1))/rustc/$(2) TARGET_BIN$(1)$(2) = $$(TARGET_ROOT$(1)$(2))/bin TARGET_LIB$(1)$(2) = $$(TARGET_ROOT$(1)$(2))/lib # The target locations of artifacts for the host architecture (used for # promoting target binaries to host binaries) TARGET_HOST_ROOT$(1) = $$(TARGET_ROOT$(1)$$(CFG_HOST_TRIPLE)) TARGET_HOST_BIN$(1) = $$(TARGET_BIN$(1)$$(CFG_HOST_TRIPLE)) TARGET_HOST_LIB$(1) = $$(TARGET_LIB$(1)$$(CFG_HOST_TRIPLE)) # The name of the standard library used by rustc ifdef CFG_DISABLE_SHAREDSTD HOST_STDLIB_DEFAULT$(1) = $$(HOST_LIB$(1))/libstd.rlib TARGET_STDLIB_DEFAULT$(1)$(2) = $$(TARGET_LIB$(1)$(2))/libstd.rlib else HOST_STDLIB_DEFAULT$(1) = $$(HOST_LIB$(1))/$(CFG_STDLIB) TARGET_STDLIB_DEFAULT$(1)$(2) = $$(TARGET_LIB$(1)$(2))/$(CFG_STDLIB) endif # Preqrequisites for using the stageN compiler HOST_SREQ$(1) = \ $$(HOST_BIN$(1))/rustc$$(X) \ $$(HOST_LIB$(1))/$$(CFG_RUNTIME) \ $$(HOST_LIB$(1))/$$(CFG_RUSTLLVM) \ $$(HOST_STDLIB_DEFAULT$(1)) \ $$(MKFILES) # Prerequisites for using the stageN compiler to build target artifacts TARGET_SREQ$(1)$(2) = \ $$(HOST_SREQ$(1)) \ $$(TARGET_LIB$(1)$(2))/$$(CFG_RUNTIME) \ $$(TARGET_LIB$(1)$(2))/intrinsics.bc # Prerequisites for complete stageN targets SREQ$(1)$(2) = \ $$(TARGET_SREQ$(1)$(2)) \ $$(TARGET_LIB$(1)$(2))/$$(CFG_STDLIB) ifeq ($(1),0) # Don't run the the stage0 compiler under valgrind - that ship has sailed CFG_VALGRIND_COMPILE$(1) = else CFG_VALGRIND_COMPILE$(1) = $$(CFG_VALGRIND_COMPILE) endif STAGE$(1)_$(2) := $$(Q)$$(call CFG_RUN_TARG,$(1), \ $$(CFG_VALGRIND_COMPILE$(1)) $$(HOST_BIN$(1))/rustc$$(X) \ $$(CFG_RUSTC_FLAGS) --target=$(2)) PERF_STAGE$(1)_$(2) := $$(Q)$$(call CFG_RUN_TARG,$(1), \ $$(CFG_PERF_TOOL) $$(HOST_BIN$(1))/rustc$$(X) \ $$(CFG_RUSTC_FLAGS) --target=$(2)) endef $(foreach target,$(CFG_TARGET_TRIPLES), \ $(eval $(call SREQ,0,$(target))) \ $(eval $(call SREQ,1,$(target))) \ $(eval $(call SREQ,2,$(target))) \ $(eval $(call SREQ,3,$(target)))) ###################################################################### # Entrypoint rule ###################################################################### ifneq ($(CFG_IN_TRANSITION),) CFG_INFO := $(info cfg:) CFG_INFO := $(info cfg: *** compiler is in snapshot transition ***) CFG_INFO := $(info cfg: *** stage2 and later will not be built ***) CFG_INFO := $(info cfg:) all: $(SREQ1$(CFG_HOST_TRIPLE)) $(GENERATED) $(DOCS) else TARGET_SREQS := $(foreach target,$(CFG_TARGET_TRIPLES),$(SREQ3$(target))) FUZZ := $(HOST_BIN3)/fuzzer$(X) #all: $(SREQ3$(CFG_HOST_TRIPLE)) $(GENERATED) $(DOCS) $(FUZZ) all: $(TARGET_SREQS) $(GENERATED) $(DOCS) $(FUZZ) endif ###################################################################### # Re-configuration ###################################################################### # This is a pretty expensive operation but I don't see any way to avoid it SUBMODULE_STATUS=$(shell cd "$(CFG_SRC_DIR)" && "$(CFG_GIT)" submodule status) # Look through for submodules prefixed with '-' (need init), or '+' (need update) NEED_GIT_RECONFIG=$(shell echo "$(SUBMODULE_STATUS)" | grep -c '^\(+\|-\)') ifeq ($(NEED_GIT_RECONFIG),0) else # If the submodules have changed then always execute config.mk .PHONY: config.mk endif config.mk: $(S)configure $(S)Makefile.in $(S)src/snapshots.txt @$(call E, cfg: reconfiguring) $(Q)$(S)configure $(CFG_CONFIGURE_ARGS) ###################################################################### # Primary-target makefiles ###################################################################### include $(CFG_SRC_DIR)/mk/target.mk include $(CFG_SRC_DIR)/mk/host.mk include $(CFG_SRC_DIR)/mk/stage0.mk include $(CFG_SRC_DIR)/mk/rt.mk include $(CFG_SRC_DIR)/mk/rustllvm.mk include $(CFG_SRC_DIR)/mk/autodep.mk include $(CFG_SRC_DIR)/mk/tools.mk include $(CFG_SRC_DIR)/mk/docs.mk include $(CFG_SRC_DIR)/mk/llvm.mk ###################################################################### # Secondary makefiles, conditionalized for speed ###################################################################### ifneq ($(strip $(findstring dist,$(MAKECMDGOALS)) \ $(findstring check,$(MAKECMDGOALS)) \ $(findstring test,$(MAKECMDGOALS)) \ $(findstring tidy,$(MAKECMDGOALS)) \ $(findstring clean,$(MAKECMDGOALS))),) CFG_INFO := $(info cfg: including dist rules) include $(CFG_SRC_DIR)/mk/dist.mk endif ifneq ($(strip $(findstring snap,$(MAKECMDGOALS)) \ $(findstring clean,$(MAKECMDGOALS))),) CFG_INFO := $(info cfg: including snap rules) include $(CFG_SRC_DIR)/mk/snap.mk endif ifneq ($(findstring reformat,$(MAKECMDGOALS)),) CFG_INFO := $(info cfg: including reformat rules) include $(CFG_SRC_DIR)/mk/pp.mk endif ifneq ($(strip $(findstring check,$(MAKECMDGOALS)) \ $(findstring test,$(MAKECMDGOALS)) \ $(findstring perf,$(MAKECMDGOALS)) \ $(findstring tidy,$(MAKECMDGOALS))),) CFG_INFO := $(info cfg: including test rules) include $(CFG_SRC_DIR)/mk/tests.mk endif ifneq ($(findstring perf,$(MAKECMDGOALS)),) CFG_INFO := $(info cfg: including perf rules) include $(CFG_SRC_DIR)/mk/perf.mk endif ifneq ($(findstring clean,$(MAKECMDGOALS)),) CFG_INFO := $(info cfg: including clean rules) include $(CFG_SRC_DIR)/mk/clean.mk endif ifneq ($(findstring install,$(MAKECMDGOALS)),) CFG_INFO := $(info cfg: including install rules) include $(CFG_SRC_DIR)/mk/install.mk endif ifneq ($(strip $(findstring TAGS.emacs,$(MAKECMDGOALS)) \ $(findstring TAGS.vi,$(MAKECMDGOALS))),) CFG_INFO := $(info cfg: including ctags rules) include $(CFG_SRC_DIR)/mk/ctags.mk endif