#!/usr/bin/make -f # -*- Makefile -*- ###### # I. Establish the root module of this subtree. # That will allow the path prefix to be established. ###### ifndef PREFIX_ESTABLISHED # set base before recursive loading begins ifndef MK_START MK_START := $M ALL_MODULES := endif ifneq ($(strip $($M/A_ROOT_MODULE)),1) # start recursive loading of lower level makes until # root is found. NEXT_M_STACK := $M $(NEXT_M_STACK) M := $(subst /XxXx,,$(dir $M)XxXx) NEXT_M_STACK := $M $(NEXT_M_STACK) include $M/mevmake.mk # pop M := $(firstword $(NEXT_M_STACK)) NEXT_M_STACK := $(wordlist 2, 20, $(NEXT_M_STACK)) else P := $(dir $M) MK_ROOT := $M endif PREFIX_ESTABLISHED := 1 ## generic stuff that just needs to be defined once .PHONY: clean allclean debug endif ###### # II. Establish operating system specific variables ###### ifndef MK_VARIABLES_ONCE MK_VARIABLES_ONCE := 1 ifneq ($(filter debug,$(MAKECMDGOALS)),) DEBUG := 1 ifeq ($(filter-out debug,$(MAKECMDGOALS)),) debug: build endif endif .SUFFIXES: .SUFFIXES: .c .cpp .h .d ifeq ($(OS),Windows_NT) # Windows extensions O := obj B := exe E := exe A := lib L := lib S := dll D := d CC := cl CXX := cl CPP := cl AR = lib /OUT:$@ RANLIB := rem MK_INCLUDES := -I$(subst /XxXx,,$(dir $P)XxXx) MK_LIBS := DEBUG_CPPFLAGS = /ZI /Gm /MLd /D "_DEBUG" DEBUG_LDFLAGS = /incremental:yes /debug /pdbtype:sept .SUFFIXES: .obj .exe .lib .dll # this is a "function" to translate file name into dependency lists per .d files GET_DEPS = $(foreach file, $($(1)), $($(file).DEPS)) GET_DEPS2 = $(foreach file, $($(1)), $($(addprefix $(MS)/,$(file)).DEPS)) else # Linux extensions O := o B := e E := e A := a L := a S := s D := d CC := gcc CXX := g++ CPP := gcc AR = ar cru $@ RANLIB := ranlib MK_INCLUDES := -I$(subst /XxXx,,$(dir $P)XxXx) MK_LIBS := .SUFFIXES: .o .a .s # this is a "function" to translate file name into dependency lists per .d files GET_DEPS = $(addsuffix .$O,$(basename $($(1)))) GET_DEPS2 = $(addsuffix .$O,$(basename $(addprefix $(MO)/,$($(1))))) #GET_DEPS = $($1) endif endif ###### # III. Set up default compiler flags for module and global ###### ifeq ($(OS),Windows_NT) $M/CFLAGS = /nologo $(GCFLAGS) $M/CPPFLAGS = /D "WIN32" /D "_CONSOLE" /D "_MBCS" $(GCPPFLAGS) $M/CXXFLAGS = /nologo /W3 /GX /Od /GZ $(GCXXFLAGS) ifndef DEBUG $M/CXXFLAGS += /ML endif $M/DEPS = /P $M/LDFLAGS = /link /nologo /subsystem:console /machine:I386 /pdb:"$(subst .$B,.pdb,$@)" /incremental:no $(GLDFLAGS) $M/LDLIBS = kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib $(GLDLIBS) $M/OUTPUT_OPTION = /FD /Fo"$(MO)/" /Fe"$(MB)/" /Fd"$(basename $@)" else #linux stuff $M/CFLAGS = -g -O2 -Wall $M/CPPFLAGS = -I/usr/local/include $M/CXXFLAGS = -g -O2 $M/DEPS = -M | sed -e 's@ /usr/i[^ ]*@@g' -e 's@^\(.*\).o:@$(MO)/\1.d $(MO)/\1.o:@' > $@ $M/LDFLAGS = $M/LDLIBS = -L/usr/local/lib $M/OUTPUT_OPTION = -o $@ endif ## globals, ensure the definition only happens once ifdef DEBUG ifndef DEBUG_DONE GCPPFLAGS += $(DEBUG_CPPFLAGS) GLDFLAGS += $(DEBUG_LDFLAGS) DEBUG_DONE:=1 endif endif ifdef MK_THREADS ifndef MK_THREADS_DONE MK_THREADS_DONE :=1 endif endif ###### # III. Recursively load makefiles for other modules ##### # protect against duplicates $M/MODULES_NEEDED := $(addprefix $P,$(sort $($M/MODULES_NEEDED))) # what modules still need to be loaded $M/NEW_MODULES := $(filter-out $(ALL_MODULES), $($M/MODULES_NEEDED)) ALL_MODULES += $($M/NEW_MODULES) # load any missing modules ifneq ($($M/NEW_MODULES),) $M/NEW_MAKES := $(addsuffix /mevmake.mk, $($M/NEW_MODULES)) # push MODULE_STACK := $M $(MODULE_STACK) # the next sequence assumes that NONE of the mevmake's # will be configured dynamically (might still work, but # not tested) NEXT_M_STACK := $($M/NEW_MODULES) $(NEXT_M_STACK) include $($M/NEW_MAKES) ## NOTE: if NEXT_M_STACK fails, ## try "include $(foreach dir,$(M/NEW_MODULES),$(call M,$dir) ## with M := $(1) in the line before ... just a thought ... # pop M := $(firstword $(MODULE_STACK)) MODULE_STACK := $(wordlist 2, 20, $(MODULE_STACK)) endif ###### # IV. Build module specific path variables ##### # Establish default Windows Visual Studio Paths ifeq ($(OS),Windows_NT) ifdef DEBUG WIN_DEFAULT :=Debug else WIN_DEFAULT :=Release endif $M/OBJ_PATH := $(if $($M/OBJ_PATH),$($M/OBJ_PATH),$(WIN_DEFAULT)) $M/LIB_PATH := $(if $($M/LIB_PATH),$($M/LIB_PATH),$(WIN_DEFAULT)) $M/BIN_PATH := $(if $($M/BIN_PATH),$($M/BIN_PATH),$(WIN_DEFAULT)) endif MS := $M$(if $($M/SRC_PATH),/$($M/SRC_PATH),) MI := $M$(if $($M/INC_PATH),/$($M/INC_PATH),) MO := $M$(if $($M/OBJ_PATH),/$($M/OBJ_PATH),) ML := $M$(if $($M/LIB_PATH),/$($M/LIB_PATH),) MB := $M$(if $($M/BIN_PATH),/$($M/BIN_PATH),) ME := $(MB) $M/BUILD_BINS := $(addsuffix .$B,$($M/BUILD_BINS)) $M/BUILD_ARCS := $(addsuffix .$A,$($M/BUILD_ARCS)) $M/BUILD_DLLS := $(addsuffix .$D,$($M/BUILD_DLLS)) $M/BUILD_DEPS := $(addprefix $(MO)/,$(addsuffix .$D,$(basename $($M/BUILD_SRCS)))) $M/BUILD_OBJS := $(addprefix $(MO)/,$(addsuffix .$O,$(basename $($M/BUILD_SRCS)))) $M/BUILD_SRCS := $(addprefix $(MS)/,$($M/BUILD_SRCS)) $M/BUILD_BINS := $(addprefix $(MB)/,$($M/BUILD_BINS)) $M/BUILD_ARCS := $(addprefix $(ML)/,$($M/BUILD_ARCS)) $M/BUILD_DLLS := $(addprefix $(ML)/,$($M/BUILD_DLLS)) ###### # V. Target specific variables and implicit rules ##### # only define implicit rules once #ifeq ($(MK_START),$M) ifndef MK_RULES_ONCE MK_RULES_ONCE := 1 # add DEFS to the underlying compile macros COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(MK_INCLUDES) $(TARGET_ARCH) -c COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(MK_INCLUDES) $(TARGET_ARCH) -c LINK.o = $(CC) $(TARGET_ARCH) LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(MK_INCLUDES) $(TARGET_ARCH) LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(MK_INCLUDES) $(TARGET_ARCH) #OUTPUT_OPTION = clean: $(RM) $($M/BUILD_ARCS) $($M/BUILD_BINS) $($M/BUILD_OBJS) $($M/BUILD_DEPS) $(MO)/*.idb $(MO)/*.pdb $(if $(wildcard $^),$(RM) $(wildcard $^)) allclean: $(if $^,$(RM) $^) endif # set default target on start make only ifeq ($(MK_START),$M) build: $($M/BUILD_ARCS) $($M/BUILD_BINS) endif $(MO)/%.$O: $(MS)/%.c $(COMPILE.c) $< $(OUTPUT_OPTION) $(MO)/%.$O: $(MS)/%.cpp $(COMPILE.cc) $< $(OUTPUT_OPTION) $(MO)/%.$D: $(MS)/%.c @echo -- Creating dependency file for $< $(patsubst /Z%,,@$(COMPILE.c) $< $($M/DEPS)) ifeq ($(OS),Windows_NT) @mvdeps $(addsuffix .i,$(basename $(notdir $<))) $@ @$(RM) $(addsuffix .i,$(basename $(notdir $<))) endif $(MO)/%.$D: $(MS)/%.cpp @echo -- Creating dependency file for $< $(patsubst /Z%,,@$(COMPILE.cc) $< $($M/DEPS)) ifeq ($(OS),Windows_NT) @mvdeps $(addsuffix .i,$(basename $(notdir $<))) $@ @$(RM) $(addsuffix .i,$(basename $(notdir $<))) endif $(MB)/%.$B: $(MO)/%.$O $(LINK.o) $(filter %.$O,$^) $(OUTPUT_OPTION) $(LDFLAGS) $(MK_LIBS) $(LDLIBS) #$(MB)/%.$B: $(MS)/%.c # $(LINK.c) $(filter %.c,$^) $(OUTPUT_OPTION) $(LDFLAGS) $(MK_LIBS) $(LDLIBS) #$(MB)/%.$B: $(MS)/%.cpp # $(LINK.cc) $(filter %.cpp,$^) $(OUTPUT_OPTION) $(LDFLAGS) $(MK_LIBS) $(LDLIBS) $(MB)/%.$B: $(if $(filter %.c,$^), $(LINK.c) $(filter %.c,$^) $(OUTPUT_OPTION) $(LDFLAGS) $(MK_LIBS) $(LDLIBS)) $(if $(filter %.cpp,$^), $(LINK.cc) $(filter %.cpp,$^) $(OUTPUT_OPTION) $(LDFLAGS) $(MK_LIBS) $(LDLIBS)) $(ML)/%.$L: $(if $(filter %.c,$^), $(COMPILE.c) $(filter %.c,$^) $(OUTPUT_OPTION)) $(if $(filter %.cpp,$^), $(COMPILE.cc) $(filter %.cpp,$^) $(OUTPUT_OPTION)) $(RM) $@ $(AR) $(patsubst $(MS)/%.c,$(MO)/%.$O,$(filter %.c,$^)) $(patsubst $(MS)/%.cpp,$(MO)/%.$O,$(filter %.cpp,$^)) $(filter %.$O,$^) #setup include paths and libraries based upon needed modules & libs $M/ARCS_PUBLISHED := $(addsuffix .$A,$($M/ARCS_PUBLISHED)) $M/ARCS_PUBLISHED := $(addprefix $(ML)/,$($M/ARCS_PUBLISHED)) $M/BINS_PUBLISHED := $(addsuffix .$B,$($M/BINS_PUBLISHED)) $M/BINS_PUBLISHED := $(addprefix $(MB)/,$($M/BINS_PUBLISHED)) ifeq ($(OS),Windows_NT) MK_LIBS += $($M/ARCS_PUBLISHED) else MK_LIBS := $(foreach lib,$($M/ARCS_PUBLISHED),-L$(dir $(lib)) -l$(patsubst lib%,%,$(basename $(notdir $(lib))))) $(MK_LIBS) endif MK_INCLUDES += $(sort $(if $($M/INC_PATH_PUBLISHED),$(addprefix -I$M/,$($M/INC_PATH_PUBLISHED))) -I$M $(if $($M/INC_PATH),-I$M/$($M/INC_PATH))) # create prerequisites out of libraries_need list MK_TEMP := $(addsuffix .$A,$($M/LIBRARIES_NEEDED)) MK_TEMP := $(addprefix %/,$(MK_TEMP)) MK_TEMP := $(foreach mod, $($M/MODULES_NEEDED), $(filter $(MK_TEMP),$($(mod)/ARCS_PUBLISHED))) ifneq ($(words $(MK_TEMP)),$(words $($M/LIBRARIES_NEEDED))) $(error Libraries needed not found in published list of modules needed.) endif $M/LIBRARIES_NEEDED := $(MK_TEMP) ifneq ($(strip $($M/BUILD_ARCS)),) $($M/BUILD_ARCS): $($M/LIBRARIES_NEEDED) endif ifneq ($(strip $($M/BUILD_BINS)),) $($M/BUILD_BINS): $($M/ARCS_PUBLISHED) $($M/LIBRARIES_NEEDED) endif allclean: $(wildcard $($M/BUILD_ARCS) $($M/BUILD_BINS) $($M/BUILD_OBJS) $($M/BUILD_DEPS) $(MO)/*.idb $(MO)/*.pdb) # set up rules based upon target paths MK_TEMP := $(if $(wildcard $(MB)),,$(shell mkdir $(MB))) $(MB)/% : CFLAGS = $($M/CFLAGS) $(MB)/% : CPPFLAGS = $($M/CPPFLAGS) $(MB)/% : CXXFLAGS = $($M/CXXFLAGS) $(MB)/% : LDFLAGS = $($M/LDFLAGS) $(MB)/% : LDLIBS = $($M/LDLIBS) $(MB)/% : OUTPUT_OPTION = $($M/OUTPUT_OPTION) $(MB)/% : M := $M $(MB)/% : MS := $(MS) $(MB)/% : MI := $(MI) $(MB)/% : MO := $(MO) $(MB)/% : ML := $(ML) $(MB)/% : MB := $(MB) $(MB)/% : ME := $(ME) ifneq ($(MB),$(ML)) MK_TEMP := $(shell mkdir $(ML)) $(ML)/% : CFLAGS = $($M/CFLAGS) $(ML)/% : CPPFLAGS = $($M/CPPFLAGS) $(ML)/% : CXXFLAGS = $($M/CXXFLAGS) $(ML)/% : LDFLAGS = $($M/LDFLAGS) $(ML)/% : LDLIBS = $($M/LDLIBS) $(ML)/% : OUTPUT_OPTION = $($M/OUTPUT_OPTION) $(ML)/% : M := $M $(ML)/% : MS := $(MS) $(ML)/% : MI := $(MI) $(ML)/% : MO := $(MO) $(ML)/% : ML := $(ML) $(ML)/% : MB := $(MB) $(ML)/% : ME := $(ME) endif ifneq ($(MB),$(MO)) MK_TEMP := $(shell mkdir $(MO)) $(MO)/% : CFLAGS = $($M/CFLAGS) $(MO)/% : CPPFLAGS = $($M/CPPFLAGS) $(MO)/% : CXXFLAGS = $($M/CXXFLAGS) $(MO)/% : LDFLAGS = $($M/LDFLAGS) $(MO)/% : LDLIBS = $($M/LDLIBS) $(MO)/% : OUTPUT_OPTION = $($M/OUTPUT_OPTION) $(MO)/% : M := $M $(MO)/% : MS := $(MS) $(MO)/% : MI := $(MI) $(MO)/% : MO := $(MO) $(MO)/% : ML := $(ML) $(MO)/% : MB := $(MB) $(MO)/% : ME := $(ME) endif ###### # VI. Create dependency files ... and load them ##### ifeq ($(filter clean allclean,$(MAKECMDGOALS)),) ifneq ($($M/BUILD_DEPS),) include $($M/BUILD_DEPS) endif endif