###################################################################### # Residual auto-configuration ###################################################################### include config.mk MKFILES := Makefile config.mk ifneq ($(MAKE_RESTARTS),) CFG_INFO := $(info cfg: make restarts: $(MAKE_RESTARTS)) endif CFG_INFO := $(info cfg: building on $(CFG_OSTYPE) $(CFG_CPUTYPE)) CFG_GCC_CFLAGS := -fno-strict-aliasing CFG_GCC_LINK_FLAGS := CFG_BOOT_FLAGS := $(BOOT_FLAGS) ifdef CFG_DISABLE_OPTIMIZE $(info cfg: disabling rustc optimization (CFG_DISABLE_OPTIMIZE)) CFG_RUSTC_FLAGS := -nowarn else CFG_RUSTC_FLAGS := -nowarn -O endif # On Darwin, we need to run dsymutil so the debugging information ends # up in the right place. On other platforms, it automatically gets # embedded into the executable, so use a no-op command. CFG_DSYMUTIL := true ifeq ($(CFG_OSTYPE), FreeBSD) CFG_LIB_NAME=lib$(1).so CFG_GCC_CFLAGS += -fPIC -march=i686 -I/usr/local/include -O2 CFG_GCC_LINK_FLAGS += -shared -fPIC -lpthread -lrt ifeq ($(CFG_CPUTYPE), x86_64) CFG_GCC_CFLAGS += -m32 CFG_GCC_LINK_FLAGS += -m32 endif CFG_UNIXY := 1 CFG_LDENV := LD_LIBRARY_PATH CFG_DEF_SUFFIX := .bsd.def endif ifeq ($(CFG_OSTYPE), Linux) CFG_LIB_NAME=lib$(1).so CFG_GCC_CFLAGS += -fPIC -march=i686 -O2 CFG_GCC_LINK_FLAGS += -shared -fPIC -ldl -lpthread -lrt CFG_GCC_DEF_FLAG := -Wl,--export-dynamic,--dynamic-list= CFG_GCC_PRE_LIB_FLAGS := -Wl,-whole-archive CFG_GCC_POST_LIB_FLAGS := -Wl,-no-whole-archive ifeq ($(CFG_CPUTYPE), x86_64) CFG_GCC_CFLAGS += -m32 CFG_GCC_LINK_FLAGS += -m32 endif CFG_UNIXY := 1 CFG_LDENV := LD_LIBRARY_PATH CFG_DEF_SUFFIX := .linux.def endif ifeq ($(CFG_OSTYPE), Darwin) CFG_LIB_NAME=lib$(1).dylib CFG_UNIXY := 1 CFG_LDENV := DYLD_LIBRARY_PATH CFG_GCC_LINK_FLAGS += -dynamiclib -lpthread CFG_GCC_DEF_FLAG := -Wl,-exported_symbols_list, # Darwin has a very blurry notion of "64 bit", and claims it's running # "on an i386" when the whole userspace is 64-bit and the compiler # emits 64-bit binaries by default. So we just force -m32 here. Smarter # approaches welcome! # # NB: Currently GCC's optimizer breaks rustrt (task-comm-1 hangs) on Darwin. CFG_GCC_CFLAGS += -m32 -O0 CFG_GCC_LINK_FLAGS += -m32 CFG_DSYMUTIL := dsymutil CFG_DEF_SUFFIX := .darwin.def endif ifneq ($(findstring MINGW,$(CFG_OSTYPE)),) CFG_WINDOWSY := 1 endif CFG_LDPATH :=$(CFG_BUILD_DIR)/rt CFG_LDPATH :=$(CFG_LDPATH):$(CFG_BUILD_DIR)/rustllvm CFG_TESTLIB=$(dir $(firstword $(1))):$(patsubst .%,%,$(suffix $(1))) CFG_EXE_TESTLIB=$(call CFG_TESTLIB,$(patsubst %.exe,%,$(1))) ifdef CFG_WINDOWSY CFG_INFO := $(info cfg: windows-y environment) CFG_EXE_SUFFIX := .exe CFG_LIB_NAME=$(1).dll CFG_LDPATH :=$(CFG_LDPATH):$(CFG_LLVM_BINDIR) CFG_LDPATH :=$(CFG_LDPATH):$$PATH CFG_RUN_TEST=PATH="$(CFG_LDPATH):$(call CFG_EXE_TESTLIB,$(1))" $(1) CFG_RUN_TARG=PATH="$(CFG_LDPATH)" $(1) CFG_PATH_MUNGE := $(strip perl -i.bak -p \ -e 's@\\(\S)@/\1@go;' \ -e 's@^/([a-zA-Z])/@\1:/@o;') ifdef CFG_FLEXLINK CFG_BOOT_NATIVE := 1 endif CFG_GCC_CFLAGS += -march=i686 -O2 CFG_GCC_LINK_FLAGS += -shared -fPIC CFG_DEF_SUFFIX := .def endif ifdef CFG_UNIXY CFG_INFO := $(info cfg: unix-y environment) CFG_PATH_MUNGE := true CFG_EXE_SUFFIX := CFG_LDPATH :=$(CFG_LDPATH):$(CFG_LLVM_LIBDIR) CFG_RUN_TARG=$(CFG_LDENV)=$(CFG_LDPATH) $(1) CFG_RUN_TEST=\ $(CFG_LDENV)=$(call CFG_TESTLIB,$(1)):$(CFG_LDPATH) \ $(CFG_VALGRIND) $(1) CFG_BOOT_NATIVE := 1 ifdef MINGW_CROSS CFG_EXE_SUFFIX := .exe CFG_LIB_NAME=$(1).dll CFG_LDPATH :=$(CFG_LDPATH):$(CFG_LLVM_BINDIR) CFG_LDPATH :=$(CFG_LDPATH):$$PATH CFG_RUN_TARG=PATH=$(CFG_LDPATH) $(1) CFG_RUN_TEST=PATH=$(CFG_LDPATH):$(call CFG_EXE_TESTLIB,$(1)) $(1) CFG_INFO := $(info cfg: mingw-cross) CFG_GCC_CROSS := i586-mingw32msvc- CFG_BOOT_FLAGS += -t win32-x86-pe ifdef CFG_VALGRIND CFG_VALGRIND += wine endif CFG_GCC_CFLAGS := -march=i686 CFG_GCC_LINK_FLAGS := -shared ifeq ($(CFG_CPUTYPE), x86_64) CFG_GCC_CFLAGS += -m32 CFG_GCC_LINK_FLAGS += -m32 endif endif ifdef CFG_VALGRIND CFG_VALGRIND += --leak-check=full \ --error-exitcode=1 \ --quiet --vex-iropt-level=0 \ --suppressions=$(CFG_SRC_DIR)src/etc/x86.supp endif endif CFG_RUNTIME :=$(call CFG_LIB_NAME,rustrt) CFG_RUSTLLVM :=$(call CFG_LIB_NAME,rustllvm) CFG_STDLIB :=$(call CFG_LIB_NAME,std) ifdef CFG_GCC CFG_INFO := $(info cfg: using gcc) CFG_GCC_CFLAGS += -Wall -Werror -fno-rtti -fno-exceptions -g CFG_GCC_LINK_FLAGS += -g CFG_COMPILE_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_CFLAGS) -c -o $(1) $(2) CFG_DEPEND_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_CFLAGS) -MT "$(1)" -MM $(2) CFG_LINK_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_LINK_FLAGS) -o $(1) \ $(CFG_GCC_DEF_FLAG)$(3) $(2) else CFG_ERR := $(error please try on a system with gcc) endif ifdef CFG_OCAMLC_OPT $(info cfg: have ocaml native compiler) OPT=.opt else $(info cfg: have only ocaml bytecode compiler) endif ifdef CFG_BOOT_PROFILE $(info cfg: forcing native bootstrap compiler (CFG_BOOT_PROFILE)) CFG_BOOT_NATIVE := 1 CFG_OCAMLOPT_PROFILE_FLAGS := -p endif ifdef CFG_BOOT_DEBUG $(info cfg: forcing bytecode bootstrap compiler (CFG_BOOT_DEBUG)) CFG_BOOT_NATIVE := endif ifdef CFG_BOOT_NATIVE $(info cfg: building native bootstrap compiler) else $(info cfg: building bytecode bootstrap compiler) endif ifdef CFG_DISABLE_VALGRIND $(info cfg: disabling valgrind (CFG_DISABLE_VALGRIND)) 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 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 # Compilers we build, we now know how to run. BOOT := $(Q)OCAMLRUNPARAM="b1" boot/rustboot$(X) $(CFG_BOOT_FLAGS) -L boot STAGE0 := $(Q)$(call CFG_RUN_TARG,\ stage0/rustc$(X) $(CFG_RUSTC_FLAGS) -L stage0) STAGE1 := $(Q)$(call CFG_RUN_TARG,\ stage1/rustc$(X) $(CFG_RUSTC_FLAGS) -L stage1) # "Source" files we generate in builddir along the way. GENERATED := boot/fe/lexer.ml boot/version.ml # Delete the built-in rules. .SUFFIXES: %:: %,v %:: RCS/%,v %:: RCS/% %:: s.% %:: SCCS/s.% ###################################################################### # Bootstrap compiler variables ###################################################################### # We must list them in link order. # Nobody calculates the link-order DAG automatically, sadly. BOOT_MLS := \ $(addsuffix .ml, \ boot/version \ $(addprefix boot/util/, fmt common bits) \ $(addprefix boot/driver/, session) \ $(addprefix boot/fe/, ast token lexer parser \ extfmt pexp item cexp fuzz) \ $(addprefix boot/be/, asm il abi) \ $(addprefix boot/me/, walk semant resolve alias \ simplify type dead layer typestate \ loop layout transutil trans dwarf) \ $(addprefix boot/be/, x86 ra pe elf macho) \ $(addprefix boot/driver/, lib glue main)) \ BOOT_CMOS := $(BOOT_MLS:.ml=.cmo) BOOT_CMXS := $(BOOT_MLS:.ml=.cmx) BOOT_OBJS := $(BOOT_MLS:.ml=.o) BOOT_CMIS := $(BOOT_MLS:.ml=.cmi) BS := $(S)src/boot BOOT_ML_DEP_INCS := -I $(BS)/fe -I $(BS)/me \ -I $(BS)/be -I $(BS)/driver \ -I $(BS)/util -I boot BOOT_ML_INCS := -I boot/fe -I boot/me \ -I boot/be -I boot/driver \ -I boot/util -I boot BOOT_ML_LIBS := unix.cma nums.cma bigarray.cma BOOT_ML_NATIVE_LIBS := unix.cmxa nums.cmxa bigarray.cmxa BOOT_OCAMLC_FLAGS := -g $(BOOT_ML_INCS) -w Ael -warn-error Ael BOOT_OCAMLOPT_FLAGS := -g $(BOOT_ML_INCS) -w Ael -warn-error Ael ifdef CFG_FLEXLINK BOOT_OCAMLOPT_FLAGS += -cclib -L/usr/lib endif ###################################################################### # Runtime (C++) library variables ###################################################################### RUNTIME_CS := rt/sync/timer.cpp \ rt/sync/sync.cpp \ rt/sync/lock_and_signal.cpp \ rt/rust.cpp \ rt/rust_builtin.cpp \ rt/rust_run_program.cpp \ rt/rust_crate.cpp \ rt/rust_crate_cache.cpp \ rt/rust_crate_reader.cpp \ rt/rust_comm.cpp \ rt/rust_dom.cpp \ rt/rust_task.cpp \ rt/rust_task_list.cpp \ rt/rust_proxy.cpp \ rt/rust_chan.cpp \ rt/rust_port.cpp \ rt/rust_upcall.cpp \ rt/rust_log.cpp \ rt/rust_message.cpp \ rt/rust_timer.cpp \ rt/circular_buffer.cpp \ rt/isaac/randport.cpp \ rt/rust_srv.cpp \ rt/rust_kernel.cpp \ rt/memory_region.cpp \ rt/test/rust_test_harness.cpp \ rt/test/rust_test_runtime.cpp \ rt/test/rust_test_util.cpp RUNTIME_HDR := rt/globals.h \ rt/rust.h \ rt/rust_dwarf.h \ rt/rust_internal.h \ rt/rust_util.h \ rt/rust_chan.h \ rt/rust_port.h \ rt/rust_dom.h \ rt/rust_task.h \ rt/rust_task_list.h \ rt/rust_proxy.h \ rt/rust_log.h \ rt/rust_message.h \ rt/circular_buffer.h \ rt/util/array_list.h \ rt/util/indexed_list.h \ rt/util/synchronized_indexed_list.h \ rt/util/hash_map.h \ rt/sync/sync.h \ rt/sync/timer.h \ rt/sync/lock_and_signal.h \ rt/sync/lock_free_queue.h \ rt/rust_srv.h \ rt/rust_kernel.h \ rt/memory_region.h \ rt/memory.h \ rt/test/rust_test_harness.h \ rt/test/rust_test_runtime.h \ rt/test/rust_test_util.h RUNTIME_DEF := rt/rustrt$(CFG_DEF_SUFFIX) RUNTIME_INCS := -I $(S)src/rt/isaac -I $(S)src/rt/uthash RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o) RUNTIME_LIBS := $(CFG_GCC_POST_LIB_FLAGS) ###################################################################### # rustc LLVM-extensions (C++) library variables ###################################################################### RUSTLLVM_LIB_CS := $(addprefix rustllvm/, \ MachOObjectFile.cpp Passes.cpp) RUSTLLVM_OBJS_CS := $(addprefix rustllvm/, RustWrapper.cpp) RUSTLLVM_HDR := rustllvm/include/llvm-c/Object.h RUSTLLVM_DEF := rustllvm/rustllvm$(CFG_DEF_SUFFIX) RUSTLLVM_INCS := -iquote $(CFG_LLVM_INCDIR) \ -iquote $(S)src/rustllvm/include RUSTLLVM_LIB_OBJS := $(RUSTLLVM_LIB_CS:.cpp=.o) RUSTLLVM_OBJS_OBJS := $(RUSTLLVM_OBJS_CS:.cpp=.o) ###################################################################### # 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)) ###################################################################### # Test dependency variables ###################################################################### LREQ := rt/$(CFG_RUNTIME) rustllvm/$(CFG_RUSTLLVM) BREQ := boot/rustboot$(X) boot/$(CFG_STDLIB) SREQ0 := stage0/rustc$(X) $(LREQ) stage0/glue.o stage0/$(CFG_STDLIB) SREQ1 := stage1/rustc$(X) $(LREQ) stage1/glue.o stage1/$(CFG_STDLIB) SREQ2 := stage2/rustc$(X) $(LREQ) stage2/glue.o stage2/$(CFG_STDLIB) ###################################################################### # Single-target rules ###################################################################### all: boot/rustboot$(X) \ boot/$(CFG_STDLIB) \ rt/$(CFG_RUNTIME) \ rustllvm/$(CFG_RUSTLLVM) \ stage0/rustc$(X) \ stage0/glue.o \ stage0/$(CFG_STDLIB) \ $(GENERATED) \ $(DOCS) rt/$(CFG_RUNTIME): $(RUNTIME_OBJS) $(MKFILES) $(RUNTIME_HDR) $(RUNTIME_DEF) @$(call E, link: $@) $(Q)$(call CFG_LINK_C,$@,$(RUNTIME_LIBS) $(RUNTIME_OBJS),$(RUNTIME_DEF)) # FIXME: Building a .a is a hack so that we build with both older and newer # versions of LLVM. In newer versions some of the bits of this library are # already in LLVM itself, so they are skipped. rustllvm/rustllvmbits.a: $(RUSTLLVM_LIB_OBJS) rm -f $@ ar crs $@ $^ # Note: We pass $(CFG_LLVM_LIBS) twice to fix the windows link since # it has no -whole-archive. rustllvm/$(CFG_RUSTLLVM): rustllvm/rustllvmbits.a $(RUSTLLVM_OBJS_OBJS) \ $(MKFILES) $(RUSTLLVM_HDR) $(RUSTLLVM_DEF) @$(call E, link: $@) $(Q)$(call CFG_LINK_C,$@,$(RUSTLLVM_OBJS_OBJS) \ $(CFG_GCC_PRE_LIB_FLAGS) $(CFG_LLVM_LIBS) \ $(CFG_GCC_POST_LIB_FLAGS) rustllvm/rustllvmbits.a \ $(CFG_LLVM_LIBS) \ $(CFG_LLVM_LDFLAGS),$(RUSTLLVM_DEF)) ifdef CFG_BOOT_NATIVE boot/rustboot$(X): $(BOOT_CMXS) $(MKFILES) @$(call E, link: $@) $(Q)ocamlopt$(OPT) -o $@ $(BOOT_OCAMLOPT_FLAGS) $(BOOT_ML_NATIVE_LIBS) \ $(BOOT_CMXS) else boot/rustboot$(X): $(BOOT_CMOS) $(MKFILES) @$(call E, link: $@) $(Q)ocamlc$(OPT) -o $@ $(BOOT_OCAMLC_FLAGS) $(BOOT_ML_LIBS) $(BOOT_CMOS) endif boot/version.ml: $(MKFILES) @$(call E, git: $@) $(Q)(cd $(S) && git log -1 \ --pretty=format:'let version = "prerelease (%h %ci)";;') >$@ || exit 1 boot/$(CFG_STDLIB): $(STDLIB_CRATE) $(STDLIB_INPUTS) \ boot/rustboot$(X) $(MKFILES) @$(call E, compile: $@) $(BOOT) -shared -o $@ $< stage0/std.o: $(STDLIB_CRATE) $(STDLIB_INPUTS) stage0/rustc$(X) $(MKFILES) @$(call E, compile: $@) $(STAGE0) -c -shared -o $@ $< stage0/$(CFG_STDLIB): stage0/std.o stage0/glue.o @$(call E, link: $@) $(Q)gcc $(CFG_GCC_CFLAGS) stage0/glue.o $(CFG_GCC_LINK_FLAGS) -o $@ $< \ -Lstage0 -Lrt -lrustrt stage1/std.o: $(STDLIB_CRATE) $(STDLIB_INPUTS) stage1/rustc$(X) $(MKFILES) @$(call E, compile: $@) $(STAGE1) -c -shared -o $@ $< stage1/$(CFG_STDLIB): stage1/std.o stage1/glue.o @$(call E, link: $@) $(Q)gcc $(CFG_GCC_CFLAGS) stage1/glue.o $(CFG_GCC_LINK_FLAGS) -o $@ $< \ -Lstage1 -Lrt -lrustrt stage2/std.o: $(STDLIB_CRATE) $(STDLIB_INPUTS) stage2/rustc$(X) $(MKFILES) @$(call E, compile: $@) $(STAGE2) -c -shared -o $@ $< stage2/$(CFG_STDLIB): stage2/std.o stage2/glue.o @$(call E, link: $@) $(Q)gcc $(CFG_GCC_CFLAGS) stage2/glue.o $(CFG_GCC_LINK_FLAGS) -o $@ $< \ -Lstage2 -Lrt -lrustrt stage0/rustc$(X): $(COMPILER_CRATE) $(COMPILER_INPUTS) $(BREQ) @$(call E, compile: $@) $(BOOT) -minimal -o $@ $< $(Q)chmod 0755 $@ stage1/rustc.o: $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ0) @$(call E, compile: $@) $(STAGE0) -c -o $@ $< stage2/rustc.o: $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ1) @$(call E, compile: $@) $(STAGE1) -c -o $@ $< stage0/glue.o: stage0/rustc$(X) boot/$(CFG_STDLIB) \ rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME) @$(call E, generate: $@) $(STAGE0) -c -o $@ -glue stage1/glue.o: stage1/rustc$(X) stage0/$(CFG_STDLIB) \ rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME) @$(call E, generate: $@) $(STAGE1) -c -o $@ -glue stage2/glue.o: stage2/rustc$(X) stage1/$(CFG_STDLIB) \ rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME) @$(call E, generate: $@) $(STAGE2) -c -o $@ -glue # Due to make not wanting to run the same implicit rules twice on the same # rule tree (implicit-rule recursion prevention, see "Chains of Implicit # Rules" in GNU Make manual) we have to re-state the %.o and %.s patterns here # for different directories, to handle cases where (say) a test relies on a # compiler that relies on a .o file. stage0/%.o: stage0/%.s @$(call E, assemble [gcc]: $@) $(Q)gcc $(CFG_GCC_CFLAGS) -o $@ -c $< stage1/%.o: stage1/%.s @$(call E, assemble [gcc]: $@) $(Q)gcc $(CFG_GCC_CFLAGS) -o $@ -c $< stage2/%.o: stage2/%.s @$(call E, assemble [gcc]: $@) $(Q)gcc $(CFG_GCC_CFLAGS) -o $@ -c $< stage1/%$(X): stage1/%.o $(SREQ0) @$(call E, link [gcc]: $@) $(Q)gcc $(CFG_GCC_CFLAGS) stage0/glue.o -o $@ $< \ -Lstage0 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. -$(Q)$(CFG_DSYMUTIL) $@ stage2/%$(X): stage2/%.o $(SREQ1) @$(call E, link [gcc]: $@) $(Q)gcc $(CFG_GCC_CFLAGS) stage1/glue.o -o $@ $< \ -Lstage1 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. -$(Q)$(CFG_DSYMUTIL) $@ ###################################################################### # Library and boot rules ###################################################################### rt/%.o: rt/%.cpp $(MKFILES) @$(call E, compile: $@) $(Q)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $< rustllvm/%.o: rustllvm/%.cpp $(MKFILES) @$(call E, compile: $@) $(Q)$(call CFG_COMPILE_C, $@, $(CFG_LLVM_CXXFLAGS) $(RUSTLLVM_INCS)) $< %.cmo: %.ml $(MKFILES) @$(call E, compile: $@) $(Q)ocamlc$(OPT) -c -o $@ $(BOOT_OCAMLC_FLAGS) $< %.cmo: %.cmi $(MKFILES) %.cmx %.o: %.ml $(MKFILES) @$(call E, compile: $@) $(Q)ocamlopt$(OPT) -c -o $@ $(BOOT_OCAMLOPT_FLAGS) $< %.ml: %.mll $(MKFILES) @$(call E, lex-gen: $@) $(Q)ocamllex$(OPT) -q -o $@ $< %.linux.def: %.def.in $(MKFILES) @$(call E, def: $@) $(Q)echo "{" > $@ $(Q)sed 's/.$$/&;/' $< >> $@ $(Q)echo "};" >> $@ %.darwin.def: %.def.in $(MKFILES) @$(call E, def: $@) $(Q)sed 's/^./_&/' $< > $@ ifdef CFG_WINDOWSY %.def: %.def.in $(MKFILES) @$(call E, def: $@) $(Q)echo LIBRARY $* > $@ $(Q)echo EXPORTS >> $@ $(Q)sed 's/^./ &/' $< >> $@ endif ###################################################################### # Doc rules ###################################################################### doc/version.texi: $(MKFILES) rust.texi (cd $(S) && git log -1 \ --pretty=format:'@macro gitversion%n%h %ci%n@end macro%n') >$@ doc/%.pdf: %.texi doc/version.texi texi2pdf -I doc -o $@ --clean $< doc/%.html: %.texi doc/version.texi makeinfo -I doc --html --ifhtml --force --no-split --output=$@ $< docsnap: doc/rust.pdf mv $< doc/rust-$(shell date +"%Y-%m-%d")-snap.pdf ###################################################################### # Testing variables ###################################################################### ALL_TEST_INPUTS = $(wildcard $(S)src/test/*/*.rs \ $(S)src/test/*/*/*.rs \ $(S)src/test/*/*.rc) TEST_XFAILS_BOOT = $(shell grep -l xfail-boot $(ALL_TEST_INPUTS)) TEST_XFAILS_STAGE0 = $(shell grep -l xfail-stage0 $(ALL_TEST_INPUTS)) ifdef MINGW_CROSS TEST_XFAILS_BOOT += $(S)src/test/run-pass/native-mod.rc TEST_XFAILS_STAGE0 += $(S)src/test/run-pass/native-mod.rc endif ifdef CFG_WINDOWSY TEST_XFAILS_BOOT += $(S)src/test/run-pass/native-mod.rc TEST_XFAILS_STAGE0 += $(S)src/test/run-pass/native-mod.rc endif BENCH_RS = $(wildcard $(S)src/test/bench/shootout/*.rs) \ $(wildcard $(S)src/test/bench/99-bottles/*.rs) RPASS_RC = $(wildcard $(S)src/test/run-pass/*.rc) RPASS_RS = $(wildcard $(S)src/test/run-pass/*.rs) $(BENCH_RS) RFAIL_RC = $(wildcard $(S)src/test/run-fail/*.rc) RFAIL_RS = $(wildcard $(S)src/test/run-fail/*.rs) CFAIL_RC = $(wildcard $(S)src/test/compile-fail/*.rc) CFAIL_RS = $(wildcard $(S)src/test/compile-fail/*.rs) ifdef CHECK_XFAILS TEST_RPASS_CRATES_BOOT = $(filter $(TEST_XFAILS_BOOT), $(RPASS_RC)) TEST_RPASS_CRATES_STAGE0 = $(filter $(TEST_XFAILS_STAGE0), $(RPASS_RC)) TEST_RPASS_SOURCES_BOOT = $(filter $(TEST_XFAILS_BOOT), $(RPASS_RS)) TEST_RPASS_SOURCES_STAGE0 = $(filter $(TEST_XFAILS_STAGE0), $(RPASS_RS)) else TEST_RPASS_CRATES_BOOT = $(filter-out $(TEST_XFAILS_BOOT), $(RPASS_RC)) TEST_RPASS_CRATES_STAGE0 = $(filter-out $(TEST_XFAILS_STAGE0), $(RPASS_RC)) TEST_RPASS_SOURCES_BOOT = $(filter-out $(TEST_XFAILS_BOOT), $(RPASS_RS)) TEST_RPASS_SOURCES_STAGE0 = $(filter-out $(TEST_XFAILS_STAGE0), $(RPASS_RS)) endif TEST_RPASS_EXES_BOOT = \ $(subst $(S)src/,,$(TEST_RPASS_CRATES_BOOT:.rc=.boot$(X))) \ $(subst $(S)src/,,$(TEST_RPASS_SOURCES_BOOT:.rs=.boot$(X))) TEST_RPASS_EXES_STAGE0 = \ $(subst $(S)src/,,$(TEST_RPASS_CRATES_STAGE0:.rc=.stage0$(X))) \ $(subst $(S)src/,,$(TEST_RPASS_SOURCES_STAGE0:.rs=.stage0$(X))) TEST_RPASS_OUTS_BOOT = \ $(TEST_RPASS_EXES_BOOT:.boot$(X)=.boot.out) TEST_RPASS_OUTS_STAGE0 = \ $(TEST_RPASS_EXES_STAGE0:.stage0$(X)=.stage0.out) TEST_RPASS_TMPS_BOOT = \ $(TEST_RPASS_EXES_BOOT:.boot$(X)=.boot$(X).tmp) TEST_RPASS_TMPS_STAGE0 = \ $(TEST_RPASS_EXES_STAGE0:.stage0$(X)=.stage0$(X).tmp) TEST_RFAIL_CRATES_BOOT = $(filter-out $(TEST_XFAILS_BOOT), $(RFAIL_RC)) TEST_RFAIL_CRATES_STAGE0 = $(filter-out $(TEST_XFAILS_STAGE0), $(RFAIL_RC)) TEST_RFAIL_SOURCES_BOOT = $(filter-out $(TEST_XFAILS_BOOT), $(RFAIL_RS)) TEST_RFAIL_SOURCES_STAGE0 = $(filter-out $(TEST_XFAILS_STAGE0), $(RFAIL_RS)) TEST_RFAIL_EXES_BOOT = \ $(subst $(S)src/,,$(TEST_RFAIL_CRATES_BOOT:.rc=.boot$(X))) \ $(subst $(S)src/,,$(TEST_RFAIL_SOURCES_BOOT:.rs=.boot$(X))) TEST_RFAIL_EXES_STAGE0 = \ $(subst $(S)src/,,$(TEST_RFAIL_CRATES_STAGE0:.rc=.stage0$(X))) \ $(subst $(S)src/,,$(TEST_RFAIL_SOURCES_STAGE0:.rs=.stage0$(X))) TEST_RFAIL_OUTS_BOOT = \ $(TEST_RFAIL_EXES_BOOT:.boot$(X)=.boot.out) TEST_RFAIL_OUTS_STAGE0 = \ $(TEST_RFAIL_EXES_STAGE0:.stage0$(X)=.stage0.out) TEST_RFAIL_TMPS_BOOT = \ $(TEST_RFAIL_EXES_BOOT:.boot$(X)=.boot$(X).tmp) TEST_RFAIL_TMPS_STAGE0 = \ $(TEST_RFAIL_EXES_STAGE0:.stage0$(X)=.stage0$(X).tmp) TEST_CFAIL_CRATES_BOOT = $(filter-out $(TEST_XFAILS_BOOT), $(CFAIL_RC)) TEST_CFAIL_CRATES_STAGE0 = $(filter-out $(TEST_XFAILS_STAGE0), $(CFAIL_RC)) TEST_CFAIL_SOURCES_BOOT = $(filter-out $(TEST_XFAILS_BOOT), $(CFAIL_RS)) TEST_CFAIL_SOURCES_STAGE0 = $(filter-out $(TEST_XFAILS_STAGE0), $(CFAIL_RS)) TEST_CFAIL_EXES_BOOT = \ $(subst $(S)src/,,$(TEST_CFAIL_CRATES_BOOT:.rc=.boot$(X))) \ $(subst $(S)src/,,$(TEST_CFAIL_SOURCES_BOOT:.rs=.boot$(X))) TEST_CFAIL_EXES_STAGE0 = \ $(subst $(S)src/,,$(TEST_CFAIL_CRATES_STAGE0:.rc=.stage0$(X))) \ $(subst $(S)src/,,$(TEST_CFAIL_SOURCES_STAGE0:.rs=.stage0$(X))) TEST_CFAIL_OUTS_BOOT = \ $(TEST_CFAIL_EXES_BOOT:.boot$(X)=.boot.out) TEST_CFAIL_OUTS_STAGE0 = \ $(TEST_CFAIL_EXES_STAGE0:.stage0$(X)=.stage0.out) TEST_CFAIL_TMPS_BOOT = \ $(TEST_CFAIL_EXES_BOOT:.boot$(X)=.boot$(X).tmp) TEST_CFAIL_TMPS_STAGE0 = \ $(TEST_CFAIL_EXES_STAGE0:.stage0$(X)=.stage0$(X).tmp) ALL_TEST_CRATES = $(TEST_CFAIL_CRATES_BOOT) \ $(TEST_RFAIL_CRATES_BOOT) \ $(TEST_RPASS_CRATES_BOOT) \ $(TEST_CFAIL_CRATES_STAGE0) \ $(TEST_RFAIL_CRATES_STAGE0) \ $(TEST_RPASS_CRATES_STAGE0) ALL_TEST_SOURCES = $(TEST_CFAIL_SOURCES_BOOT) \ $(TEST_RFAIL_SOURCES_BOOT) \ $(TEST_RPASS_SOURCES_BOOT) \ $(TEST_CFAIL_SOURCES_STAGE0) \ $(TEST_RFAIL_SOURCES_STAGE0) \ $(TEST_RPASS_SOURCES_STAGE0) # The test suite currently relies on logging to validate results so # make sure that logging uses the default configuration unexport RUST_LOG check_nocompile: $(TEST_CFAIL_OUTS_BOOT) \ $(TEST_CFAIL_OUTS_STAGE0) check: tidy \ $(TEST_RPASS_EXES_BOOT) $(TEST_RFAIL_EXES_BOOT) \ $(TEST_RPASS_OUTS_BOOT) $(TEST_RFAIL_OUTS_BOOT) \ $(TEST_CFAIL_OUTS_BOOT) \ $(TEST_RPASS_EXES_STAGE0) $(TEST_RFAIL_EXES_STAGE0) \ $(TEST_RPASS_OUTS_STAGE0) $(TEST_RFAIL_OUTS_STAGE0) \ $(TEST_CFAIL_OUTS_STAGE0) compile-check: tidy \ $(TEST_RPASS_EXES_BOOT) $(TEST_RFAIL_EXES_BOOT) \ $(TEST_RPASS_EXES_STAGE0) $(TEST_RFAIL_EXES_STAGE0) ###################################################################### # Testing rules ###################################################################### %.stage0$(X): %.stage0.o $(SREQ0) @$(call E, link [gcc]: $@) $(Q)gcc $(CFG_GCC_CFLAGS) stage0/glue.o -o $@ $< \ -Lstage0 -Lrt -lrustrt -lstd -lm @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. -$(Q)$(CFG_DSYMUTIL) $@ %.stage1(X): %.stage1.o $(SREQ1) @$(call E, link [gcc]: $@) $(Q)gcc $(CFG_GCC_CFLAGS) stage1/glue.o -o $@ $< \ -Lstage1 -Lrt -lrustrt -lstd -lm @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. -$(Q)$(CFG_DSYMUTIL) $@ %.stage2$(X): %.stage2.o $(SREQ2) @$(call E, link [gcc]: $@) $(Q)gcc $(CFG_GCC_CFLAGS) stage2/glue.o -o $@ $< \ -Lstage2 -Lrt -lrustrt -lstd -lm @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. -$(Q)$(CFG_DSYMUTIL) $@ %.boot$(X): %.rs $(BREQ) @$(call E, compile [boot]: $@) $(BOOT) -o $@ $< %.boot$(X): %.rc $(BREQ) @$(call E, compile [boot]: $@) $(BOOT) -o $@ $< %.stage0.o: %.rc $(SREQ0) @$(call E, compile [stage0]: $@) $(STAGE0) -c -o $@ $< %.stage0.o: %.rs $(SREQ0) @$(call E, compile [stage0]: $@) $(STAGE0) -c -o $@ $< %.stage1.o: %.rc $(SREQ1) @$(call E, compile [stage1]: $@) $(STAGE1) -c -o $@ $< %.stage1.o: %.rs $(SREQ1) @$(call E, compile [stage1]: $@) $(STAGE1) -c -o $@ $< %.stage2.o: %.rc $(SREQ2) @$(call E, compile [stage2]: $@) $(STAGE2) -c -o $@ $< %.stage2.o: %.rs $(SREQ2) @$(call E, compile [stage2]: $@) $(STAGE2) -c -o $@ $< # Cancel the implicit .out rule in GNU make. %.out: % %.out: %.out.tmp $(Q)mv $< $@ test/run-pass/%.out.tmp: test/run-pass/%$(X) rt/$(CFG_RUNTIME) $(Q)rm -f $<.tmp @$(call E, run: $@) $(Q)$(call CFG_RUN_TEST, $<) > $@ test/bench/shootout/%.out.tmp: test/bench/shootout/%$(X) \ rt/$(CFG_RUNTIME) $(Q)rm -f $<.tmp @$(call E, run: $@) $(Q)$(call CFG_RUN_TEST, $<) > $@ test/bench/99-bottles/%.out.tmp: test/bench/99-bottles/%$(X) \ rt/$(CFG_RUNTIME) $(Q)rm -f $<.tmp @$(call E, run: $@) $(Q)$(call CFG_RUN_TEST, $<) > $@ test/run-fail/%.out.tmp: test/run-fail/%$(X) \ rt/$(CFG_RUNTIME) $(Q)rm -f $<.tmp @$(call E, run: $@) $(Q)grep -q error-pattern $(S)src/test/run-fail/$(basename $*).rs $(Q)rm -f $@ $(Q)$(call CFG_RUN_TEST, $<) >$@ 2>&1 ; X=$$? ; \ if [ $$X -eq 0 ] ; then exit 1 ; else exit 0 ; fi $(Q)grep --text --quiet \ "$$(grep error-pattern $(S)src/test/run-fail/$(basename $*).rs \ | cut -d : -f 2- | tr -d '\n\r')" $@ test/compile-fail/%.boot.out.tmp: test/compile-fail/%.rs $(BREQ) @$(call E, compile [boot]: $@) $(Q)grep -q error-pattern $< $(Q)rm -f $@ $(BOOT) -o $(@:.out=$(X)) $< >$@ 2>&1; test $$? -ne 0 $(Q)grep --text --quiet \ "$$(grep error-pattern $< | cut -d : -f 2- | tr -d '\n\r')" $@ test/compile-fail/%.stage0.out.tmp: test/compile-fail/%.rs $(SREQ0) @$(call E, compile [stage0]: $@) $(Q)grep -q error-pattern $< $(Q)rm -f $@ $(STAGE0) -o $(@:.out=$(X)) $< >$@ 2>&1; test $$? -ne 0 $(Q)grep --text --quiet \ "$$(grep error-pattern $< | cut -d : -f 2- | tr -d '\n\r')" $@ ###################################################################### # Auto-dependency ###################################################################### ML_DEPFILES := $(BOOT_MLS:%.ml=%.d) C_DEPFILES := $(RUNTIME_CS:%.cpp=%.d) $(RUSTLLVM_LIB_CS:%.cpp=%.d) \ $(RUSTLLVM_OBJS_CS:%.cpp=%.d) rt/%.d: rt/%.cpp $(MKFILES) @$(call E, dep: $@) $(Q)$(call CFG_DEPEND_C, $@ \ $(subst $(S)src/,,$(patsubst %.cpp, %.o, $<)), \ $(RUNTIME_INCS)) $< >$@.tmp $(Q)$(CFG_PATH_MUNGE) $@.tmp $(Q)rm -f $@.tmp.bak $(Q)mv $@.tmp $@ rustllvm/%.d: rustllvm/%.cpp $(MKFILES) @$(call E, dep: $@) $(Q)$(call CFG_DEPEND_C, $@ \ $(subst $(S)src/,,$(patsubst %.cpp, %.o, $<)), \ $(CFG_LLVM_CXXFLAGS) $(RUSTLLVM_INCS)) $< >$@.tmp $(Q)$(CFG_PATH_MUNGE) $@.tmp $(Q)rm -f $@.tmp.bak $(Q)mv $@.tmp $@ %.d: %.ml $(MKFILES) @$(call E, dep: $@) $(Q)ocamldep$(OPT) -slash $(BOOT_ML_DEP_INCS) $< >$@.tmp $(Q)$(CFG_PATH_MUNGE) $@.tmp $(Q)rm -f $@.tmp.bak $(Q)perl -i.bak -pe "s@$(S)src/@@go" $@.tmp $(Q)rm -f $@.tmp.bak $(Q)mv $@.tmp $@ %.d: %.mli $(MKFILES) @$(call E, dep: $@) $(Q)ocamldep$(OPT) -slash $(BOOT_ML_DEP_INCS) $< >$@.tmp $(Q)$(CFG_PATH_MUNGE) $@.tmp $(Q)rm -f $@.tmp.bak $(Q)perl -i.bak -pe "s@$(S)src/@@go" $@.tmp $(Q)rm -f $@.tmp.bak $(Q)mv $@.tmp $@ ifneq ($(MAKECMDGOALS),clean) -include $(ML_DEPFILES) $(C_DEPFILES) endif RUSTBOOT_PROBE := $(wildcard boot/rustboot$(X)) ifneq ($(RUSTBOOT_PROBE),) CFG_INFO := $(info cfg: using built boot/rustboot$(X) for rust deps) CRATE_DEPFILES := $(subst $(S)src/,,$(ALL_TEST_CRATES:%.rc=%.d)) \ boot/$(CFG_STDLIB).d \ stage0/rustc$(X).d \ stage0/$(CFG_STDLIB).d boot/$(CFG_STDLIB).d: $(STDLIB_CRATE) $(STDLIB_INPUTS) \ $(MKFILES) boot/rustboot$(X) @$(call E, dep: $@) $(BOOT) -o $(patsubst %.d,%$(X),$@) -shared -rdeps $< >$@.tmp $(Q)$(CFG_PATH_MUNGE) $@.tmp $(Q)rm -f $@.tmp.bak $(Q)mv $@.tmp $@ stage0/rustc$(X).d: $(COMPILER_CRATE) $(COMPILER_INPUTS) \ $(STDLIB_CRATE) $(MKFILES) boot/rustboot$(X) @$(call E, dep: $@) $(BOOT) -o $(patsubst %.d,%$(X),$@) -shared -rdeps $< >$@.tmp $(Q)$(CFG_PATH_MUNGE) $@.tmp $(Q)rm -f $@.tmp.bak $(Q)mv $@.tmp $@ %.d: %.rc $(MKFILES) boot/rustboot$(X) @$(call E, dep: $@) $(BOOT) -o $(patsubst %.d,%$(X),$@) -rdeps $< >$@.tmp $(Q)$(CFG_PATH_MUNGE) $@.tmp $(Q)rm -f $@.tmp.bak $(Q)mv $@.tmp $@ ifneq ($(MAKECMDGOALS),clean) -include $(CRATE_DEPFILES) endif endif depend: boot/rustboot$(X) $(CRATE_DEPFILES) $(ML_DEPFILES) $(C_DEPFILES) ###################################################################### # Re-configuration ###################################################################### config.mk: $(S)configure $(S)Makefile.in @$(call E, cfg: reconfiguring) $(S)configure $(CFG_CONFIGURE_ARGS) ###################################################################### # Distribution ###################################################################### PKG_NAME := rust PKG_VER = $(shell date +"%Y-%m-%d")-snap PKG_DIR = $(PKG_NAME)-$(PKG_VER) PKG_TAR = $(PKG_DIR).tar.gz PKG_3RDPARTY := rt/valgrind.h rt/memcheck.h \ rt/isaac/rand.h rt/isaac/standard.h \ rt/uthash/uthash.h rt/uthash/utlist.h \ rt/bigint/bigint.h rt/bigint/bigint_int.cpp \ rt/bigint/bigint_ext.cpp rt/bigint/low_primes.h PKG_FILES = \ $(wildcard $(S)src/etc/*.*) \ $(S)LICENSE.txt $(S)README \ $(S)configure $(S)Makefile.in \ $(addprefix $(S)src/, \ README boot/README comp/README \ $(filter-out $(GENERATED), $(BOOT_MLS)) \ $(RUNTIME_CS) $(RUNTIME_HDR) \ $(RUSTLLVM_LIB_CS) $(RUSTLLVM_OBJS_CS) \ $(RUSTLLVM_HDR) \ $(PKG_3RDPARTY)) \ $(GENERATED) \ $(S)src/boot/fe/lexer.ml \ $(COMPILER_INPUTS) \ $(STDLIB_INPUTS) \ $(ALL_TEST_INPUTS) \ $(GENERATED) dist: $(PKG_TAR) $(PKG_TAR): $(GENERATED) @$(call E, making dist dir) $(Q)rm -Rf dist $(Q)mkdir -p dist/$(PKG_DIR) $(Q)tar -c $(PKG_FILES) | tar -x -C dist/$(PKG_DIR) $(Q)tar -czf $(PKG_TAR) -C dist $(PKG_DIR) $(Q)rm -Rf dist distcheck: $(PKG_TAR) $(Q)rm -Rf dist $(Q)mkdir -p dist @$(call E, unpacking $(PKG_TAR) in dist/$(PKG_DIR)) $(Q)cd dist && tar -xzf ../$(PKG_TAR) @$(call E, configuring in dist/$(PKG_DIR)-build) $(Q)mkdir -p dist/$(PKG_DIR)-build $(Q)cd dist/$(PKG_DIR)-build && ../$(PKG_DIR)/configure @$(call E, making 'check' in dist/$(PKG_DIR)-build) $(Q)make -C dist/$(PKG_DIR)-build check @$(call E, making 'clean' in dist/$(PKG_DIR)-build) $(Q)make -C dist/$(PKG_DIR)-build clean $(Q)rm -Rf dist @echo @echo ----------------------------------------------- @echo $(PKG_TAR) ready for distribution @echo ----------------------------------------------- ###################################################################### # Cleanup ###################################################################### .PHONY: clean tidy: @$(call E, check: formatting) $(Q)echo \ $(filter-out $(GENERATED) $(addprefix $(S)src/, $(GENERATED)) \ $(addprefix $(S)src/, $(RUSTLLVM_LIB_CS) $(RUSTLLVM_OBJS_CS) \ $(RUSTLLVM_HDR) $(PKG_3RDPARTY)) \ $(S)src/etc/%, $(PKG_FILES)) \ | xargs -n 10 python $(S)src/etc/tidy.py clean: @$(call E, cleaning) $(Q)rm -f $(RUNTIME_OBJS) $(RUNTIME_DEF) $(Q)rm -f $(RUSTLLVM_LIB_OBJS) $(RUSTLLVM_OBJS_OBJS) $(RUSTLLVM_DEF) $(Q)rm -f $(BOOT_CMOS) $(BOOT_CMIS) $(BOOT_CMXS) $(BOOT_OBJS) $(Q)rm -f $(ML_DEPFILES) $(C_DEPFILES) $(CRATE_DEPFILES) $(Q)rm -f $(ML_DEPFILES:%.d=%.d.tmp) $(Q)rm -f $(C_DEPFILES:%.d=%.d.tmp) $(Q)rm -f $(CRATE_DEPFILES:%.d=%.d.tmp) $(Q)rm -f $(GENERATED) $(Q)rm -f boot/rustboot$(X) boot/$(CFG_STDLIB) $(Q)rm -f stage0/rustc$(X) stage0/$(CFG_STDLIB) stage0/glue* $(Q)rm -f stage1/rustc$(X) stage1/$(CFG_STDLIB) stage1/glue* $(Q)rm -f stage2/rustc$(X) stage2/$(CFG_STDLIB) stage2/glue* $(Q)rm -f rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME) $(Q)rm -Rf $(PKG_NAME)-*.tar.gz dist $(Q)rm -f $(foreach ext,cmx cmi cmo cma bc o a d exe,\ $(wildcard boot/*/*.$(ext) boot/*/*/*.$(ext))) $(Q)rm -f $(foreach ext,o a d bc s exe,$(wildcard stage*/*.$(ext))) $(Q)rm -Rf $(foreach ext,out out.tmp \ boot$(X) stage0$(X) stage1$(X) stage2$(X) \ bc o s exe dSYM, \ $(wildcard test/*/*.$(ext) test/bench/*/*.$(ext))) $(Q)rm -Rf $(foreach ext, \ aux cp fn ky log pdf html pg toc tp vr cps, \ $(wildcard doc/*.$(ext))) $(Q)rm -Rf doc/version.texi