| # 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. |
| |
| STAGES = 0 1 2 3 |
| |
| ###################################################################### |
| # Residual auto-configuration |
| ###################################################################### |
| |
| include config.mk |
| |
| ifdef IGNORE_MKFILES |
| MKFILE_DEPS := |
| else |
| OUR_MKFILES := Makefile config.mk $(wildcard $(CFG_SRC_DIR)/mk/*.mk) |
| 3RDPARTY_MKFILES := $(CFG_SRC_DIR)/src/libuv/Makefile \ |
| $(wildcard $(CFG_SRC_DIR)/src/libuv/*.mk) |
| GEN_MKFILES := $(wildcard $(CFG_SRC_DIR)/mk/libuv/*/*/*) \ |
| $(wildcard $(CFG_SRC_DIR)/mk/libuv/mac/src/libuv/*) \ |
| $(wildcard $(CFG_SRC_DIR)/mk/libuv/mac/src/libuv/*) \ |
| $(wildcard $(CFG_SRC_DIR)/mk/libuv/mac/src/libuv/*) |
| MKFILE_DEPS := $(OUR_MKFILES) $(3RDPARTY_MKFILES) $(GEN_MKFILES) |
| endif |
| |
| NON_HOST_TRIPLES = $(filter-out $(CFG_HOST_TRIPLE),$(CFG_TARGET_TRIPLES)) |
| |
| ifneq ($(MAKE_RESTARTS),) |
| CFG_INFO := $(info cfg: make restarts: $(MAKE_RESTARTS)) |
| endif |
| |
| CFG_INFO := $(info cfg: shell host triple $(CFG_HOST_TRIPLE)) |
| CFG_INFO := $(info cfg: non host triples $(NON_HOST_TRIPLES)) |
| |
| 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 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_CORELIB :=$(call CFG_LIB_NAME,core) |
| CFG_STDLIB :=$(call CFG_LIB_NAME,std) |
| CFG_LIBRUSTC :=$(call CFG_LIB_NAME,rustc) |
| |
| STDLIB_GLOB :=$(call CFG_LIB_GLOB,std) |
| CORELIB_GLOB :=$(call CFG_LIB_GLOB,core) |
| LIBRUSTC_GLOB :=$(call CFG_LIB_GLOB,rustc) |
| |
| # version-string calculation |
| CFG_GIT_DIR := $(CFG_SRC_DIR).git |
| CFG_RELEASE = 0.1 |
| CFG_VERSION = $(CFG_RELEASE) |
| |
| 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 |
| |
| |
| ###################################################################### |
| # 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.% |
| |
| ###################################################################### |
| # Core library variables |
| ###################################################################### |
| |
| CORELIB_CRATE := $(S)src/libcore/core.rc |
| CORELIB_INPUTS := $(wildcard $(addprefix $(S)src/libcore/, \ |
| core.rc *.rs */*.rs)) |
| |
| ###################################################################### |
| # Standard library variables |
| ###################################################################### |
| |
| STDLIB_CRATE := $(S)src/libstd/std.rc |
| STDLIB_INPUTS := $(wildcard $(addprefix $(S)src/libstd/, \ |
| std.rc *.rs */*.rs)) |
| |
| ###################################################################### |
| # rustc crate variables |
| ###################################################################### |
| |
| COMPILER_CRATE := $(S)src/comp/rustc.rc |
| COMPILER_INPUTS := $(filter-out $(S)src/comp/driver/rustc.rs, \ |
| $(wildcard $(addprefix $(S)src/comp/, \ |
| rustc.rc *.rs */*.rs */*/*.rs))) |
| |
| RUSTC_INPUTS := $(S)src/comp/driver/rustc.rs |
| |
| ###################################################################### |
| # LLVM macros |
| ###################################################################### |
| |
| # FIXME: x86-ism |
| LLVM_COMPONENTS=x86 ipo bitreader bitwriter linker asmparser |
| |
| define DEF_LLVM_VARS |
| # The configure script defines these variables with the target triples |
| # separated by Z. This defines new ones with the expected format. |
| CFG_LLVM_BUILD_DIR_$(1):=$$(CFG_LLVM_BUILD_DIR_$(subst -,_,$(1))) |
| CFG_LLVM_INST_DIR_$(1):=$$(CFG_LLVM_INST_DIR_$(subst -,_,$(1))) |
| |
| # Any rules that depend on LLVM should depend on LLVM_CONFIG |
| LLVM_CONFIG_$(1):=$$(CFG_LLVM_INST_DIR_$(1))/bin/llvm-config$$(X) |
| LLVM_MC_$(1):=$$(CFG_LLVM_INST_DIR_$(1))/bin/llvm-mc$$(X) |
| LLVM_VERSION_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --version) |
| LLVM_BINDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --bindir) |
| LLVM_INCDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --includedir) |
| LLVM_LIBDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --libdir) |
| LLVM_LIBS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --libs $$(LLVM_COMPONENTS)) |
| LLVM_LDFLAGS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --ldflags) |
| LLVM_CXXFLAGS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --cxxflags) |
| LLVM_HOST_TRIPLE_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --host-target) |
| |
| LLVM_AS_$(1)=$$(CFG_LLVM_INST_DIR_$(1))/bin/llvm-as$$(X) |
| LLC_$(1)=$$(CFG_LLVM_INST_DIR_$(1))/bin/llc$$(X) |
| |
| endef |
| |
| $(foreach target,$(CFG_TARGET_TRIPLES), \ |
| $(eval $(call DEF_LLVM_VARS,$(target)))) |
| |
| ###################################################################### |
| # 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 |
| export CFG_LIBDIR |
| |
| ###################################################################### |
| # Subprograms |
| ###################################################################### |
| |
| ###################################################################### |
| # Per-stage targets and runner |
| ###################################################################### |
| |
| define SREQ |
| # $(1) is the stage number |
| # $(2) is the target triple |
| # $(3) is the host triple |
| |
| # Destinations of artifacts for the host compiler |
| HROOT$(1)_H_$(3) = $(3)/stage$(1) |
| HBIN$(1)_H_$(3) = $$(HROOT$(1)_H_$(3))/bin |
| HLIB$(1)_H_$(3) = $$(HROOT$(1)_H_$(3))/$$(CFG_LIBDIR) |
| |
| # Destinations of artifacts for target architectures |
| TROOT$(1)_T_$(2)_H_$(3) = $$(HLIB$(1)_H_$(3))/rustc/$(2) |
| TBIN$(1)_T_$(2)_H_$(3) = $$(TROOT$(1)_T_$(2)_H_$(3))/bin |
| TLIB$(1)_T_$(2)_H_$(3) = $$(TROOT$(1)_T_$(2)_H_$(3))/$$(CFG_LIBDIR) |
| |
| # The name of the core and standard libraries used by rustc |
| ifdef CFG_DISABLE_SHAREDSTD |
| HCORELIB_DEFAULT$(1)_H_$(3) = \ |
| $$(HLIB$(1)_H_$(3))/libcore.rlib |
| TCORELIB_DEFAULT$(1)_T_$(2)_H_$(3) = \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/libcore.rlib |
| |
| HSTDLIB_DEFAULT$(1)_H_$(3) = \ |
| $$(HLIB$(1)_H_$(3))/libstd.rlib |
| TSTDLIB_DEFAULT$(1)_T_$(2)_H_$(3) = \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/libstd.rlib |
| |
| HLIBRUSTC_DEFAULT$(1)_H_$(3) = \ |
| $$(HLIB$(1)_H_$(3))/librustc.rlib |
| TLIBRUSTC_DEFAULT$(1)_T_$(2)_H_$(3) = \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/librustc.rlib |
| else |
| HCORELIB_DEFAULT$(1)_H_$(3) = \ |
| $$(HLIB$(1)_H_$(3))/$(CFG_CORELIB) |
| TCORELIB_DEFAULT$(1)_T_$(2)_H_$(3) = \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_CORELIB) |
| |
| HSTDLIB_DEFAULT$(1)_H_$(3) = \ |
| $$(HLIB$(1)_H_$(3))/$(CFG_STDLIB) |
| TSTDLIB_DEFAULT$(1)_T_$(2)_H_$(3) = \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB) |
| |
| HLIBRUSTC_DEFAULT$(1)_H_$(3) = \ |
| $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTC) |
| TLIBRUSTC_DEFAULT$(1)_T_$(2)_H_$(3) = \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC) |
| endif |
| |
| # Preqrequisites for using the stageN compiler |
| HSREQ$(1)_H_$(3) = \ |
| $$(HBIN$(1)_H_$(3))/rustc$$(X) \ |
| $$(HLIB$(1)_H_$(3))/$$(CFG_RUNTIME) \ |
| $$(HLIB$(1)_H_$(3))/$$(CFG_RUSTLLVM) \ |
| $$(HCORELIB_DEFAULT$(1)_H_$(3)) \ |
| $$(HSTDLIB_DEFAULT$(1)_H_$(3)) \ |
| $$(HLIBRUSTC_DEFAULT$(1)_H_$(3)) \ |
| $$(MKFILE_DEPS) |
| |
| # Prerequisites for using the stageN compiler to build target artifacts |
| TSREQ$(1)_T_$(2)_H_$(3) = \ |
| $$(HSREQ$(1)_H_$(3)) \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_RUNTIME) \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/intrinsics.bc \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a |
| |
| # Prerequisites for complete stageN targets |
| SREQ$(1)_T_$(2)_H_$(3) = \ |
| $$(TSREQ$(1)_T_$(2)_H_$(3)) \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_CORELIB) \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB) \ |
| $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC) |
| |
| 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)_T_$(2)_H_$(3) := \ |
| $$(Q)$$(call CFG_RUN_TARG,$(1), \ |
| $$(CFG_VALGRIND_COMPILE$(1)) \ |
| $$(HBIN$(1)_H_$(3))/rustc$$(X) \ |
| $$(CFG_RUSTC_FLAGS) --target=$(2)) |
| |
| PERF_STAGE$(1)_T_$(2)_H_$(3) := \ |
| $$(Q)$$(call CFG_RUN_TARG,$(1), \ |
| $$(CFG_PERF_TOOL) \ |
| $$(HBIN$(1)_H_$(3))/rustc$$(X) \ |
| $$(CFG_RUSTC_FLAGS) --target=$(2)) |
| |
| endef |
| |
| $(foreach build,$(CFG_TARGET_TRIPLES), \ |
| $(eval $(foreach target,$(CFG_TARGET_TRIPLES), \ |
| $(eval $(foreach stage,$(STAGES), \ |
| $(eval $(call SREQ,$(stage),$(target),$(build)))))))) |
| |
| ###################################################################### |
| # rustc-H-targets |
| # |
| # Builds a functional Rustc for the given host. |
| ###################################################################### |
| |
| define DEF_RUSTC_STAGE_TARGET |
| # $(1) == architecture |
| # $(2) == stage |
| |
| rustc-stage$(2)-H-$(1): \ |
| $$(foreach target,$$(CFG_TARGET_TRIPLES), \ |
| $$(SREQ$(2)_T_$$(target)_H_$(1))) |
| |
| endef |
| |
| $(foreach host,$(CFG_TARGET_TRIPLES), \ |
| $(eval $(foreach stage,1 2 3, \ |
| $(eval $(call DEF_RUSTC_STAGE_TARGET,$(host),$(stage)))))) |
| |
| rustc-stage1: rustc-stage1-H-$(CFG_HOST_TRIPLE) |
| rustc-stage2: rustc-stage2-H-$(CFG_HOST_TRIPLE) |
| rustc-stage3: rustc-stage3-H-$(CFG_HOST_TRIPLE) |
| |
| define DEF_RUSTC_TARGET |
| # $(1) == architecture |
| |
| rustc-H-$(1): rustc-stage2-H-$(1) |
| endef |
| |
| $(foreach host,$(CFG_TARGET_TRIPLES), \ |
| $(eval $(call DEF_RUSTC_TARGET,$(host)))) |
| |
| rustc-stage1: rustc-stage1-H-$(CFG_HOST_TRIPLE) |
| rustc-stage2: rustc-stage2-H-$(CFG_HOST_TRIPLE) |
| rustc-stage3: rustc-stage3-H-$(CFG_HOST_TRIPLE) |
| rustc: rustc-H-$(CFG_HOST_TRIPLE) |
| |
| rustc-H-all: $(foreach host,$(CFG_TARGET_TRIPLES),rustc-H-$(host)) |
| |
| ###################################################################### |
| # Entrypoint rule |
| ###################################################################### |
| |
| .DEFAULT_GOAL := all |
| |
| 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 |
| |
| TSREQS := \ |
| $(foreach target,$(CFG_TARGET_TRIPLES), \ |
| $(SREQ3_T_$(target)_H_$(CFG_HOST_TRIPLE))) |
| FUZZ := $(HBIN3_H_$(CFG_HOST_TRIPLE))/fuzzer$(X) |
| CARGO := $(HBIN3_H_$(CFG_HOST_TRIPLE))/cargo$(X) |
| RUSTDOC := $(HBIN3_H_$(CFG_HOST_TRIPLE))/rustdoc$(X) |
| |
| all: rustc $(GENERATED) docs $(FUZZ) $(CARGO) $(RUSTDOC) |
| |
| endif |
| |
| |
| ###################################################################### |
| # Re-configuration |
| ###################################################################### |
| |
| ifndef CFG_DISABLE_MANAGE_SUBMODULES |
| # This is a pretty expensive operation but I don't see any way to avoid it |
| NEED_GIT_RECONFIG=$(shell cd "$(CFG_SRC_DIR)" && "$(CFG_GIT)" submodule status | grep -c '^\(+\|-\)') |
| else |
| NEED_GIT_RECONFIG=0 |
| endif |
| |
| 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 |