###################################################################### # 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 := CFG_GCC_LINK_FLAGS := CFG_BOOT_FLAGS := $(BOOT_FLAGS) CFG_RUSTC_FLAGS := -nowarn # 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 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 endif ifeq ($(CFG_OSTYPE), Linux) CFG_LIB_NAME=lib$(1).so CFG_GCC_CFLAGS += -fPIC -march=i686 CFG_GCC_LINK_FLAGS += -shared -fPIC -ldl -lpthread -lrt ifeq ($(CFG_CPUTYPE), x86_64) CFG_GCC_CFLAGS += -m32 CFG_GCC_LINK_FLAGS += -m32 endif CFG_UNIXY := 1 endif ifeq ($(CFG_OSTYPE), Darwin) CFG_LIB_NAME=lib$(1).dylib CFG_UNIXY := 1 CFG_GCC_LINK_FLAGS += -dynamiclib -lpthread # 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! CFG_GCC_CFLAGS += -m32 CFG_GCC_LINK_FLAGS += -m32 CFG_DSYMUTIL := dsymutil endif ifneq ($(findstring MINGW,$(CFG_OSTYPE)),) CFG_WINDOWSY := 1 endif CFG_LDPATH :=$(CFG_BUILD_DIR)/rt CFG_LDPATH :=$(CFG_LDPATH):$(CFG_BUILD_DIR)/llvmext 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_PROGRAM=PATH=$(CFG_LDPATH) $(1) CFG_PATH_MUNGE := $(strip | perl -p \ -e 's@\\(.)@/\1@go;' \ -e 's@^/([a-zA-Z])/@\1:/@o;') ifdef CFG_FLEXLINK CFG_BOOT_NATIVE := 1 endif CFG_GCC_CFLAGS += -march=i686 CFG_GCC_LINK_FLAGS += -shared -fPIC endif ifdef CFG_UNIXY CFG_INFO := $(info cfg: unix-y environment) CFG_EXE_SUFFIX := CFG_LDPATH :=$(CFG_LDPATH):$(CFG_LLVM_LIBDIR) CFG_RUN_PROGRAM=\ LD_LIBRARY_PATH=$(dir $(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_PROGRAM=PATH=$(CFG_LDPATH) $(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=$(S)src/etc/x86.supp endif endif CFG_RUNTIME :=$(call CFG_LIB_NAME,rustrt) CFG_LLVMEXT :=$(call CFG_LIB_NAME,llvmext) CFG_STDLIB :=$(call CFG_LIB_NAME,std) CFG_LLC_CFLAGS := -march=x86 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_LINK_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_LINK_FLAGS) -o $(1) CFG_DEPEND_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_CFLAGS) -MT "$(1)" -MM $(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 BOOT_PROFILE $(info cfg: forcing native bootstrap compiler (BOOT_PROFILE)) CFG_BOOT_NATIVE := 1 CFG_OCAMLOPT_PROFILE_FLAGS := -p endif ifdef BOOT_DEBUG $(info cfg: forcing bytecode bootstrap compiler (DEBUG)) CFG_BOOT_NATIVE := endif ifdef CFG_BOOT_NATIVE $(info cfg: building native bootstrap compiler) else $(info cfg: building bytecode bootstrap compiler) endif ifdef NO_VALGRIND $(info cfg: disabling valgrind (NO_VALGRIND)) CFG_VALGRIND := endif ###################################################################### # Target-and-rule "utility variables" ###################################################################### ifdef VERBOSE Q := E = else Q := @ E = echo $(1) endif R := $(CFG_RUN_PROGRAM) 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 stage0 STAGE0 := $(Q)$(CFG_RUN_PROGRAM) stage0/rustc$(X) $(CFG_RUSTC_FLAGS) -L stage1 STAGE1 := $(Q)$(CFG_RUN_PROGRAM) stage1/rustc$(X) $(CFG_RUSTC_FLAGS) -L stage2 # "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 effect 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 ###################################################################### # 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_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_INCS := -I $(S)src/rt/isaac -I $(S)src/rt/uthash RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o) ###################################################################### # rustc LLVM-extensions (C++) library variables ###################################################################### LLVMEXT_CS := $(addprefix llvmext/, \ MachOObjectFile.cpp Object.cpp RustWrapper.cpp) LLVMEXT_HDR := llvmext/include/llvm-c/Object.h LLVMEXT_INCS := -iquote $(CFG_LLVM_INCDIR) \ -iquote $(S)src/llvmext/include LLVMEXT_OBJS := $(LLVMEXT_CS:.cpp=.o) LLVMEXT_LIBS := $(CFG_LLVM_LDFLAGS) $(CFG_LLVM_LIBS) ###################################################################### # Standard library variables ###################################################################### STDLIB_CRATE := lib/std.rc STDLIB_INPUTS := $(wildcard $(addprefix $(S)src/lib/,*.rc *.rs */*.rs)) ###################################################################### # rustc crate variables ###################################################################### COMPILER_CRATE := comp/rustc.rc COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/comp/, \ rustc.rc *.rs */*.rs)) ###################################################################### # Single-target rules ###################################################################### all: boot/rustboot$(X) \ rt/$(CFG_RUNTIME) \ llvmext/$(CFG_LLVMEXT) \ stage0/$(CFG_STDLIB) \ stage1/$(CFG_STDLIB) \ stage0/rustc$(X) \ stage0/glue.o \ $(GENERATED) rt/$(CFG_RUNTIME): $(RUNTIME_OBJS) $(MKFILES) $(RUNTIME_HDR) @$(call E, link: $@) $(Q)$(call CFG_LINK_C, $@) $(RUNTIME_OBJS) llvmext/$(CFG_LLVMEXT): $(LLVMEXT_OBJS) $(MKFILES) $(LLVMEXT_HDR) @$(call E, link: $@) $(Q)$(call CFG_LINK_C, $@ $(LLVMEXT_OBJS) \ $(CFG_LLVM_LIBS) $(CFG_LLVM_LDFLAGS)) 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)git log -1 \ --pretty=format:'let version = "prerelease (%h %ci)";;' >$@ || exit 1 stage0/$(CFG_STDLIB): $(S)src/$(STDLIB_CRATE) $(STDLIB_INPUTS) \ boot/rustboot$(X) $(MKFILES) @$(call E, compile: $@) $(BOOT) -shared -o $@ $< stage1/$(CFG_STDLIB): $(S)src/$(STDLIB_CRATE) $(STDLIB_INPUTS) \ stage0/rustc$(X) $(MKFILES) @$(call E, compile: $@) $(STAGE0) -shared -o $@ $< stage0/rustc$(X): $(S)src/$(COMPILER_CRATE) $(COMPILER_INPUTS) \ boot/rustboot$(X) rt/$(CFG_RUNTIME) \ stage0/$(CFG_STDLIB) @$(call E, compile: $@) $(BOOT) -minimal -o $@ $< $(Q)chmod 0755 $@ stage1/rustc$(X): $(S)src/$(COMPILER_CRATE) $(COMPILER_INPUTS) \ stage0/rustc$(X) rt/$(CFG_RUNTIME) \ stage1/$(CFG_STDLIB) @$(call E, compile: $@) $(STAGE0) -o $@ $< $(Q)chmod 0755 $@ stage0/glue.bc: stage0/rustc$(X) stage0/$(CFG_STDLIB) \ llvmext/$(CFG_LLVMEXT) rt/$(CFG_RUNTIME) @$(call E, generate: $@) $(STAGE0) -o $@ -glue stage1/glue.bc: stage1/rustc$(X) stage1/$(CFG_STDLIB) \ llvmext/$(CFG_LLVMEXT) rt/$(CFG_RUNTIME) @$(call E, generate: $@) $(STAGE1) -o $@ -glue ###################################################################### # Pattern rules ###################################################################### rt/%.o: rt/%.cpp $(MKFILES) @$(call E, compile: $@) $(Q)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $< llvmext/%.o: llvmext/%.cpp $(MKFILES) @$(call E, compile: $@) $(Q)$(call CFG_COMPILE_C, $@, $(CFG_LLVM_CXXFLAGS) $(LLVMEXT_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 $@ $< %.o: %.s @$(call E, assemble [llvm]: $@) $(Q)gcc $(CFG_GCC_CFLAGS) -o $@ -c $< %.ll: %.bc @$(call E, dis [llvm]: $@) $(Q)$(CFG_LLVM_BINDIR)/llvm-dis -o $@ $< %.s: %.bc @$(call E, compile [llvm]: $@) $(Q)$(CFG_LLVM_BINDIR)/llc $(CFG_LLC_CFLAGS) -o $@ $< ###################################################################### # Cleanup ###################################################################### .PHONY: clean clean: @$(call E, cleaning) $(Q)rm -f $(foreach ext, cmx cmi cmo cma bc o a d $(X) \ h cpp ml s \ out bc dSYM \ , \ $(wildcard *.$(ext) \ */*.$(ext) \ */*/*.$(ext) \ */*/*/*.$(ext) \ ))