################################################################################ # Desc: Web Cross Compiler # Author: Ken Grimes # Date: 2016 ################################################################################ # This makefile manages a build environment targeting native platforms with gcc # and web platforms with either emscripten or binaryen (js or wasm). ################################################################################ # Each .c file is automatically compiled into an environment-dependent object # file of compiler-specific format (.o for gcc, .bc for llvm/emcc/em++). ################################################################################ # The default rule to be built if none specified default: all # webcc's root ROOT_DIR := . # source directory to find compilable language files in SRC_DIR := $(ROOT_DIR)/src # directory where files with 'main' functions live (can be in SRC_DIR) DRIVER_DIR := $(SRC_DIR)/bin # make configuration directory CONF_DIR := $(ROOT_DIR)/make # Source languages handled by this build system. These languages are capable of # being compiled to an intermediary format for binary output by one of the # provided compilersfor each language LANGS := c cpp go # Source-to-source languages handled by this build system SLANGS := y rl # Language-specific compilers and flags passed in from environment c_C := $(strip $(notdir $(CC))) c_FLAGS := $(strip $(CFLAGS)) -I$(SRC_DIR) c_SRCL := y cpp_C := $(strip $(notdir $(CXX))) cpp_FLAGS := $(strip $(CXXFLAGS)) $(c_FLAGS) go_C := gccgo go_FLAGS := $(c_FLAGS) # Source to source languages # Bison y_C := bison y_FLAGS := -d y_STEM := tab y_TRG := c h # Ragel rl_C := ragel rl_FLAGS := -C rl_TRG := c # Compiler-specific associations. Each compiler has a binary object suffix # (OBJ), an archiver (AR), and an archiver object suffix (AROBJ). Each compiler # may optionally have defined a linker (LD), and a binary output suffix (OUT). cc_OBJ := o cc_LD := $(LD) cc_AR := $(AR) cc_AROBJ := a cc_DBG := gdb $(cpp_C)_LD := $(cc_LD) gcc_OBJ := $(cc_OBJ) gcc_LD := $(cc_LD) ngcc_AR := $(cc_AR) gcc_AROBJ := $(cc_AROBJ) gcc_DBG := $(cc_DBG) emcc_OBJ := bc emcc_AR := emar emcc_AROBJ := $(emcc_OBJ) #emar is just a python script that reparses shit for emcc emcc_OUT := .js g++_OBJ := $(cc_OBJ) em++_OBJ := $(emcc_OBJ) em++_AR := $(emcc_AR) em++_AROBJ := $(emcc_AROBJ) em++_OUT := $(emcc_OUT) gccgo_OBJ := o gccgo_LD := $(cc_LD) gccgo_AR := $(cc_AR) gccgo_AROBJ := $(cc_AROBJ) # Shell functions to determine what libraries can be linked by the compiler cc_LDLIBS := $(shell ldconfig -p | sed -e 's@\-*[0-9\.]*\.so.*$$@@g' -e 's@\tlib@@g' -e '/[\t ]/d') gcc_LDLIBS := $(cc_LDLIBS) emcc_LDLIBS := g++_LDLIBS := $(cc_LDLIBS) em++_LDLIBS := go_LDLIBS := $(cc_LDLIBS) # location to build cross-compilation libraries in, not intended to be installed # in the host system LIB_DIR := $(ROOT_DIR)/lib$(shell uname -m)/$($(c_C)_OBJ) LIBDL_DIR := $(LIB_DIR)/.cache LIBINC_DIR := $(ROOT_DIR)/include # The makefile MUST be capable of generating these directories and all of their # contents. These directories are removed during the 'scrub' rule MAKE_DIRS := $(LIB_DIR) $(LIBDL_DIR) # Set up lib inclusions, and scan for built libs c_FLAGS += -I$(LIBINC_DIR) c_OBJ := $($(c_C)_OBJ) # Modules are any directories other than 'DRIVER_MODULE' in 'SRC_DIR' and # produce a single archive in 'SRC_DIR' containing all of the module's symbols MODULES := $(patsubst $(SRC_DIR)/%/,%,$(filter-out $(DRIVER_DIR)/%,$(shell ls -d $(SRC_DIR)/*/))) # Include the make libraries include make/lib/*.mk # If available, invoke the premake system ifdef PREMAKE_SOURCE_COMPILER $(eval $(call PREMAKE_SOURCE_COMPILER,)) else $(info Warning: No premake system found, source-to-source languages (e.g. bison) not functional) endif # Backup the CVS password and CVSROOT environment vars in case we change them $(if $(wildcard ~/.cvspass),\ $(eval CVSPASS_BAK := $(file <~/.cvspass))) $(if $(CVSROOT),\ $(eval CVSROOT_BAK := $(CVSROOT))) # The recursive library dependecy traversal constructs a tree ordered by nested # dependency depth. when linking, this order is reversed. # Initialize each language and look for its files ifdef LANG_INIT $(foreach lang,$(LANGS),\ $(eval $(call LANG_INIT,$(lang)))\ ) else $(error No LANG_INIT available, no languages can be compiled) endif # Create module object rules for each module $(foreach module,$(MODULES),\ $(eval $(call MODULE_ARCRULE,$(module)))\ ) $(if $(c_DBG),$(eval MAKE_DIRS += .$(c_DBG)/)) # Create lang-specific rules for producing final (linked) targets $(foreach lang,$(LANGS),\ $(foreach drvsrc,$($(lang)_DRV_SRC),\ $(eval $(call SRC_LANG_DRVRULE,$(drvsrc),$(lang)))\ )) # Create driver rules for each driver we found, let users call make specifying # the basename of the driver file, and just route to the correct e we # made in the last paragraph DRV_FNAMES := $(notdir $(DRV_SRC)) .PHONY: all $(basename $(DRV_NAMES)) $(foreach fname,$(DRV_FNAMES),\ $(eval $(basename $(fname)): \ $(filter %/$(basename $(fname))$($(lastword $(subst ., ,$(fname))_OUT)),$(DRV_TRG)))\ ) all: $(basename $(DRV_FNAMES)) @echo Build Complete # Rule to make any dirs that we're in charge of $(sort $(MAKE_DIRS)): @mkdir -p $@ # Cleaning rules. # Clean destroys all object files and internal module archives. CLEAN_TARGETS := $(sort $(foreach mtarg,$(MAKE_TARGETS),$(if $(wildcard $(mtarg)),$(mtarg)))) clean: $(BUILTLIBS:%=clean_%) $(if $(CLEAN_TARGETS),rm $(CLEAN_TARGETS)) # Scrub destroys all distributable binaries SCRUB_TARGETS := $(sort $(foreach starg,$(SCRUB_TARGETS),$(if $(wildcard $(starg)),$(starg)))) scrub: clean $(if $(SCRUB_TARGETS),rm $(SCRUB_TARGETS)) # Purge destroys all distributables created by a distributable binary # (e.g. assets) # Uninstall destroys all objects and directories that cannot be recreated by # this make file uninstall: scrub rm -Rf $(MAKE_DIRS)