################################################################################
-# Desc: Mihrtec Standard Transpilation Makefile
-# Author: Mihrtec LLC
+# 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 autopresidential debate california timematically compiled into an environment-dependent object
+# 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
-# Source languages handled by this build system
+# Base directories
+# 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.
+c_FLAGS := $(strip $(CFLAGS)) -I$(SRC_DIR)
c_LIBS := SDL2 wolfssl
c_SRCL := y
cpp_C := $(strip $(notdir $(CXX)))
g++_LDLIBS := $(cc_LDLIBS)
em++_LDLIBS :=
go_LDLIBS := $(cc_LDLIBS)
-# Directories
-# The directory in './' containing app drivers and compilation info
-DRIVER_DIR := bin
-ROOT_DIR := ..
+# 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) $(LCLLIB_DIR)
+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 './' and produce a
-# single object file in './' containing all of the module's symbols and
-# binaries.
-MODULES := $(filter-out $(DRIVER_DIR),$(subst /,,$(shell ls -d */)))
+# 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)/*/)))
#AWK_REVERSE_SQUASH##############################################################
# The following awk program reverses the order of a list while also removing
define PREMAKE_SOURCE_COMPILER =
# Find the sources for each source-to-source language
$(foreach slang,$(SLANGS),
-$(eval SLANG_SRC := $(patsubst ./%, %,$(shell find -name "*.$(slang)" -not -name ".*")))
+$(eval SLANG_SRC := $(shell find $(SRC_DIR) -name "*.$(slang)" -not -name ".*"))
# Foreach target type in the source-to-source language, add this source's
# targets to the list of the current source-to-source language targets
$(eval undefine SLANG_TRG)
$(eval OLDER_TIME := $(firstword $(sort $(NEWEST_TRG_TIME) $(SRC_TIME))))
# If the older of the two times is the newest target time found, then we need to
# rebuild, but only if our build rule intends to actually make something. If it
-# does not intend to make something, drop a functional rule to actually make the
-# target
+# instead does not intend to actually make a target, drop a functional rule that
+# could hypothetically make the target for debugging and analysis purposes
$(if $(MAKECMDGOALS),
$(eval BUILDGOALS := $(filter-out clean scrub purge uninstall,$(MAKECMDGOALS))),
$(eval BUILDGOALS := all))
# some kind of user error #######################################################
define SRC_LANG_RULE =
$(if $($1),,$(eval $1 := t)\
-$(eval MOD := $(filter $(MODULES),$(firstword $(subst /, ,$(dir $1)))))\
+$(eval MOD := $(filter $(MODULES),$(firstword $(subst /, ,$(subst $(SRC_DIR),,$(dir $1))))))\
$(eval FLG := $(MOD:%=-I% ))\
$(if $(wildcard $1),
-$(eval DEPS := $(filter-out \ %:,$(shell $($2_C) $(FLG) -M -MG $1)))\
+$(eval DEPS := $(filter-out \ %:,$(shell $($2_C) $(FLG) -M -MG $1)))\
+$(eval DDEPS := $(filter $(DRIVER_DIR:$(SRC_DIR)/%=%/%),$(DEPS)))\
$(eval MDEPS := $(filter $(MODULES:%=%/%),$(DEPS)))\
-$(eval LOST := $(filter-out \ %: $(DRIVER_DIR)/% $(MODULES:%=%/%),$(shell $($2_C) $(FLG) -MM -MG $1)))\
+$(eval DEPS := $(filter-out $(DDEPS) $(MDEPS),$(DEPS)))\
+$(eval MDEPS := $(MDEPS:%=$(SRC_DIR)/%))\
+$(eval DDEPS := $(DDEPS:%=$(SRC_DIR)/%))\
+$(eval LOST := $(filter-out \ %: $(DRIVER_DIR:./%=%)/% $(MODULES:%=$(SRC_DIR:./%=%)/%/%),$(shell $($2_C) $(FLG) -MM -MG $1)))\
$(eval MDEPS += $(LOST:%=$(dir $1)%))\
-$(eval MDEPS := $(shell echo $(MDEPS) | sed -e 's@[a-zA-Z0-9\-\+/]*\.\./include@../include@g'))\
-$(eval ALLDEPS := $(MDEPS) $(DEPS)),\
+$(eval MDEPS := $(shell echo $(MDEPS) | sed -e 's@[a-zA-Z0-9\-\+/]*\.\./include@$(LIBINC_DIR)@g'))\
+$(eval ALLDEPS := $(DDEPS) $(MDEPS) $(DEPS)),\
$(error Cannot generate deps for: $1, file not found))\
$(eval SRC_OBJ := $(basename $1).$($2_OBJ))\
$(eval MAKE_TARGETS += $(SRC_OBJ))
# establish a build and link rule given a source driver and language ############
define SRC_LANG_DRVRULE =
$(eval DRIVER_NAME := $(basename $(notdir $1)))
-$(eval DRIVER_TARG := $(1:%.$2=$(ROOT_DIR)/%$($2_OUT)))
+$(eval DRIVER_TARG := $(1:$(SRC_DIR)/%.$2=$(ROOT_DIR)/%$($2_OUT)))
$(eval DRIVER_SOB := $(basename $1).$($2_OBJ))
# Generate a rule for the driver object
$(foreach module_dep,$(MDEPS),
$(eval DRIVER_MODULES += $(firstword $(subst /, ,$(module_dep))))
)
-$(eval DRIVER_MODULES := $(filter-out $(DRIVER_DIR) ..,$(sort $(DRIVER_MODULES))))
+$(eval DRIVER_MODULES := $(filter-out $(DRIVER_DIR) . ..,$(sort $(DRIVER_MODULES))))
# In the event that the driver developer does not wish to include a header to
# any internal modules, the developer may instead create a file with the same
$(eval DRIVER_MODULES += $(filter-out -l%,$(DRIVER_LDVALS)))
# List of module archives to link together during compilation
-$(eval DRIVER_ARCHIVES := $(DRIVER_MODULES:%=%.$($2_AROBJ)))
+$(eval DRIVER_ARCHIVES := $(DRIVER_MODULES:%=$(SRC_DIR)/%.$($2_AROBJ)))
$(eval DRIVER_DEPS := $(DRIVER_SOB) $(DRIVER_ARCHIVES))
-$(eval DRIVER_DBGARCHIVES := $(DRIVER_MODULES:%=.$($2_DBG)/%.$($2_AROBJ)))
+$(eval DRIVER_DBGARCHIVES := $(DRIVER_MODULES:%=$(SRC_DIR)/.$($2_DBG)/%.$($2_AROBJ)))
$(eval DRIVER_DBGDEPS := $(dir $(DRIVER_SOB)).$($2_DBG)/$(notdir $(DRIVER_SOB)))
$(eval DRIVER_DBGDEPS += $(DRIVER_DBGARCHIVES))
$(eval STLIBS := $($2_LIBS)))
# Directory setup
-$(eval DRIVER_TARG_DIR := $(dir $(1:%.$2=$(ROOT_DIR)/%)))
+$(eval DRIVER_TARG_DIR := $(dir $(1:$(SRC_DIR)/%.$2=$(ROOT_DIR)/%)))
$(eval MAKE_DIRS += $(DRIVER_TARG_DIR))
$(if $($2_DBG),$(eval MAKE_DIRS += $(DRIVER_TARG_DIR).$($2_DBG)))
$(eval ARCDEPS := $(filter $1/%.$(c_OBJ),$(foreach lang,$(LANGS),$($(lang)_MOD_TRG))))\
$(eval MAKE_TARGETS+= $1.$(c_AROBJ))\
-$1.$(c_AROBJ): $(ARCDEPS)
+$(SRC_DIR)/$1.$(c_AROBJ): $(ARCDEPS)
$(c_AR) cr $$@ $$^
$(if $(c_DBG),
$(eval undefine DBGARCDEPS)
$(foreach arcdep,$(ARCDEPS),$(eval DBGARCDEPS += $(dir $(arcdep)).$(c_DBG)/$(notdir $(arcdep))))
$(eval MAKE_TARGETS+= .$(c_DBG)/$1.$(c_AROBJ))\
-.$(c_DBG)/$1.$(c_AROBJ): $(DBGARCDEPS) | .$(c_DBG)/
+$(SRC_DIR)/.$(c_DBG)/$1.$(c_AROBJ): $(DBGARCDEPS) | .$(c_DBG)/
$(c_AR) cr $$@ $$^
)
#/MODULE_ARCRULE#################################################################
$(foreach var, WEBTARG WEBINIT CVSGET CVSPASS CONFIGUREDBG,
$(eval undefine $(var)))
)
-# Include and evaluate such that it may be called and evaluated for immediate
-# evaluation of its contents
-define EVALINCLUDE =
-$(eval include $2.mk)
-endef
# If there is a .mk file for this lib, import it. Otherwise, we'll try to link
# it later, unless there is no linker for the language's compiler.
-$(if $(wildcard $2.mk),$(eval $(file <$2.mk)),\
+$(if $(wildcard $(CONF_DIR)/$2.mk),$(eval $(file <$(CONF_DIR)/$2.mk)),\
$(if $($($1_C)_LD),\
$(warning No $2.mk for lib$2, attempting to link from the system),\
$(error No $2.mk for lib$2 and '$($1_C)' is not configured for linking)))\
$1_OBJ := $($($1_C)_OBJ)
$1_OUT := $($($1_C)_OUT)
$1_AROBJ := $($($1_C)_AROBJ)
-$1_SOURCES := $(subst ./,,$(shell find -name "*.$1" -not -name ".*"))
+$1_SOURCES := $(shell find $(SRC_DIR) -name "*.$1" -not -name ".*")
$1_DBG := $($($1_C)_DBG)
$1_AR := $($($1_C)_AR)
)
# Find save language-specific driver and module sources and targets
$(eval $1_DRV_SRC := $(filter $(DRIVER_DIR)/%,$($1_SOURCES)))
-$(eval $1_DRV_TRG := $(patsubst %.$1,$(ROOT_DIR)/%$($1_OUT),$($1_DRV_SRC)))
+$(eval $1_DRV_TRG := $(patsubst $(SRC_DIR)/%.$1,$(ROOT_DIR)/%$($1_OUT),$($1_DRV_SRC)))
$(eval $1_MOD_SRC := $(filter-out $(DRIVER_DIR)/%,$($1_SOURCES)))
-$(eval $1_MOD_TRG := $(subst .$1,.$($1_OBJ),$($1_MOD_SRC)))
+$(eval $1_MOD_TRG := $(addsuffix .$($1_OBJ),$(basename $($1_MOD_SRC))))
# Add those sources and targets to a language-irreverant var
$(eval
DRV_SRC += $($1_DRV_SRC)
# Module Object Rules for each of them.
$(foreach module,$(MODULES),
# Evaluate the module sources for this language
-$(eval $(module)_$1_SRC := $(filter $(module)/%,$($1_MOD_SRC)))
+$(eval $(module)_$1_SRC := $(filter $(SRC_DIR)/$(module)/%,$($1_MOD_SRC)))
# Evaluate module targets for this language
$(eval $(module)_$1_TRG := $($(module)_$1_SRC:%.$1=%.$($1_OBJ)))
# Add these language-specific sources and targets to the module's src/targs
$(module)_TRG += $($(module)_$1_TRG)
)
# For every source file, create a build rule for it for our language
-$(foreach src,$(filter $(module)/%,$($1_MOD_SRC)),\
+$(foreach src,$(filter $(SRC_DIR)/$(module)/%,$($1_MOD_SRC)),\
$(eval $(call SRC_LANG_RULE,$(src),$1))\
))
# For all the listed libraries, initialize the library, which will set up all of