From b11e73d0be97162904ced06f32f68444041f9ffa Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 13 Feb 2014 21:22:08 -0800 Subject: [PATCH 1/7] mk: Add some serious documentation and 'make help' 'make help' is implemented in a fairly ridiculous way, using awk to parse comments out of Makefile.in and displaying them. --- Makefile.in | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index ef1701a61e80..2bfcd49e7fc4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -8,7 +8,54 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. -# An explanation of how the build is structured: +# +# +# # The Rust Build System +# +# Start with these these build targets: +# +# * all - The default rule. Builds a complete stage2 compiler, std, +# and extra for all hosts and targets +# * docs - Generate HTML documentation for the std and extra libraries +# from source code comments +# * rustc - The stage 2 compiler for the build platform with standard +# and extra libraries +# * install +# * uninstall +# * check - Run tests +# * check-stage1-$(crate) - Run tests for a crate, e.g. `check-stage1-std` +# * check-stage1-rpass - Run the language tests +# * check-docs - Run the doc tests +# +# Then mix in some of these environment variables to harness the +# ultimate power of Rust Build System. +# +# * `VERBOSE=1` - Print all commands. Use this to see what's going on. +# * `RUSTFLAGS=...` - Add compiler flags to all `rustc` invocations +# * `CFG_ENABLE_VALGRIND=1` - Run tests under valgrind +# * `VALGRIND_COMPILE=1` - Run the compiler itself under valgrind +# (may require `CFG_ENABLE_VALGRIND`) +# * `NO_REBUILD=1` - Don't rebootstrap when testing std +# (and possibly other crates) +# * `SAVE_TEMPS=1` - Use `--save-temps` flag on all `rustc` invocations +# * `ASM_COMMENTS=1` - Use `-Z asm-comments` +# * `TIME_PASSES=1` - Use `-Z time-passes` +# * `TIME_LLVM_PASSES=1` - Use `-Z time-llvm-passes` +# * `TRACE=1` - Use `-Z trace` +# +# This is hardly all there is to know of The Rust Build System's +# mysteries. Your journey continues on the wiki[1][2]. +# +# [1]: https://github.com/mozilla/rust/wiki/Note-build-system +# [2]: https://github.com/mozilla/rust/wiki/Note-testsuite +# +# +# +# # An (old) explanation of how the build is structured: +# +# *Note: Hey, like, this is probably inaccurate, and is definitely +# an outdated and insufficient explanation of the remarkable +# and discomfiting Rust Build System.* # # There are multiple build stages (0-3) needed to verify that the # compiler is properly self-hosting. Each stage is divided between @@ -598,3 +645,9 @@ endif # header file dependencies. ALL_DEP_FILES := $(ALL_OBJ_FILES:%.o=%.d) -include $(ALL_DEP_FILES) + +help: +# Show the comments from this file as "help" +# pick everything between tags | remove first line | remove last line +# | remove extra (?) line | strip leading `#` from lines + $(Q)awk '//,/<\/help>/' $(S)/Makefile.in | sed '1d' | sed '$$d' | sed 's/^# \?//' From 94d2c8a21fae1b30340750346d15f6da84a76a87 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 13 Feb 2014 23:25:07 -0800 Subject: [PATCH 2/7] mk: Remove the concept of 'snapshot transitions' This way of doing snapshots hasn't been used since 2011. --- Makefile.in | 14 -------------- configure | 6 ------ 2 files changed, 20 deletions(-) diff --git a/Makefile.in b/Makefile.in index 2bfcd49e7fc4..cc5816b248f0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -518,18 +518,6 @@ rustc-H-all: $(foreach host,$(CFG_HOST),rustc-H-$(host)) .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:) - -#FIXME This is surely busted -all: $(SREQ1$(CFG_BUILD)) $(GENERATED) docs - -else - define ALL_TARGET_N ifneq ($$(findstring $(1),$$(CFG_HOST)),) # This is a host @@ -550,8 +538,6 @@ ALL_TARGET_RULES = $(foreach target,$(CFG_TARGET), \ all: $(ALL_TARGET_RULES) $(GENERATED) docs -endif - ###################################################################### # Re-configuration diff --git a/configure b/configure index b771e3923ce4..de0b7680dcfe 100755 --- a/configure +++ b/configure @@ -1071,12 +1071,6 @@ then putvar CFG_PANDOC fi -if head -n 1 ${CFG_SRC_DIR}src/snapshots.txt | grep -q '^T' -then - CFG_IN_TRANSITION=1 - putvar CFG_IN_TRANSITION -fi - # Valgrind is only reliable on Linux. On Windows it doesn't work at all, and # on the Mac the dynamic linker causes Valgrind to emit a huge stream of # errors. From 2852fea61e51752a0a7f6c2aeb8fe798a2890c4e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 13 Feb 2014 23:55:49 -0800 Subject: [PATCH 3/7] mk: Move most of Makefile.in to .mk files Because the build system treats Makefile.in and the .mk files slightly differently (.in is copied, .mk are included), this makes the system more uniform. Fewer build system changes will require a complete reconfigure. --- Makefile.in | 497 +++---------------------------------------------- mk/main.mk | 431 ++++++++++++++++++++++++++++++++++++++++++ mk/reconfig.mk | 33 ++++ mk/util.mk | 28 +++ 4 files changed, 518 insertions(+), 471 deletions(-) create mode 100644 mk/main.mk create mode 100644 mk/reconfig.mk create mode 100644 mk/util.mk diff --git a/Makefile.in b/Makefile.in index cc5816b248f0..599984623e25 100644 --- a/Makefile.in +++ b/Makefile.in @@ -99,490 +99,45 @@ # # Admittedly this is a little convoluted. -STAGES = 0 1 2 3 - ###################################################################### -# Residual auto-configuration -###################################################################### - -# Recursive wildcard function -# http://blog.jgc.org/2011/07/gnu-make-recursive-wildcard-function.html -rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) \ - $(filter $(subst *,%,$2),$d)) - -include config.mk - -# We track all of the object files we might build so that we can find -# and include all of the .d files in one fell swoop. -ALL_OBJ_FILES := - -MKFILE_DEPS := config.stamp $(call rwildcard,$(CFG_SRC_DIR)mk/,*) -NON_BUILD_HOST = $(filter-out $(CFG_BUILD),$(CFG_HOST)) -NON_BUILD_TARGET = $(filter-out $(CFG_BUILD),$(CFG_TARGET)) - -ifneq ($(MAKE_RESTARTS),) -CFG_INFO := $(info cfg: make restarts: $(MAKE_RESTARTS)) -endif - -CFG_INFO := $(info cfg: build triple $(CFG_BUILD)) -CFG_INFO := $(info cfg: host triples $(CFG_HOST)) -CFG_INFO := $(info cfg: target triples $(CFG_TARGET)) - -ifneq ($(wildcard $(NON_BUILD_HOST)),) -CFG_INFO := $(info cfg: non-build host triples $(NON_BUILD_HOST)) -endif -ifneq ($(wildcard $(NON_BUILD_TARGET)),) -CFG_INFO := $(info cfg: non-build target triples $(NON_BUILD_TARGET)) -endif - -CFG_RUSTC_FLAGS := $(RUSTFLAGS) -CFG_GCCISH_CFLAGS := -CFG_GCCISH_LINK_FLAGS := - -ifdef CFG_DISABLE_OPTIMIZE - $(info cfg: disabling rustc optimization (CFG_DISABLE_OPTIMIZE)) - CFG_RUSTC_FLAGS += -else - # The rtopt cfg turns off runtime sanity checks - CFG_RUSTC_FLAGS += -O --cfg rtopt -endif - -ifdef CFG_DISABLE_DEBUG - CFG_RUSTC_FLAGS += --cfg ndebug - CFG_GCCISH_CFLAGS += -DRUST_NDEBUG -else - $(info cfg: enabling more debugging (CFG_ENABLE_DEBUG)) - CFG_RUSTC_FLAGS += --cfg debug - CFG_GCCISH_CFLAGS += -DRUST_DEBUG -endif - -ifdef SAVE_TEMPS - CFG_RUSTC_FLAGS += --save-temps -endif -ifdef ASM_COMMENTS - CFG_RUSTC_FLAGS += -Z asm-comments -endif -ifdef TIME_PASSES - CFG_RUSTC_FLAGS += -Z time-passes -endif -ifdef TIME_LLVM_PASSES - CFG_RUSTC_FLAGS += -Z time-llvm-passes -endif -ifdef TRACE - CFG_RUSTC_FLAGS += -Z trace -endif -ifdef CFG_DISABLE_RPATH -CFG_RUSTC_FLAGS += -C no-rpath -endif - -# The executables crated during this compilation process have no need to include -# static copies of libstd and libextra. We also generate dynamic versions of all -# libraries, so in the interest of space, prefer dynamic linking throughout the -# compilation process. -# -# Note though that these flags are omitted for stage2+. This means that the -# snapshot will be generated with a statically linked rustc so we only have to -# worry about the distribution of one file (with its native dynamic -# dependencies) -RUSTFLAGS_STAGE0 += -C prefer-dynamic -RUSTFLAGS_STAGE1 += -C prefer-dynamic - -# 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 - -# version-string calculation -CFG_GIT_DIR := $(CFG_SRC_DIR).git -CFG_RELEASE = 0.10-pre -CFG_VERSION = $(CFG_RELEASE) -# windows exe's need numeric versions - don't use anything but -# numbers and dots here -CFG_VERSION_WIN = 0.10 - -# since $(CFG_GIT) may contain spaces (especially on Windows), -# we need to escape them. (" " to r"\ ") -# Note that $(subst ...) ignores space after `subst`, -# so we use a hack: define $(SPACE) which contains space character. -SPACE := -SPACE += -ifneq ($(wildcard $(subst $(SPACE),\$(SPACE),$(CFG_GIT))),) -ifneq ($(wildcard $(subst $(SPACE),\$(SPACE),$(CFG_GIT_DIR))),) - CFG_VERSION += $(shell git --git-dir='$(CFG_GIT_DIR)' log -1 \ - --pretty=format:'(%h %ci)') - CFG_VER_HASH = $(shell git --git-dir='$(CFG_GIT_DIR)' rev-parse HEAD) -endif -endif - -ifdef CFG_ENABLE_VALGRIND - $(info cfg: enabling valgrind (CFG_ENABLE_VALGRIND)) -else - 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) - -define DEF_X -X_$(1) := $(CFG_EXE_SUFFIX_$(1)) -endef -$(foreach target,$(CFG_TARGET),\ - $(eval $(call DEF_X,$(target)))) - -# "Source" files we generate in builddir along the way. -GENERATED := - -# Delete the built-in rules. -.SUFFIXES: -%:: %,v -%:: RCS/%,v -%:: RCS/% -%:: s.% -%:: SCCS/s.% - - -###################################################################### -# Cleaning out old crates -###################################################################### - -# $(1) is the path for directory to match against -# $(2) is the glob to use in the match -# -# Note that a common bug is to accidentally construct the glob denoted -# by $(2) with a space character prefix, which invalidates the -# construction $(1)$(2). -define CHECK_FOR_OLD_GLOB_MATCHES - $(Q)MATCHES="$(wildcard $(1))"; if [ -n "$$MATCHES" ] ; then echo "warning: there are previous" \'$(notdir $(2))\' "libraries:" $$MATCHES; fi -endef - -# Same interface as above, but deletes rather than just listing the files. -ifdef VERBOSE -define REMOVE_ALL_OLD_GLOB_MATCHES - $(Q)MATCHES="$(wildcard $(1))"; if [ -n "$$MATCHES" ] ; then echo "warning: removing previous" \'$(notdir $(1))\' "libraries:" $$MATCHES; rm $$MATCHES ; fi -endef -else -define REMOVE_ALL_OLD_GLOB_MATCHES - $(Q)MATCHES="$(wildcard $(1))"; if [ -n "$$MATCHES" ] ; then rm $$MATCHES ; fi -endef -endif - -# We use a different strategy for LIST_ALL_OLD_GLOB_MATCHES_EXCEPT -# than in the macros above because it needs the result of running the -# `ls` command after other rules in the command list have run; the -# macro-expander for $(wildcard ...) would deliver its results too -# soon. (This is in contrast to the macros above, which are meant to -# be run at the outset of a command list in a rule.) -ifdef VERBOSE -define LIST_ALL_OLD_GLOB_MATCHES - @echo "info: now are following matches for" '$(notdir $(1))' "libraries:" - @( ls $(1) 2>/dev/null || true ) -endef -else -define LIST_ALL_OLD_GLOB_MATCHES -endef -endif - -###################################################################### -# LLVM macros -###################################################################### - -# FIXME: x86-ism -LLVM_COMPONENTS=x86 arm mips ipo bitreader bitwriter linker asmparser jit mcjit \ - interpreter instrumentation - -# Only build these LLVM tools -LLVM_TOOLS=bugpoint llc llvm-ar llvm-as llvm-dis llvm-mc opt llvm-extract - -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_$(1)) -LLVM_MC_$(1):=$$(CFG_LLVM_INST_DIR_$(1))/bin/llvm-mc$$(X_$(1)) -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) -# On FreeBSD, it may search wrong headers (that are for pre-installed LLVM), -# so we replace -I with -iquote to ensure that it searches bundled LLVM first. -LLVM_CXXFLAGS_$(1)=$$(subst -I, -iquote , $$(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_$(1)) -LLC_$(1)=$$(CFG_LLVM_INST_DIR_$(1))/bin/llc$$(X_$(1)) - -endef - -$(foreach host,$(CFG_HOST), \ - $(eval $(call DEF_LLVM_VARS,$(host)))) - -###################################################################### -# 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_VERSION_WIN -export CFG_RELEASE -export CFG_BUILD -export CFG_LLVM_ROOT -export CFG_ENABLE_MINGW_CROSS -export CFG_PREFIX -export CFG_LIBDIR -export CFG_RUSTLIBDIR -export CFG_LIBDIR_RELATIVE -export CFG_DISABLE_INJECT_STD_VERSION - -###################################################################### -# Per-stage targets and runner -###################################################################### - -include $(CFG_SRC_DIR)mk/crates.mk - -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_RELATIVE) - -# Destinations of artifacts for target architectures -TROOT$(1)_T_$(2)_H_$(3) = $$(HLIB$(1)_H_$(3))/$$(CFG_RUSTLIBDIR)/$(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))/lib - -# Preqrequisites for using the stageN compiler -ifeq ($(1),0) -HSREQ$(1)_H_$(3) = $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) -else -HSREQ$(1)_H_$(3) = \ - $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ - $$(HLIB$(1)_H_$(3))/stamp.rustc \ - $$(foreach dep,$$(RUST_DEPS_rustc),$$(HLIB$(1)_H_$(3))/stamp.$$(dep)) \ - $$(MKFILE_DEPS) -endif - -# 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))/libmorestack.a \ - $$(TLIB$(1)_T_$(2)_H_$(3))/libcompiler-rt.a - -# Prerequisites for a working stageN compiler and libraries, for a specific -# target -SREQ$(1)_T_$(2)_H_$(3) = \ - $$(TSREQ$(1)_T_$(2)_H_$(3)) \ - $$(foreach dep,$$(TARGET_CRATES),\ - $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep)) - -# Prerequisites for a working stageN compiler and complete set of target -# libraries -CSREQ$(1)_T_$(2)_H_$(3) = \ - $$(TSREQ$(1)_T_$(2)_H_$(3)) \ - $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \ - $$(foreach dep,$$(CRATES),$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep)) \ - $$(foreach dep,$$(HOST_CRATES),$$(HLIB$(1)_H_$(3))/stamp.$$(dep)) - -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 - -# Add RUSTFLAGS_STAGEN values to the build command -EXTRAFLAGS_STAGE$(1) = $$(RUSTFLAGS_STAGE$(1)) - -CFGFLAG$(1)_T_$(2)_H_$(3) = stage$(1) - -# Pass --cfg stage0 only for the build->host part of stage0; -# if you're building a cross config, the host->* parts are -# effectively stage1, since it uses the just-built stage0. -ifeq ($(1),0) -ifneq ($(strip $(CFG_BUILD)),$(strip $(3))) -CFGFLAG$(1)_T_$(2)_H_$(3) = stage1 -endif -endif - -ifdef CFG_DISABLE_RPATH -ifeq ($$(OSTYPE_$(3)),apple-darwin) - RPATH_VAR$(1)_T_$(2)_H_$(3) := \ - DYLD_LIBRARY_PATH="$$$$DYLD_LIBRARY_PATH:$$(HLIB$(1)_H_$(3))" -else - RPATH_VAR$(1)_T_$(2)_H_$(3) := \ - LD_LIBRARY_PATH="$$$$LD_LIBRARY_PATH:$$(HLIB$(1)_H_$(3))" -endif -else - RPATH_VAR$(1)_T_$(2)_H_$(3) := -endif - -STAGE$(1)_T_$(2)_H_$(3) := \ - $$(Q)$$(RPATH_VAR$(1)_T_$(2)_H_$(3)) \ - $$(call CFG_RUN_TARG_$(3),$(1), \ - $$(CFG_VALGRIND_COMPILE$(1)) \ - $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ - --cfg $$(CFGFLAG$(1)_T_$(2)_H_$(3)) \ - $$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) \ - $$(RUSTC_FLAGS_$(2)) - -PERF_STAGE$(1)_T_$(2)_H_$(3) := \ - $$(Q)$$(call CFG_RUN_TARG_$(3),$(1), \ - $$(CFG_PERF_TOOL) \ - $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ - --cfg $$(CFGFLAG$(1)_T_$(2)_H_$(3)) \ - $$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) \ - $$(RUSTC_FLAGS_$(2)) - -endef - -$(foreach build,$(CFG_HOST), \ - $(eval $(foreach target,$(CFG_TARGET), \ - $(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),$$(SREQ$(2)_T_$$(target)_H_$(1))) - -endef - -$(foreach host,$(CFG_HOST), \ - $(eval $(foreach stage,1 2 3, \ - $(eval $(call DEF_RUSTC_STAGE_TARGET,$(host),$(stage)))))) - -rustc-stage1: rustc-stage1-H-$(CFG_BUILD) -rustc-stage2: rustc-stage2-H-$(CFG_BUILD) -rustc-stage3: rustc-stage3-H-$(CFG_BUILD) - -define DEF_RUSTC_TARGET -# $(1) == architecture - -rustc-H-$(1): rustc-stage2-H-$(1) -endef - -$(foreach host,$(CFG_TARGET), \ - $(eval $(call DEF_RUSTC_TARGET,$(host)))) - -rustc-stage1: rustc-stage1-H-$(CFG_BUILD) -rustc-stage2: rustc-stage2-H-$(CFG_BUILD) -rustc-stage3: rustc-stage3-H-$(CFG_BUILD) -rustc: rustc-H-$(CFG_BUILD) - -rustc-H-all: $(foreach host,$(CFG_HOST),rustc-H-$(host)) - -###################################################################### -# Entrypoint rule -###################################################################### - -.DEFAULT_GOAL := all - -define ALL_TARGET_N -ifneq ($$(findstring $(1),$$(CFG_HOST)),) -# This is a host -all-target-$(1)-host-$(2): $$(CSREQ2_T_$(1)_H_$(2)) -else -# This is a target only -all-target-$(1)-host-$(2): $$(SREQ2_T_$(1)_H_$(2)) -endif -endef - -$(foreach target,$(CFG_TARGET), \ - $(foreach host,$(CFG_HOST), \ - $(eval $(call ALL_TARGET_N,$(target),$(host))))) - -ALL_TARGET_RULES = $(foreach target,$(CFG_TARGET), \ - $(foreach host,$(CFG_HOST), \ - all-target-$(target)-host-$(host))) - -all: $(ALL_TARGET_RULES) $(GENERATED) docs - - -###################################################################### -# 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.stamp -endif - -Makefile config.mk: config.stamp - -config.stamp: $(S)configure $(S)Makefile.in $(S)src/snapshots.txt - @$(call E, cfg: reconfiguring) - $(Q)$(S)configure $(CFG_CONFIGURE_ARGS) - - -###################################################################### -# Primary-target makefiles +# Primary rules ###################################################################### # Issue #9531: If you change the order of any of the following (or add # new definitions), make sure definitions always precede their uses, # especially for the dependency lists of recipes. +# First, load the variables exported by the configure script +include config.mk + +# Just a few macros used everywhere +include $(CFG_SRC_DIR)mk/util.mk +# All crates and their dependencies +include $(CFG_SRC_DIR)mk/crates.mk +# Reconfiguring when the makefiles or submodules change +include $(CFG_SRC_DIR)mk/reconfig.mk +# Various bits of setup, common macros, and top-level rules +include $(CFG_SRC_DIR)mk/main.mk +# C and assembly components that are not LLVM include $(CFG_SRC_DIR)mk/rt.mk +# Rules for crates in the target directories include $(CFG_SRC_DIR)mk/target.mk +# Rules for crates in the host directories include $(CFG_SRC_DIR)mk/host.mk +# Special rules for bootstrapping stage0 include $(CFG_SRC_DIR)mk/stage0.mk +# Rust-specific LLVM extensions include $(CFG_SRC_DIR)mk/rustllvm.mk +# Documentation include $(CFG_SRC_DIR)mk/docs.mk +# LLVM include $(CFG_SRC_DIR)mk/llvm.mk ###################################################################### # Secondary makefiles, conditionalized for speed ###################################################################### +# Source and binary distribution artifacts ifneq ($(strip $(findstring dist,$(MAKECMDGOALS)) \ $(findstring check,$(MAKECMDGOALS)) \ $(findstring test,$(MAKECMDGOALS)) \ @@ -592,12 +147,14 @@ ifneq ($(strip $(findstring dist,$(MAKECMDGOALS)) \ include $(CFG_SRC_DIR)mk/dist.mk endif +# Binary snapshots ifneq ($(strip $(findstring snap,$(MAKECMDGOALS)) \ $(findstring clean,$(MAKECMDGOALS))),) CFG_INFO := $(info cfg: including snap rules) include $(CFG_SRC_DIR)mk/snap.mk endif +# The test suite ifneq ($(strip $(findstring check,$(MAKECMDGOALS)) \ $(findstring test,$(MAKECMDGOALS)) \ $(findstring perf,$(MAKECMDGOALS)) \ @@ -606,21 +163,25 @@ ifneq ($(strip $(findstring check,$(MAKECMDGOALS)) \ include $(CFG_SRC_DIR)mk/tests.mk endif +# Performance and benchmarking ifneq ($(findstring perf,$(MAKECMDGOALS)),) CFG_INFO := $(info cfg: including perf rules) include $(CFG_SRC_DIR)mk/perf.mk endif +# Cleaning ifneq ($(findstring clean,$(MAKECMDGOALS)),) CFG_INFO := $(info cfg: including clean rules) include $(CFG_SRC_DIR)mk/clean.mk endif +# Installation from the build directory ifneq ($(findstring install,$(MAKECMDGOALS)),) CFG_INFO := $(info cfg: including install rules) include $(CFG_SRC_DIR)mk/install.mk endif +# CTAGS building ifneq ($(strip $(findstring TAGS.emacs,$(MAKECMDGOALS)) \ $(findstring TAGS.vi,$(MAKECMDGOALS))),) CFG_INFO := $(info cfg: including ctags rules) @@ -631,9 +192,3 @@ endif # header file dependencies. ALL_DEP_FILES := $(ALL_OBJ_FILES:%.o=%.d) -include $(ALL_DEP_FILES) - -help: -# Show the comments from this file as "help" -# pick everything between tags | remove first line | remove last line -# | remove extra (?) line | strip leading `#` from lines - $(Q)awk '//,/<\/help>/' $(S)/Makefile.in | sed '1d' | sed '$$d' | sed 's/^# \?//' diff --git a/mk/main.mk b/mk/main.mk new file mode 100644 index 000000000000..064b9cc35113 --- /dev/null +++ b/mk/main.mk @@ -0,0 +1,431 @@ +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +# We track all of the object files we might build so that we can find +# and include all of the .d files in one fell swoop. +ALL_OBJ_FILES := + +MKFILE_DEPS := config.stamp $(call rwildcard,$(CFG_SRC_DIR)mk/,*) +NON_BUILD_HOST = $(filter-out $(CFG_BUILD),$(CFG_HOST)) +NON_BUILD_TARGET = $(filter-out $(CFG_BUILD),$(CFG_TARGET)) + +ifneq ($(MAKE_RESTARTS),) +CFG_INFO := $(info cfg: make restarts: $(MAKE_RESTARTS)) +endif + +CFG_INFO := $(info cfg: build triple $(CFG_BUILD)) +CFG_INFO := $(info cfg: host triples $(CFG_HOST)) +CFG_INFO := $(info cfg: target triples $(CFG_TARGET)) + +ifneq ($(wildcard $(NON_BUILD_HOST)),) +CFG_INFO := $(info cfg: non-build host triples $(NON_BUILD_HOST)) +endif +ifneq ($(wildcard $(NON_BUILD_TARGET)),) +CFG_INFO := $(info cfg: non-build target triples $(NON_BUILD_TARGET)) +endif + +CFG_RUSTC_FLAGS := $(RUSTFLAGS) +CFG_GCCISH_CFLAGS := +CFG_GCCISH_LINK_FLAGS := + +ifdef CFG_DISABLE_OPTIMIZE + $(info cfg: disabling rustc optimization (CFG_DISABLE_OPTIMIZE)) + CFG_RUSTC_FLAGS += +else + # The rtopt cfg turns off runtime sanity checks + CFG_RUSTC_FLAGS += -O --cfg rtopt +endif + +ifdef CFG_DISABLE_DEBUG + CFG_RUSTC_FLAGS += --cfg ndebug + CFG_GCCISH_CFLAGS += -DRUST_NDEBUG +else + $(info cfg: enabling more debugging (CFG_ENABLE_DEBUG)) + CFG_RUSTC_FLAGS += --cfg debug + CFG_GCCISH_CFLAGS += -DRUST_DEBUG +endif + +ifdef SAVE_TEMPS + CFG_RUSTC_FLAGS += --save-temps +endif +ifdef ASM_COMMENTS + CFG_RUSTC_FLAGS += -Z asm-comments +endif +ifdef TIME_PASSES + CFG_RUSTC_FLAGS += -Z time-passes +endif +ifdef TIME_LLVM_PASSES + CFG_RUSTC_FLAGS += -Z time-llvm-passes +endif +ifdef TRACE + CFG_RUSTC_FLAGS += -Z trace +endif +ifdef CFG_DISABLE_RPATH +CFG_RUSTC_FLAGS += -C no-rpath +endif + +# The executables crated during this compilation process have no need to include +# static copies of libstd and libextra. We also generate dynamic versions of all +# libraries, so in the interest of space, prefer dynamic linking throughout the +# compilation process. +# +# Note though that these flags are omitted for stage2+. This means that the +# snapshot will be generated with a statically linked rustc so we only have to +# worry about the distribution of one file (with its native dynamic +# dependencies) +RUSTFLAGS_STAGE0 += -C prefer-dynamic +RUSTFLAGS_STAGE1 += -C prefer-dynamic + +# 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 + +# version-string calculation +CFG_GIT_DIR := $(CFG_SRC_DIR).git +CFG_RELEASE = 0.10-pre +CFG_VERSION = $(CFG_RELEASE) +# windows exe's need numeric versions - don't use anything but +# numbers and dots here +CFG_VERSION_WIN = 0.10 + +# since $(CFG_GIT) may contain spaces (especially on Windows), +# we need to escape them. (" " to r"\ ") +# Note that $(subst ...) ignores space after `subst`, +# so we use a hack: define $(SPACE) which contains space character. +SPACE := +SPACE += +ifneq ($(wildcard $(subst $(SPACE),\$(SPACE),$(CFG_GIT))),) +ifneq ($(wildcard $(subst $(SPACE),\$(SPACE),$(CFG_GIT_DIR))),) + CFG_VERSION += $(shell git --git-dir='$(CFG_GIT_DIR)' log -1 \ + --pretty=format:'(%h %ci)') + CFG_VER_HASH = $(shell git --git-dir='$(CFG_GIT_DIR)' rev-parse HEAD) +endif +endif + +ifdef CFG_ENABLE_VALGRIND + $(info cfg: enabling valgrind (CFG_ENABLE_VALGRIND)) +else + 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" +###################################################################### + +define DEF_X +X_$(1) := $(CFG_EXE_SUFFIX_$(1)) +endef +$(foreach target,$(CFG_TARGET),\ + $(eval $(call DEF_X,$(target)))) + +# "Source" files we generate in builddir along the way. +GENERATED := + +# Delete the built-in rules. +.SUFFIXES: +%:: %,v +%:: RCS/%,v +%:: RCS/% +%:: s.% +%:: SCCS/s.% + + +###################################################################### +# Cleaning out old crates +###################################################################### + +# $(1) is the path for directory to match against +# $(2) is the glob to use in the match +# +# Note that a common bug is to accidentally construct the glob denoted +# by $(2) with a space character prefix, which invalidates the +# construction $(1)$(2). +define CHECK_FOR_OLD_GLOB_MATCHES + $(Q)MATCHES="$(wildcard $(1))"; if [ -n "$$MATCHES" ] ; then echo "warning: there are previous" \'$(notdir $(2))\' "libraries:" $$MATCHES; fi +endef + +# Same interface as above, but deletes rather than just listing the files. +ifdef VERBOSE +define REMOVE_ALL_OLD_GLOB_MATCHES + $(Q)MATCHES="$(wildcard $(1))"; if [ -n "$$MATCHES" ] ; then echo "warning: removing previous" \'$(notdir $(1))\' "libraries:" $$MATCHES; rm $$MATCHES ; fi +endef +else +define REMOVE_ALL_OLD_GLOB_MATCHES + $(Q)MATCHES="$(wildcard $(1))"; if [ -n "$$MATCHES" ] ; then rm $$MATCHES ; fi +endef +endif + +# We use a different strategy for LIST_ALL_OLD_GLOB_MATCHES_EXCEPT +# than in the macros above because it needs the result of running the +# `ls` command after other rules in the command list have run; the +# macro-expander for $(wildcard ...) would deliver its results too +# soon. (This is in contrast to the macros above, which are meant to +# be run at the outset of a command list in a rule.) +ifdef VERBOSE +define LIST_ALL_OLD_GLOB_MATCHES + @echo "info: now are following matches for" '$(notdir $(1))' "libraries:" + @( ls $(1) 2>/dev/null || true ) +endef +else +define LIST_ALL_OLD_GLOB_MATCHES +endef +endif + +###################################################################### +# LLVM macros +###################################################################### + +# FIXME: x86-ism +LLVM_COMPONENTS=x86 arm mips ipo bitreader bitwriter linker asmparser jit mcjit \ + interpreter instrumentation + +# Only build these LLVM tools +LLVM_TOOLS=bugpoint llc llvm-ar llvm-as llvm-dis llvm-mc opt llvm-extract + +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_$(1)) +LLVM_MC_$(1):=$$(CFG_LLVM_INST_DIR_$(1))/bin/llvm-mc$$(X_$(1)) +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) +# On FreeBSD, it may search wrong headers (that are for pre-installed LLVM), +# so we replace -I with -iquote to ensure that it searches bundled LLVM first. +LLVM_CXXFLAGS_$(1)=$$(subst -I, -iquote , $$(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_$(1)) +LLC_$(1)=$$(CFG_LLVM_INST_DIR_$(1))/bin/llc$$(X_$(1)) + +endef + +$(foreach host,$(CFG_HOST), \ + $(eval $(call DEF_LLVM_VARS,$(host)))) + +###################################################################### +# 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_VERSION_WIN +export CFG_RELEASE +export CFG_BUILD +export CFG_LLVM_ROOT +export CFG_ENABLE_MINGW_CROSS +export CFG_PREFIX +export CFG_LIBDIR +export CFG_RUSTLIBDIR +export CFG_LIBDIR_RELATIVE +export CFG_DISABLE_INJECT_STD_VERSION + +###################################################################### +# Per-stage targets and runner +###################################################################### + +STAGES = 0 1 2 3 + +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_RELATIVE) + +# Destinations of artifacts for target architectures +TROOT$(1)_T_$(2)_H_$(3) = $$(HLIB$(1)_H_$(3))/$$(CFG_RUSTLIBDIR)/$(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))/lib + +# Preqrequisites for using the stageN compiler +ifeq ($(1),0) +HSREQ$(1)_H_$(3) = $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) +else +HSREQ$(1)_H_$(3) = \ + $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ + $$(HLIB$(1)_H_$(3))/stamp.rustc \ + $$(foreach dep,$$(RUST_DEPS_rustc),$$(HLIB$(1)_H_$(3))/stamp.$$(dep)) \ + $$(MKFILE_DEPS) +endif + +# 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))/libmorestack.a \ + $$(TLIB$(1)_T_$(2)_H_$(3))/libcompiler-rt.a + +# Prerequisites for a working stageN compiler and libraries, for a specific +# target +SREQ$(1)_T_$(2)_H_$(3) = \ + $$(TSREQ$(1)_T_$(2)_H_$(3)) \ + $$(foreach dep,$$(TARGET_CRATES),\ + $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep)) + +# Prerequisites for a working stageN compiler and complete set of target +# libraries +CSREQ$(1)_T_$(2)_H_$(3) = \ + $$(TSREQ$(1)_T_$(2)_H_$(3)) \ + $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \ + $$(foreach dep,$$(CRATES),$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep)) \ + $$(foreach dep,$$(HOST_CRATES),$$(HLIB$(1)_H_$(3))/stamp.$$(dep)) + +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 + +# Add RUSTFLAGS_STAGEN values to the build command +EXTRAFLAGS_STAGE$(1) = $$(RUSTFLAGS_STAGE$(1)) + +CFGFLAG$(1)_T_$(2)_H_$(3) = stage$(1) + +# Pass --cfg stage0 only for the build->host part of stage0; +# if you're building a cross config, the host->* parts are +# effectively stage1, since it uses the just-built stage0. +ifeq ($(1),0) +ifneq ($(strip $(CFG_BUILD)),$(strip $(3))) +CFGFLAG$(1)_T_$(2)_H_$(3) = stage1 +endif +endif + +ifdef CFG_DISABLE_RPATH +ifeq ($$(OSTYPE_$(3)),apple-darwin) + RPATH_VAR$(1)_T_$(2)_H_$(3) := \ + DYLD_LIBRARY_PATH="$$$$DYLD_LIBRARY_PATH:$$(HLIB$(1)_H_$(3))" +else + RPATH_VAR$(1)_T_$(2)_H_$(3) := \ + LD_LIBRARY_PATH="$$$$LD_LIBRARY_PATH:$$(HLIB$(1)_H_$(3))" +endif +else + RPATH_VAR$(1)_T_$(2)_H_$(3) := +endif + +STAGE$(1)_T_$(2)_H_$(3) := \ + $$(Q)$$(RPATH_VAR$(1)_T_$(2)_H_$(3)) \ + $$(call CFG_RUN_TARG_$(3),$(1), \ + $$(CFG_VALGRIND_COMPILE$(1)) \ + $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ + --cfg $$(CFGFLAG$(1)_T_$(2)_H_$(3)) \ + $$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) \ + $$(RUSTC_FLAGS_$(2)) + +PERF_STAGE$(1)_T_$(2)_H_$(3) := \ + $$(Q)$$(call CFG_RUN_TARG_$(3),$(1), \ + $$(CFG_PERF_TOOL) \ + $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ + --cfg $$(CFGFLAG$(1)_T_$(2)_H_$(3)) \ + $$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) \ + $$(RUSTC_FLAGS_$(2)) + +endef + +$(foreach build,$(CFG_HOST), \ + $(eval $(foreach target,$(CFG_TARGET), \ + $(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),$$(SREQ$(2)_T_$$(target)_H_$(1))) + +endef + +$(foreach host,$(CFG_HOST), \ + $(eval $(foreach stage,1 2 3, \ + $(eval $(call DEF_RUSTC_STAGE_TARGET,$(host),$(stage)))))) + +rustc-stage1: rustc-stage1-H-$(CFG_BUILD) +rustc-stage2: rustc-stage2-H-$(CFG_BUILD) +rustc-stage3: rustc-stage3-H-$(CFG_BUILD) + +define DEF_RUSTC_TARGET +# $(1) == architecture + +rustc-H-$(1): rustc-stage2-H-$(1) +endef + +$(foreach host,$(CFG_TARGET), \ + $(eval $(call DEF_RUSTC_TARGET,$(host)))) + +rustc-stage1: rustc-stage1-H-$(CFG_BUILD) +rustc-stage2: rustc-stage2-H-$(CFG_BUILD) +rustc-stage3: rustc-stage3-H-$(CFG_BUILD) +rustc: rustc-H-$(CFG_BUILD) + +rustc-H-all: $(foreach host,$(CFG_HOST),rustc-H-$(host)) + +###################################################################### +# Entrypoint rule +###################################################################### + +.DEFAULT_GOAL := all + +define ALL_TARGET_N +ifneq ($$(findstring $(1),$$(CFG_HOST)),) +# This is a host +all-target-$(1)-host-$(2): $$(CSREQ2_T_$(1)_H_$(2)) +else +# This is a target only +all-target-$(1)-host-$(2): $$(SREQ2_T_$(1)_H_$(2)) +endif +endef + +$(foreach target,$(CFG_TARGET), \ + $(foreach host,$(CFG_HOST), \ + $(eval $(call ALL_TARGET_N,$(target),$(host))))) + +ALL_TARGET_RULES = $(foreach target,$(CFG_TARGET), \ + $(foreach host,$(CFG_HOST), \ + all-target-$(target)-host-$(host))) + +all: $(ALL_TARGET_RULES) $(GENERATED) docs + +help: +# Show the comments from Makefile.in as "help" +# pick everything between tags | remove first line | remove last line +# | remove extra (?) line | strip leading `#` from lines + $(Q)awk '//,/<\/help>/' $(S)/Makefile.in | sed '1d' | sed '$$d' | sed 's/^# \?//' diff --git a/mk/reconfig.mk b/mk/reconfig.mk new file mode 100644 index 000000000000..8b88fee0ad3d --- /dev/null +++ b/mk/reconfig.mk @@ -0,0 +1,33 @@ +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +# Recursive wildcard function +# http://blog.jgc.org/2011/07/gnu-make-recursive-wildcard-function.html +rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) \ + $(filter $(subst *,%,$2),$d)) + +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.stamp +endif + +Makefile config.mk: config.stamp + +config.stamp: $(S)configure $(S)Makefile.in $(S)src/snapshots.txt + @$(call E, cfg: reconfiguring) + $(S)configure $(CFG_CONFIGURE_ARGS) diff --git a/mk/util.mk b/mk/util.mk new file mode 100644 index 000000000000..2f113f7622d3 --- /dev/null +++ b/mk/util.mk @@ -0,0 +1,28 @@ +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +ifdef VERBOSE + Q := + E = +else + Q := @ + E = echo $(1) +endif + +ifdef VERBOSE + Q := + E = +else + Q := @ + E = echo $(1) +endif + +S := $(CFG_SRC_DIR) + From ab17f445fe999bf7edf22d09b16ac7b7fd1155be Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 14 Feb 2014 00:10:06 -0800 Subject: [PATCH 4/7] mk: Add NO_MKFILE_DEPS for turning off rebuild from makefile changes --- Makefile.in | 1 + mk/main.mk | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Makefile.in b/Makefile.in index 599984623e25..1d828f6ee4c4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -37,6 +37,7 @@ # (may require `CFG_ENABLE_VALGRIND`) # * `NO_REBUILD=1` - Don't rebootstrap when testing std # (and possibly other crates) +# * `NO_MKFILE_DEPS=1` - Don rebuild for modified .mk files # * `SAVE_TEMPS=1` - Use `--save-temps` flag on all `rustc` invocations # * `ASM_COMMENTS=1` - Use `-Z asm-comments` # * `TIME_PASSES=1` - Use `-Z time-passes` diff --git a/mk/main.mk b/mk/main.mk index 064b9cc35113..723f659b7fda 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -12,7 +12,11 @@ # and include all of the .d files in one fell swoop. ALL_OBJ_FILES := +ifneq ($(NO_MAKEFILE_DEPS),) +MKFILE_DEPS := +else MKFILE_DEPS := config.stamp $(call rwildcard,$(CFG_SRC_DIR)mk/,*) +endif NON_BUILD_HOST = $(filter-out $(CFG_BUILD),$(CFG_HOST)) NON_BUILD_TARGET = $(filter-out $(CFG_BUILD),$(CFG_TARGET)) From 334af011f01ceda1086d335231ada3363190b8a9 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 14 Feb 2014 03:34:18 -0800 Subject: [PATCH 5/7] mk: Improve build system help commands --- Makefile.in | 112 +++++++++++++++++++++++++++++++++++++--------------- configure | 2 + mk/main.mk | 18 +++++++-- mk/tests.mk | 4 ++ 4 files changed, 101 insertions(+), 35 deletions(-) diff --git a/Makefile.in b/Makefile.in index 1d828f6ee4c4..f83ddf76eefa 100644 --- a/Makefile.in +++ b/Makefile.in @@ -8,55 +8,100 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. -# +# \(^o^)/ # -# # The Rust Build System +# Greetings, adventurer! The Rust Build System is at your service. # -# Start with these these build targets: +# Whether you want a genuine copy of `rustc`, access to the latest and +# most authoritative Rust documentation, or even to investigate the +# most intimate workings of the compiler itself, you've come to the +# right place. Let's see what's on the menu. # -# * all - The default rule. Builds a complete stage2 compiler, std, -# and extra for all hosts and targets -# * docs - Generate HTML documentation for the std and extra libraries -# from source code comments -# * rustc - The stage 2 compiler for the build platform with standard -# and extra libraries -# * install -# * uninstall -# * check - Run tests -# * check-stage1-$(crate) - Run tests for a crate, e.g. `check-stage1-std` -# * check-stage1-rpass - Run the language tests -# * check-docs - Run the doc tests +# First, start with one of these build targets: +# +# * all - The default. Builds a complete, bootstrapped compiler. +# `rustc` will be in `${target-triple}/stage2/bin/`. Run it +# directly from the build directory if you like. This also +# comes with docs in `doc/`. +# +# * check - Run the complete test suite +# +# * install - Install Rust. Note that installation is not necessary +# to use the compiler. +# +# * uninstall - Uninstall the binaries +# +# For hot tips on working with The Rust Build System, just: +# +# type `make hot-tips` +# +# Otherwise +# +# type `make` +# +# +# +# +# +# # The Rust Build System Tip Line +# +# There are a bazillion different targets you might want to build. Here +# are a few ideas. +# +# * docs - Build gobs of HTML documentation and put it into `doc/` +# * check-$(crate) - Test a crate, e.g. `check-std` +# * check-ref - Run the language reference tests +# * check-docs - Test the documentation examples +# +# TODO: Lots more # # Then mix in some of these environment variables to harness the -# ultimate power of Rust Build System. +# ultimate power of The Rust Build System. # -# * `VERBOSE=1` - Print all commands. Use this to see what's going on. -# * `RUSTFLAGS=...` - Add compiler flags to all `rustc` invocations -# * `CFG_ENABLE_VALGRIND=1` - Run tests under valgrind -# * `VALGRIND_COMPILE=1` - Run the compiler itself under valgrind -# (may require `CFG_ENABLE_VALGRIND`) -# * `NO_REBUILD=1` - Don't rebootstrap when testing std -# (and possibly other crates) -# * `NO_MKFILE_DEPS=1` - Don rebuild for modified .mk files -# * `SAVE_TEMPS=1` - Use `--save-temps` flag on all `rustc` invocations -# * `ASM_COMMENTS=1` - Use `-Z asm-comments` -# * `TIME_PASSES=1` - Use `-Z time-passes` -# * `TIME_LLVM_PASSES=1` - Use `-Z time-llvm-passes` -# * `TRACE=1` - Use `-Z trace` +# * `VERBOSE=1` - Print all commands. Use this to see what's going on. +# * `RUSTFLAGS=...` - Add compiler flags to all `rustc` invocations +# +# * `TESTNAME=...` - Specify the name of tests to run +# * `CHECK_IGNORED=1` - Run normally-ignored tests +# * `NO_BENCH=1` - Don't run crate benchmarks (disable `--bench` flag) +# +# * `CFG_ENABLE_VALGRIND=1` - Run tests under valgrind +# * `VALGRIND_COMPILE=1` - Run the compiler itself under valgrind +# (may require `CFG_ENABLE_VALGRIND`) +# +# * `NO_REBUILD=1` - Don't rebootstrap when testing std +# (and possibly other crates) +# * `NO_MKFILE_DEPS=1` - Don rebuild for modified .mk files +# +# * `SAVE_TEMPS=1` - Use `--save-temps` flag on all `rustc` invocations +# * `ASM_COMMENTS=1` - Use `-Z asm-comments` +# * `TIME_PASSES=1` - Use `-Z time-passes` +# * `TIME_LLVM_PASSES=1` - Use `-Z time-llvm-passes` +# * `TRACE=1` - Use `-Z trace` # # This is hardly all there is to know of The Rust Build System's -# mysteries. Your journey continues on the wiki[1][2]. +# mysteries. The tale continues on the wiki[1][2]. # # [1]: https://github.com/mozilla/rust/wiki/Note-build-system # [2]: https://github.com/mozilla/rust/wiki/Note-testsuite # -# +# Unless you feel like getting your hands dirty, then: +# +# don't type `make nitty-gritty` +# +# +# +# +# +# # The Rust Build System +# +# Gosh I wish there was something useful here (TODO). # # # An (old) explanation of how the build is structured: # # *Note: Hey, like, this is probably inaccurate, and is definitely # an outdated and insufficient explanation of the remarkable -# and discomfiting Rust Build System.* +# Rust Build System.* # # There are multiple build stages (0-3) needed to verify that the # compiler is properly self-hosting. Each stage is divided between @@ -99,6 +144,9 @@ # will just link against the libraries in the target lib directory. # # Admittedly this is a little convoluted. +# +# +# ###################################################################### # Primary rules diff --git a/configure b/configure index de0b7680dcfe..60d7efc7ac8b 100755 --- a/configure +++ b/configure @@ -1103,3 +1103,5 @@ rm -f config.tmp touch config.stamp step_msg "complete" +msg "type \`make help\`" +msg diff --git a/mk/main.mk b/mk/main.mk index 723f659b7fda..c42b7b4757ad 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -428,8 +428,20 @@ ALL_TARGET_RULES = $(foreach target,$(CFG_TARGET), \ all: $(ALL_TARGET_RULES) $(GENERATED) docs -help: -# Show the comments from Makefile.in as "help" +###################################################################### +# Build system documentation +###################################################################### + +# $(1) is the name of the doc
in Makefile.in # pick everything between tags | remove first line | remove last line # | remove extra (?) line | strip leading `#` from lines - $(Q)awk '//,/<\/help>/' $(S)/Makefile.in | sed '1d' | sed '$$d' | sed 's/^# \?//' +SHOW_DOCS = $(Q)awk '/$(1)/,/<\/$(1)>/' $(S)/Makefile.in | sed '1d' | sed '$$d' | sed 's/^\# \?//' + +help: + $(call SHOW_DOCS,help) + +hot-tips: + $(call SHOW_DOCS,hottips) + +nitty-gritty: + $(call SHOW_DOCS,nittygritty) diff --git a/mk/tests.mk b/mk/tests.mk index 7dec48b83729..049b41ab204d 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -190,6 +190,10 @@ check-lite: cleantestlibs cleantmptestlogs \ check-stage2-rfail check-stage2-cfail check-stage2-rmake $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log +check-ref: cleantestlibs cleantmptestlogs check-stage2-rpass \ + check-stage2-rfail check-stage2-cfail check-stage2-rmake + $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log + .PHONY: cleantmptestlogs cleantestlibs cleantmptestlogs: From 24915c84e0d4764a7995039fac2b3f31c409d04c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 14 Feb 2014 11:24:22 -0800 Subject: [PATCH 6/7] mk: Move version info to top of main.mk Just so it's easier to find. --- mk/main.mk | 55 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/mk/main.mk b/mk/main.mk index c42b7b4757ad..aa5ae77b3ac7 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -8,6 +8,39 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. +###################################################################### +# Version numbers and strings +###################################################################### + +# The version number +CFG_RELEASE = 0.10-pre + +# The version string plus commit information +CFG_VERSION = $(CFG_RELEASE) +CFG_GIT_DIR := $(CFG_SRC_DIR).git +# since $(CFG_GIT) may contain spaces (especially on Windows), +# we need to escape them. (" " to r"\ ") +# Note that $(subst ...) ignores space after `subst`, +# so we use a hack: define $(SPACE) which contains space character. +SPACE := +SPACE += +ifneq ($(wildcard $(subst $(SPACE),\$(SPACE),$(CFG_GIT))),) +ifneq ($(wildcard $(subst $(SPACE),\$(SPACE),$(CFG_GIT_DIR))),) + CFG_VERSION += $(shell git --git-dir='$(CFG_GIT_DIR)' log -1 \ + --pretty=format:'(%h %ci)') + CFG_VER_HASH = $(shell git --git-dir='$(CFG_GIT_DIR)' rev-parse HEAD) +endif +endif + +# windows exe's need numeric versions - don't use anything but +# numbers and dots here +CFG_VERSION_WIN = $(subst -pre,,$(CFG_RELEASE)) + + +###################################################################### +# More configuration +###################################################################### + # We track all of the object files we might build so that we can find # and include all of the .d files in one fell swoop. ALL_OBJ_FILES := @@ -97,28 +130,6 @@ else CFG_VALGRIND_COMPILE := endif -# version-string calculation -CFG_GIT_DIR := $(CFG_SRC_DIR).git -CFG_RELEASE = 0.10-pre -CFG_VERSION = $(CFG_RELEASE) -# windows exe's need numeric versions - don't use anything but -# numbers and dots here -CFG_VERSION_WIN = 0.10 - -# since $(CFG_GIT) may contain spaces (especially on Windows), -# we need to escape them. (" " to r"\ ") -# Note that $(subst ...) ignores space after `subst`, -# so we use a hack: define $(SPACE) which contains space character. -SPACE := -SPACE += -ifneq ($(wildcard $(subst $(SPACE),\$(SPACE),$(CFG_GIT))),) -ifneq ($(wildcard $(subst $(SPACE),\$(SPACE),$(CFG_GIT_DIR))),) - CFG_VERSION += $(shell git --git-dir='$(CFG_GIT_DIR)' log -1 \ - --pretty=format:'(%h %ci)') - CFG_VER_HASH = $(shell git --git-dir='$(CFG_GIT_DIR)' rev-parse HEAD) -endif -endif - ifdef CFG_ENABLE_VALGRIND $(info cfg: enabling valgrind (CFG_ENABLE_VALGRIND)) else From 8d4b675ced48d3382382a4940dad20615347c29e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 14 Feb 2014 19:17:50 -0800 Subject: [PATCH 7/7] mk: Address review feedback --- Makefile.in | 32 ++++++++++++++++++++++---------- configure | 2 +- mk/tests.mk | 20 ++++++++++++++++++++ mk/util.mk | 8 -------- 4 files changed, 43 insertions(+), 19 deletions(-) diff --git a/Makefile.in b/Makefile.in index f83ddf76eefa..ba1879a77132 100644 --- a/Makefile.in +++ b/Makefile.in @@ -31,17 +31,17 @@ # # * uninstall - Uninstall the binaries # -# For hot tips on working with The Rust Build System, just: +# For tips on working with The Rust Build System, just: # -# type `make hot-tips` +# run `make tips` # # Otherwise # -# type `make` +# run `make` # # # -# +# # # # The Rust Build System Tip Line # @@ -52,8 +52,9 @@ # * check-$(crate) - Test a crate, e.g. `check-std` # * check-ref - Run the language reference tests # * check-docs - Test the documentation examples -# -# TODO: Lots more +# * check-stage$(stage)-$(crate) - Test a crate in a specific stage +# * check-stage$(stage)-{rpass,rfail,cfail,rmake,...} - Run tests in src/test/ +# * check-stage1-T-$(target)-H-$(host) - Run cross-compiled-tests # # Then mix in some of these environment variables to harness the # ultimate power of The Rust Build System. @@ -71,7 +72,7 @@ # # * `NO_REBUILD=1` - Don't rebootstrap when testing std # (and possibly other crates) -# * `NO_MKFILE_DEPS=1` - Don rebuild for modified .mk files +# * `NO_MKFILE_DEPS=1` - Don't rebuild for modified .mk files # # * `SAVE_TEMPS=1` - Use `--save-temps` flag on all `rustc` invocations # * `ASM_COMMENTS=1` - Use `-Z asm-comments` @@ -79,17 +80,28 @@ # * `TIME_LLVM_PASSES=1` - Use `-Z time-llvm-passes` # * `TRACE=1` - Use `-Z trace` # +# # Rust recipes for build system success +# +# // Modifying libstd? Use this comment to run unit tests just on your change +# make check-stage1-std NO_REBUILD=1 NO_BENCH=1 +# +# // Added a run-pass test? Use this to test running your test +# make check-stage1-rpass TESTNAME=my-shiny-new-test +# +# // Having trouble figuring out which test is failing? Turn off parallel tests +# make check-stage1-std RUST_TEST_TASKS=1 +# # This is hardly all there is to know of The Rust Build System's # mysteries. The tale continues on the wiki[1][2]. # # [1]: https://github.com/mozilla/rust/wiki/Note-build-system # [2]: https://github.com/mozilla/rust/wiki/Note-testsuite # -# Unless you feel like getting your hands dirty, then: +# If you really feel like getting your hands dirty, then: # -# don't type `make nitty-gritty` +# run `make nitty-gritty` # -# +# # # # diff --git a/configure b/configure index 60d7efc7ac8b..75514ada973b 100755 --- a/configure +++ b/configure @@ -1103,5 +1103,5 @@ rm -f config.tmp touch config.stamp step_msg "complete" -msg "type \`make help\`" +msg "run \`make help\`" msg diff --git a/mk/tests.mk b/mk/tests.mk index 049b41ab204d..8ca4da85994f 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -194,6 +194,9 @@ check-ref: cleantestlibs cleantmptestlogs check-stage2-rpass \ check-stage2-rfail check-stage2-cfail check-stage2-rmake $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log +check-docs: cleantestlibs cleantmptestlogs check-stage2-docs + $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log + .PHONY: cleantmptestlogs cleantestlibs cleantmptestlogs: @@ -827,6 +830,23 @@ $(foreach stage,$(STAGES), \ $(foreach group,$(TEST_GROUPS), \ $(eval $(call DEF_CHECK_FOR_STAGE_AND_HOSTS_AND_GROUP,$(stage),$(host),$(group)))))) +define DEF_CHECK_DOC_FOR_STAGE +check-stage$(1)-docs: $$(foreach docname,$$(DOC_TEST_NAMES),\ + check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-$$(docname)) \ + $$(foreach crate,$$(DOC_CRATE_NAMES),\ + check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-$$(crate)) +endef + +$(foreach stage,$(STAGES), \ + $(eval $(call DEF_CHECK_DOC_FOR_STAGE,$(stage)))) + +define DEF_CHECK_CRATE +check-$(1): check-stage2-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-$(1)-exec +endef + +$(foreach crate,$(TEST_CRATES), \ + $(eval $(call DEF_CHECK_CRATE,$(crate)))) + ###################################################################### # check-fast rules ###################################################################### diff --git a/mk/util.mk b/mk/util.mk index 2f113f7622d3..3bbc8f413aec 100644 --- a/mk/util.mk +++ b/mk/util.mk @@ -16,13 +16,5 @@ else E = echo $(1) endif -ifdef VERBOSE - Q := - E = -else - Q := @ - E = echo $(1) -endif - S := $(CFG_SRC_DIR)