X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fwebcc.git;a=blobdiff_plain;f=src%2FMakefile;h=5801e30230f9ec86ad928b0f29b3b83f866b8355;hp=8e0c926f94383706b5eddaff8fd7eb1e24285ca1;hb=c0288501d87f8aaacba73daee346e5adf71a9bd2;hpb=e77819fa39836d4fe0f81895297a4e78c95f5572 diff --git a/src/Makefile b/src/Makefile index 8e0c926..5801e30 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,120 +1,441 @@ -################################################## -#Desc: Mihrtec Standard Makefile -#Author: Mihrtec LLC -#Date: 2016 -################################################## -#Application Information -################################################## -#Executable name, also passed as -DAPPNAME to compiler -APPNAME := the_march -#Directory in which we expect to find main() -APPMODULE := core -#Compiler flags for the final executable -APPFLAGS := -#Object files statically linked for the executable -APPOBJ := -#Dependencies which must be built before the executable -APPDEPS := -#Directories containing independent tools for GNU -TOOLS := apc -################################################## -#Emscripten Info -################################################## -#Functions to export for JS Module -EXPORT_FUNCS := em_main auth_encrypt -#Flags to always run on emcc/em++ -EMFLAGS := - -#Import the build system setup -include .make/build.mk - -#Directories to be constructed -DIRS := $(sort $(dir $(APPDEPS) $(APPTARG))) - -#Targets that don't generate a file -.PHONY: $(APPNAME) run push dox doc clean scrub all default -#Define default rules to point to APPNAME -all default: $(APPTARG) - -#Build the executable -$(APPNAME) $(APPTARG): $(DIRS) $(APPDEPS) - $(APPC) -o $(APPTARG) $(APPFLAGS) $(APPSRC) - -#create directories -$(DIRS): +################################################################################ +# Desc: Mihrtec Standard Transpilation Makefile +# Author: Mihrtec LLC +# 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++). +################################################################################ +default: all +# Source languages handled by this build system +LANGS := c cpp go +# Language-specific compilers and flags passed in from environment +c_C := $(strip $(notdir $(CC))) +c_FLAGS := $(strip $(CFLAGS)) -I. +c_LIBS := SDL2_ttf SDL2_net SDL2_image SDL2 wolfssl +c_SRCL := y +cpp_C := $(strip $(notdir $(CXX))) +cpp_FLAGS := $(strip $(CXXFLAGS)) $(c_FLAGS) +cpp_LIBS := $(c_LIBS) +go_C := gccgo +go_FLAGS := $(c_FLAGS) +# Source to source languages +y_C := bison +y_FLAGS := -d +y_STEM := tab +y_DUP := h +y_CHDIR := t +# 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 +$(cpp_C)_LD := $(cc_LD) +gcc_OBJ := $(cc_OBJ) +gcc_LD := $(cc_LD) +gcc_AR := $(cc_AR) +gcc_AROBJ := $(cc_AROBJ) +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 | head -n -2 | grep -v Broken | sed -e 's@^.*lib\([_\+a-Z0-9\-]*\)\..*@\1@g' -e '1d') +gcc_LDLIBS := $(cc_LDLIBS) +emcc_LDLIBS := +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 := .. +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) +# Set up lib inclusions, and scan for built libs +c_FLAGS += -I$(LIBINC_DIR) +c_OBJ := $($(c_C)_OBJ) +# If we have a linker, include 'LIB_DIR' in the paths it looks in +$(foreach lang,$(LANGS),$(if $($($(lang)_C)_LD),$(eval\ +$(lang)_FLAGS += -L$(LIB_DIR)\ +))) +# 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 */))) + +# determine the dependencies of a given source and language, but route link +# issues to /dev/null since we will generate them later +# can pass an optional third argument for additional opts +define SRC_LANG_DEPS = +$(shell $($2_C) -MM -MG $(if $3,-I$3) $($2_FLAGS) $1 2> /dev/null\ +| sed -e 's@^.*\.o: @@' -e 's@\\@@') +endef + +# create a list of module object archives associated with the given files, +# if any, filtering out any drivers or non-module objects +define FLIST_MODULEOBJS = +$(sort $(shell echo $(filter-out .%,$(filter-out $(DRIVER_DIR)/%,$1))\ + | sed -e 's@^\([a-Z\-\+]*\)/*@\1.$(c_OBJ)@g' )) +endef + +# establish a dependency rule given a source and language. if passed a +# directory name as the third argument, will prefix all header files in the +# dependency with the local lib +define SRC_LANG_DEPRULE = +$(eval $1_$2_DEPS := $(call SRC_LANG_DEPS,$1,$2,$3)) +$(foreach hdr,$(filter %.h,$($1_$2_DEPS)),\ +$(if $(word 2,$(subst /, ,$(hdr))),,\ +$(eval $1_$2_DEPS := $($1_$2_DEPS:$(hdr)=$3/$(hdr)))\ +)) +$(basename $1).$($2_OBJ): $($1_$2_DEPS) +endef + +# establish a build and link rule given a source driver and language ############ +define SRC_LANG_LINKRULE = +# turn the non-existent third argument into an identifier for our link data +$(eval 3 := $(notdir $(basename $1))) +# generate the dependecies list +$(eval $3_DEP := $(filter-out $1,$(call SRC_LANG_DEPS,$1,$2))) +# Implicit and Manual LD Options to allow .ld files to specify manual linking to +# one of the built-in modules. Implicit LDOs are ones we can surmise from +# include rules generated with 'SRC_LANG_DEPS', but these are only caught if +# there was an explicitly included header, or some other file, within the source +# file of the driver to one of the internal modules. This practice is a +# reliable way to automatically link an internal module, but if desired an +# associated '.ld' file for the driver can contain a list of whitespace +# separated module names to ensure they link properly +$(eval MODULE_FILES := $(filter-out .% $(DRIVER_DIR)/%,$($3_DEP))) +$(eval MODULE_FILES := $(basename $(MODULE_FILES))) +$(foreach mfile,$(MODULE_FILES),\ +$(eval $3_ILDO += $(firstword $(subst /, ,$(mfile))))) +# Find the .ld files, if present, and include their 'links' to our internal libs +$(if $(wildcard $(1:.$2=.ld)),\ +$(eval $3_MLDO := $(basename $(strip $(file <$(1:.$2=.ld)))))) +$(eval $3_LDO := $(patsubst %,%.$($($2_C)_AROBJ),$(sort $($3_ILDO) $($3_MLDO)))) +# If we have any libs to generate, make sure their specific shared object file +# is available, and that the linker is linking to our expected link directory +# for our compiler and architecture (transpilation magic) +$(eval $3_SRC_OBJS := $(filter-out $1 %.h,$($3_DEP) $($3_LDO))) +# If the compiler supports linking, filter any shared objects out of the list +# that can be linked (the -l command option should already be in $2_FLAGS) +# otherwise, explicitly include all shared objects in the source objects, while +# also putting them on the dep list +$(if $($($2_C)_LD),\ +$(eval $3_SOB := $(filter-out $($2_LD_LIBS),$($2_LIBS))),\ +$(eval $3_SOB := $($2_LIBS:%=$(LIB_DIR)/lib%.so))\ +$(eval $3_SRC_OBJS += $($3_SOB))) +$(eval $3_SOB += $(filter $(LIB_DIR)/lib%.so,$($2_FLAGS))) +# Directory setup +$(eval $3_DIR := $(dir $(1:%.$2=$(ROOT_DIR)/%))) +$(eval MAKE_DIRS += $($3_DIR)) +# Commandline setup. The recursive library dependecy traversal constructs a +# tree ordered by nested dependency depth. when linking, this order is reversed +# Establish the link tree: +$(eval LINK_TREE := $(filter -l% %.so,$($2_FLAGS)) $($3_DEP) $($3_LDO) $1) +$(eval LINK_TREE := $(shell echo $(filter-out %.h,$(LINK_TREE)) | awk \ +' +BEGIN { OFS = " "; ORS = " " } +{ for (i=NF; i>1; i--) + printf("%s ",$$i); + print $$1; +} +')) +# The actual rule +$($3_DIR)$3$($2_OUT): $($3_SOB) $($3_LDO) $($3_DEP) | $($3_DIR) + $$($2_C) $$(filter-out $(LINK_TREE),$($2_FLAGS)) $(LINK_TREE) -o $$@ +#/SRC_LANG_LINKRULE############################################################## +endef + +# generate rule for turning an entire module's collection of binary objects into +# a single locally-linked (no external -L libs) object (for simplified linking +# modules as static libs). +define MODULE_ARCRULE = +$(eval $1_ARCDEPS := $(filter $1/%,$(foreach lang,$(LANGS),$($(lang)_MOD_TRG)))) +$1.$($(c_C)_AROBJ): $($1_ARCDEPS) | $(LCLLIB_DIR) + $($(c_C)_AR) cr $$@ $$^ +endef + +# define an object creation rule given a module and language +define MODULE_LANG_OBJRULE = +$1/%.$($2_OBJ): $1/%.$2 + $$($2_C) -I$1 $$(filter-out -l%,$$($2_FLAGS)) $$< -c -o $$@ +endef + +# LANG_LIB_PARENT_BUILDRULE###################################################### +# define rules for creating unknown libraries in the local build environment for +# either binary or bytecode representation given a library name and, optionally, +# a parent lib that included it for error reporting ############################# +define LANG_LIB_PARENT_BUILDRULE = +# Construct the download method, or error if there isn't a valid one + +$(if $($2_GITADDR),$(eval LIBDL := git clone $($2_GITADDR) $2),\ +$(if $($2_HGADDR),$(eval LIBDL := hg clone $($2_HGADDR) $2),\ +$(if $($2_CVSADDR),$(shell echo $($2_CVSPASS) > ~/.cvspass)\ +$(eval LIBDL := export CVSROOT=$($2_CVSADDR) && cvs $($2_CVSGET)),\ +$(if $($2_WEBADDR),$(eval LIBDL := wget -O $($2_WEBTARG) $($2_WEBADDR)),\ +$(eval $(error No way to download $2 needed by $3 for $1 language )))))) +# '$2' Download Rule +$(LIBDL_DIR)/$2: + mkdir -p $$@ + cd $(LIBDL_DIR) && $(LIBDL) $(if $($2_WEBINIT),&& $($2_WEBINIT)) +# '$2' Make and install rule +$(LIB_DIR)/lib$2.so: $(LIBDL_DIR)/$2 $($2_LIBDEPS:%=$(LIB_DIR)/lib%.so) + @mkdir -p $(LIB_DIR) + cd $(LIBDL_DIR)/$2 && $($2_MAKE) + cd $(LIBDL_DIR)/$2 && $($2_INSTALL) + +# each library generated will be included in the libs available list, removed +# from the missing libs list, and passed by -l'libname' to the language flags +$(foreach lang,$(LIBLANGS),\ +$(eval $(lang)_LIBS_AVAILABLE += $2)\ +$(eval $(lang)_MISSING_LIBS := $(filter-out $2,$($(lang)_MISSING_LIBS)))\ +$(eval $(lang)_SOBS += $(2:%=$(LIB_DIR)/lib%.so))\ +) +#/LANG_LIB_PARENT_BUILDRULE###################################################### +endef + + +#LANG_LIB_INIT################################################################### +# For every library in this language, we need to determine how, and if, to link +# its data. This could potentially be done recursively as libraries have +# dependencies upon each other. We call a recursive macro here to expand out +# all the libs for this language, and then flatten the tree by removing +# duplicates with shell commands. We can't use make's 'sort' function because +# we actually care about the ordering so that interdependent libraries can link +# back up the tree ############################################################## +define LANG_LIB_INIT = +# Implicit defaults for lib.mk files +$(eval AUTOGEN := ./autogen.sh) +$(eval CONFIGURE := ./configure) +$(eval CONFIGURE += --prefix=$(abspath $(LIB_DIR)/.trash)) +$(eval CONFIGURE += --includedir=$(abspath $(LIBINC_DIR))) +$(eval CONFIGURE += --libdir=$(abspath $(LIB_DIR))) +$(eval MKCMD := make -k) +$(eval MKINSTALL := make -k install) +$(eval MKCLEAN := make clean) +$(eval LIBDEPS :=) +# One of these must be defined in the .mk file imported +$(foreach var, GITADDR WEBADDR HGADDR CVSADDR,\ +$(eval undefine $(var))) +# Other, optional, variables to clear +$(eval undefine WEBTARG) # File 'WEBADDR' is stored in +$(eval undefine WEBINIT) # Method of extracting 'WEBTARG', if necessary +$(eval undefine CVSGET) # checkout command +$(eval undefine CVSPASS) # auto-put into ~/.cvspass to login automatically +# Sneaky expansion to call a file inclusion with unelevated (eval'ed) text +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 $(call EVALINCLUDE)),\ +$(if $($($1_C)_LD),\ +$(warning No $2.mk for lib$2, linking from the system),\ +$(error No $2.mk for lib$2 and '$($1_C)' is not configured for linking))) + +# Store lib specific build info +$(foreach var,GITADDR WEBADDR HGADDR CVSADDR WEBTARG WEBINIT CVSGET CVSPASS,\ +$(eval $2_$(var) := $($(var)))) +$(eval $2_MAKE := $(if $(AUTOGEN),$(AUTOGEN) && )) +$(eval $2_MAKE += $(if $(CONFIGURE),$(CONFIGURE) && )) +$(if $(MKCMD),\ +$(eval $2_MAKE += $(MKCMD)),\ +$(error $2.mk requires a valid MKCMD definition)) +$(if $(MKINSTALL),\ +$(eval $2_INSTALL := $(MKINSTALL)),\ +$(error $2.mk requires a valid MKINSTALL definition)) +$(eval $2_CLEAN := $(MKCLEAN)) +$(eval $2_DEPS := $(LIBDEPS)) + +# Add dependencies we found (potentially recursively, ignore repeats until later +# so we can preserve ordering information for interdependency build ordering) +$(if $(LIBDEPS),$(eval $1_LIBS += $(LIBDEPS))) + +# languages that can link this library (typically any lang that shares the +# object format (ELF by default, but this is compiler-dependent (e.g. emcc uses +# llvm bitcode, which is just an intermediary representation of data that can +# link to anything else statically, or as an archive))) +$(eval LIBLANGS ?= c cpp go) +$(if $(findstring $1,$(LIBLANGS)),,\ +$(error $2.mk must specifically set LIBLANGS := $1 if it is compatible with $1)) + +# Mark this lib as available for all its other compatible languages. This list +# is assumed to be sorted later, so we will ignore repeats for speed +$(foreach lang,$(LIBLANGS),\ +$(eval $(lang)_LD_LIBS += $2)\ +$(if $(findstring $2,$($(lang)_LIBS)),,\ +$(eval $(lang)_LIBS += $2)\ +)) + +# Recurse this function for every libdep encountered +$(foreach libdep,$(LIBDEPS),\ +$(eval $(call LANG_LIB_INIT,$1,$(libdep)))\ +) +#/LIB_INIT####################################################################### +endef + +# Initialize data for supported lanaguages ###################################### +define LANG_INIT = +# Initialize all relevant (although not necessarily used) language relative data +$(eval $1_OBJ := $($($1_C)_OBJ)) +$(eval $1_OUT := $($($1_C)_OUT)) +$(eval $1_SOURCES := $(subst ./,,$(shell find -name "*.$1"))) +# For each source language that can compile to this language, add the expected +# result of such a transformation to the sources of this language. Then, if the +# source-to-source compiler also creates duplicate files of other formats +# (i.e. yacc/bison also produce accompanying .h files), add them to the list of +# source files that this makefile can generate ('$1_MKSRC'), to later be deleted +# during the clean rule. +$(info $1_SOURCES: $($1_SOURCES)) +$(foreach srcl,$($1_SRCL),\ +$(eval $1_MKSRC := $(shell find -name "*.$(srcl)" \ +| sed -e 's@^\(.*\).$(srcl)@\1$($(srcl)_STEM:%=.%).$1@g' -e 's@\./@@'))\ +$(eval $1_SOURCES += $($1_MKSRC))\ +$(eval $(srcl)_SOURCES += $($1_MKSRC))\ +$(if $($(srcl)_DUP),\ +$(eval $1_SOURCES += $($1_MKSRC:%.$1=%.$($(srcl)_DUP))))\ +) +$(info $1_SOURCES: $($1_SOURCES)) + +$(eval $1_DRV_SRC := $(filter $(DRIVER_DIR)/%,$($1_SOURCES))) +$(eval DRV_SRC += $($1_DRV_SRC)) +$(eval $1_DRV_TRG := $(patsubst %.$1,$(ROOT_DIR)/%$($1_OUT),$($1_DRV_SRC))) +$(eval DRV_TRG += $($1_DRV_TRG)) +$(eval $1_MOD_SRC := $(filter-out $(DRIVER_DIR)/%,$($1_SOURCES))) +$(eval MOD_SRC += $($1_MOD_SRC)) +$(eval $1_MOD_TRG := $(subst .$1,.$($1_OBJ),$($1_MOD_SRC))) +$(eval MOD_TRG += $($1_MOD_TRG)) +# Generate a list of shared object files this language has access to +$(eval $1_SOBS := $(wildcard $(LIB_DIR)/lib*.so)) + +# First, initialize language-module, module, and language relative data. Then, +# filter out each source file from the module and generate Dependency Rules and +# Module Object Rules for each of them. +$(foreach module,$(MODULES),\ +$(eval $(module)_$1_SRC := $(filter $(module)/%,$($1_MOD_SRC)))\ +$(eval $(module)_$1_TRG := $(filter $(module)/%,$($1_MOD_TRG)))\ +$(eval $(module)_SRC += $(module)_$1_SRC)\ +$(eval $(module)_TRG += $($(module)_$1_TRG))\ +$(eval $1_TRG += $($(module)_TRG))\ +$(eval \ +$(foreach src,$(filter $(module)/%,$($1_MOD_SRC)),\ +$(eval $(call SRC_LANG_DEPRULE,$(src),$1,$(module)))\ +$(eval $(call MODULE_LANG_OBJRULE,$(module),$1)))\ +)) +$(eval $1_TARGETS += $($1_TRG)) + +# For all the listed libraries, initialize the library, which will set up all of +# its local ($1_LIBS, etc) data +$(foreach lib,$($1_LIBS),\ +$(call LANG_LIB_INIT,$1,$(lib))) +# The initializer produces an ordered list of interlinked dependencies in groups +# by depth, so when reading backwards and compressing repeats we are left with a +# reliable build order for library interlinking. this awk program just looks +# through a list of space separated words backwards failing to print when it +# encounters a repeat (which is suitable as a kind of ad-hoc make lisp function) +$(eval $1_LIBS := $(shell echo "$($1_LIBS)" | awk \ +' +{ for(i=NF;i>0;i--) + printf (!a[$$i]++) ? $$i FS : ""; + i=split("",a); + print "" +} +' +)) +# If our compiler has a linker, find its list of available links and start +# adding '-lLIBNAME' options to the language flags if the linker has them, or to +# the list of missing libraries for this language if the linker cannot find them. +# If this compiler has no linker, mark all libs as missing +$(eval $1_LD_LIBS := $(sort $1_LD_LIBS)) +$(if $($($1_C)_LD),\ +$(eval $1_LD_LIBS := $($($1_C)_LDLIBS) $($1_SOBS:$(LIB_DIR)/lib%.so=%))\ +$(foreach lib,$($1_LIBS),\ +$(if $(findstring $(lib),$($1_LD_LIBS)),\ +$(eval $1_FLAGS += -l$(lib)),\ +$(eval $1_MISSING_LIBS += $(lib))\ +$(eval $1_FLAGS += $(LIB_DIR)/lib$(lib).so)\ +)),\ +$(eval $1_MISSING_LIBS := $(filter-out $($1_LD_LIBS),$($1_LIBS)))\ +) +#/LANG_INIT###################################################################### +endef + +# Initialize each language and look for its files +$(foreach lang,$(LANGS),\ +$(eval $(call LANG_INIT,$(lang)))) + +# Generate rules for making missing libs +$(foreach lang,$(LANGS),\ +$(foreach mlib,$($(lang)_MISSING_LIBS),\ +$(eval $(call LANG_LIB_PARENT_BUILDRULE,$(lang),$(mlib),root))\ +)) + +# Create module object rules for each module and scan for interpreted code +# sources (yacc, etc) +$(foreach module,$(MODULES),\ +$(eval $(call MODULE_ARCRULE,$(module)))\ +$(eval YS += $(wildcard $(module)/*.y))\ +) + +# Create lang-specific rules for producing final (linked) targets +$(foreach lang,$(LANGS),\ +$(foreach drvsrc,$($(lang)_DRV_SRC),\ +$(eval $(call SRC_LANG_DEPRULE,$(drvsrc),$(lang)))\ +$(eval $(call SRC_LANG_LINKRULE,$(drvsrc),$(lang)))\ +)) + +# Make any dirs that we're in charge of +$(MAKE_DIRS): @mkdir -p $@ -#run the game after making it -run: $(APPNAME) - $(APPTARG) - -#push to github after successful compile -push: $(APPTARG) - @printf '\nEnter a commit message:\n'; \ - read CMT; \ - git commit -am "$$CMT" - git push - -dox doc: - doxygen dox.conf - -################## DEFAULTS ##################### -#cancel default %.o behavior for %.d dependency -%.o : %.c - -#construct list of make rules for tools -ifdef TOOLS -TOOLTRG := $(foreach tool,$(TOOLS),$(tool)/$(tool)) -.phony: $(TOOLS) -$(TOOLS): $(TOOLTRG) - -T = $(notdir $@) -D = $(dir $@) -B = $(basename $D) -$(TOOLTRG): $(TOOLOBJ) - $($TCC) $($TFLG) $($TSRC:.c=.o) -o $@ - -#Tools only work on whatever system they're designed for -#(typically GNU), so their creation rules are dependent -#on each tool (define in .make/.buildtools.mk) -$(foreach tool,$(TOOLS),$(tool)/%.o): $(dir $@)%.c - $($BCC) $(BFLG) $< -c -o $@ - -#Put our toolsrc on the ctarg list for generating deps -CTARG := $(CTARG) $(TOOLOBJ) -endif - -#Generate and evaluate C dependencies -$(foreach base,$(basename $(sort $(strip $(CTARG)))),\ - $(eval $(strip $(base)$(COBJSUF): $(shell $(subst $BASE,$(base),$(CDEPSCOMMAND)))) $(CDEPS))) - -#new default C build rule -%.bc %.o: %.c $(CDEPS) - $(CC) $(CXXFLAGS) $(CFLAGS) $< -c -o $@ - -#construct list of cp rules for each web item -ifdef WEBTARG -$(WEBTARG): $(subst $(DISTDIR),$(HTSRCDIR),$(WEBTARG)) - cp -f $(subst $(DISTDIR),$(HTSRCDIR),$@) $@ -endif - -#force including rules for making each lib if -#we have identified any missing libs -#(fail if no rule exists) -ifdef MISSINGLIBS -include $(foreach lib,$(MISSINGLIBS),.make/lib$(lib).mk) -endif - -#include rules for making each app -ifdef APPTARGS -include $(foreach app,$(APPTARGS),.make/app$(app).mk) -endif - -#clean up intermediate dependency files and binaries -clean: - @echo "Cleaning build targets" - rm -f $(APPTARG) $(WEBTARG) $(CTARG) +# Create driver rules for each driver we found, let users call make specifying +# the basename of the driver, and just route to the correct linkrule 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 + +# Source-to-source build rules +# Compilers that don't specify an output location can be made to change +# directories with 'cd' to the target file's directory, update the command line +# source files, and allow the compiler to output in its default current working +# directory 'cwd'. this is done by setting the $1_CHDIR flag to 't' +define SRCLANG_TRGLANG_BUILDRULE = +$(info SRCLANG_TRGLANG_BUILDRULE $1 $2) +%$($1_STEM:%=.%).$2$(if $($1_DUP), %$($1_STEM:%=.%).$($1_DUP)): %.$1 + $(if $($1_CHDIR),cd $$(shell dirname $$@) && )$$($1_C) $$($1_FLAGS)$(if $($1_CHDIR),\ +$$(shell echo $$@ | sed -e 's@^.*/\([^\.]*\).*@\1@').$1,\ +$$<) +endef +$(foreach lang,$(LANGS),$(if $($(lang)_SRCL),$(foreach srcl,$($(lang)_SRCL),\ +$(eval $(call SRCLANG_TRGLANG_BUILDRULE,$(srcl),$(lang)))))) -#Scrub down to minimal distribution -scrub: | clean +clean: + rm -f $(foreach lang,$(LANGS),$($(lang)_TARGETS) $($(lang)_MKSRC)) +scrub: clean + rm -Rf $(MAKE_DIRS)