# Sandstorm/Tools/MakeTail
#
# Tail include-makefile 

SRCMOD_ = $(strip $(SRC_MODULE))

#define variables needed below, if there is a library or headers
ifneq "$(strip $(OBJS))$(strip $(EXTRA_OBJS))$(strip $(HEADERS))" ""
ifeq "$(SRCMOD_)" ""
    SRCMOD_ = $(notdir $(PWD))
    $(warning no value for SRC_MODULE - using '$(SRCMOD_)' )
endif
MKFILE = $(SRCMOD_).mk
endif

######### include files - from HEADERS #############
# If there are any headers, they must be installed.
# Their fully installed names are listed in INCLUDE_DEST.
# INCLUDE_DEST is a prerequisite to the 'inst' target.
ifneq "$(MKFILE)" ""
INCLUDE_DEST = $(foreach hdr,$(HEADERS) $(MKFILE),$(INC_DIR)/$(hdr))
$(INCLUDE_DEST): $(INC_DIR)/%: %
	$(INSTALL_DATA) $< $@
$(INC_DIR): 
	@if test ! -d $(INC_DIR); then \
		mkdir -p $(INC_DIR); \
	fi; 
RM_INCDIR ?= $(INC_DIR)
else
$(INC_DIR): 
endif

######### Library - from OBJ & EXTRA_OBJS #############
INTFLBS_ := -L$(INSTALL_DIR)/lib 

ifneq "$(strip $(OBJS))$(strip $(EXTRA_OBJS))" ""

# build list of needed libraries
# use the libraries listed in SUPPORT_LIBS and their .mk files
SUPLIBS_ = $(filter -l%, $(SUPPORT_LIBS))
BADLIBS_ = $(filter-out -l%, $(SUPPORT_LIBS))
ifneq "$(strip $(BAD_LIBS))" ""
          $(warning Missing "-l" in SUPPORT_LIBS on $(BADLIBS_))
endif
INTF_LIBS := 
ifneq "$(strip $(SUPLIBS_))" ""
include $(foreach f, $(SUPLIBS_), $(INSTALL_DIR)/include/$(f:-l%=%)/$(f:-l%=%).mk)
endif
INTFLBS_ := $(INTFLBS_)  \
                $(shell sh -c "echo '$(INTF_LIBS) $(EXTRA_SUPPORT_LIBS)' \
                | $(LIBPRUNE)") 

# INTFLBS_ has the list of libraries needed by clients 

# build/install the library itself

LIB_NAME = lib$(SRCMOD_).a
LIBRARY_DEST=$(LIB_DIR)/$(LIB_NAME)
$(LIB_NAME): $(OBJS) $(EXTRA_OBJS)
	-rm -f $@
	$(AR) cr $@ $^
	$(RANLIB) $@
$(LIBRARY_DEST): $(LIB_NAME)
	$(INSTALL_DATA) $< $@
	$(RANLIB) $@ 
$(LIB_DIR): 
	@if test ! -d $(LIB_DIR); then \
		mkdir -p $(LIB_DIR); \
	fi; 
else 
$(LIB_DIR):
endif

######### create MKFILE
# note that MKFILE is defined if there are HEADERS or OBJS or EXTRA_OBJS
ifneq "$(MKFILE)" ""
$(MKFILE): Makefile
	@rm -rf $(MKFILE)
	@echo 'SUPPORT_MAKEFILES += $(SUPPORT_MAKEFILES)'   >   $(MKFILE)
	@echo '$(SRCMOD_)_INCS = $(EXTRA_INC_DIRS)'         >>  $(MKFILE)
	@echo '$(SRCMOD_)_SUPPORT = $(INTFLBS_)'            >>  $(MKFILE)
	@echo '$(SRCMOD_)_LIBS = -l$(SRCMOD_) \
	         $${$(SRCMOD_)_SUPPORT}'                    >> $(MKFILE)
	@echo 'INTF_LIBS := $$(INTF_LIBS) $${$(SRCMOD_)_LIBS}' \
                                                            >> $(MKFILE)
endif

######### construct full list of libraries 
#          for TARGET and other executables
ifneq "$(strip $(TARGET_LIBS))" ""
INTF_LIBS := $(INTFLBS_)   
TRGLIBS_ = $(filter -l%, $(TARGET_LIBS))
BADLIBS_ = $(filter-out -l%, $(TARGET_LIBS))
ifneq "$(strip $(BAD_LIBS))" ""
          $(warning Missing "-l" in TARGET_LIBS on $(BADLIBS_))
endif

# the following will fail if -lSRC_MODULE is in SUPPORT_LIBS or  TARGET_LIBS
ifneq "$(strip $(TRGLIBS_))" ""
include $(foreach f, $(TRGLIBS_), $(INSTALL_DIR)/include/$(f:-l%=%)/$(f:-l%=%).mk)
endif

INTFLBS_ := $(INTF_LIBS)
endif

# make sure we get the ConfigSource makefile
include $(UTILS_DIR)/include/ConfigSource/ConfigSource.mk
include $(UTILS_DIR)/include/TimeSource/TimeSource.mk

###
### All NavLab modules need TimeSource and ConfigSource.
### These in turn need the libraries listed on the last line of ALLLIBS_.
### This is a kludge. We should figure out how to know if we need these libs.
###
# Set LDLIBS.  It is used for both TARGET and implicit linking
ALLLIBS_ = -L$(LIB_DIR) $(LIB_NAME) $(INTFLBS_) $(EXTRA_TARGET_LIBS) \
	   $(ConfigSource_LIBS) $(TimeSource_LIBS) \
           -lfltk -L/usr/X11R6/lib -lX11 -lipt -lutils -lm
LDLIBS = $(shell sh -c "echo '$(ALLLIBS_)' | $(LIBPRUNE)")

#OURLIBS_ - so we rebuild TARGET for a change to any lib
#           listed in SUPPORT_LIBS or TARGET_LIBS

OURLIBS_ = $(LIB_NAME) \
         $(foreach f, $(SUPLIBS_) $(TRGLIBS_), \
                      $(INSTALL_DIR)/lib/lib$(f:-l%=%).a)

######### Executable = TARGET #############
# if there is a TARGET, an executable is to be built

ifneq "$(strip $(TARGET))" ""
INST_TARGET ?= $(TARGET)
INST_TARGET := $(strip $(INST_TARGET))
TARGET_DEST=$(BIN_DIR)/$(INST_TARGET)

$(TARGET): $(TARGET_OBJS) $(EXTRA_TARGET_OBJS) $(OURLIBS_) $(TARGET_DEPENDS)
	$(CXX) $(CPP_FLAGS) $(CXX_FLAGS) -o $(TARGET) \
                 $(TARGET_OBJS) $(EXTRA_TARGET_OBJS) $(LDLIBS)

$(TARGET_DEST): $(TARGET); $(INSTALL_PROGRAM) $< $@

$(BIN_DIR): 
	@if test ! -d $(BIN_DIR); then \
		mkdir -p $(BIN_DIR); \
	fi; 
else
TARGET_DEST=
$(BIN_DIR):
endif

######### Testing = TEST_BIN #############
# AUTO_TESTS lists binary executables for simple test programs.
RUN_AUTO_TESTS = $(AUTO_TESTS:%=test-%)
$(RUN_AUTO_TESTS): test-%: %
	./$<

# OTHER_AUTO_TESTS
# Names of binaries for other tests to be done for 'make test'
RUN_OTHER_TESTS = $(OTHER_AUTO_TESTS:%=test-%)

# TEST_BINS is deprecated
RUN_TESTS = $(TEST_BINS:%=test-%)


# the following makes everything depend on those Sandstorm libraries
# mentioned in SUPPORT_LIBS or TARGET_LIBS
# it has a side-effect of adding these libraries to link commands
# they wind up listed twice; this full form and a -l form
ifneq "$(strip $(TEST_BINS))$(strip $(AUTO_TESTS))\
$(strip $(OTHER_AUTO_TESTS))$(strip $(BUILD_TESTS))" ""
$(TEST_BINS) $(AUTO_TESTS) $(OTHER_AUTO_TESTS) $(BUILD_TESTS): $(OURLIBS_)
endif

.PHONY: $(AUTO_TESTS:%=test-%)
.PHONY: $(OTHER_AUTO_TESTS:%=test-%)
.PHONY: $(RUN_TESTS)

TESTDEPS_ = $(AUTO_TESTS:%=%.o) $(OTHER_AUTO_TESTS:%=%.o) $(BUILD_TESTS:%=%.o) 

###########################################
# targets for actions on local directory
.PHONY: reallocal inst test testbin clean uninst localcleaner
.PHONY: all include install testall cleanall uninstall cleaner
.PHONY: uninstallsubdirs cleansubdirs

reallocal: $(LIB_NAME) $(TARGET) $(TEST_BINS) $(EXTRA_BUILDS)
inst: $(INC_DIR) $(INCLUDE_DEST) \
             $(LIB_DIR) $(LIBRARY_DEST) \
             $(BIN_DIR) $(TARGET_DEST) $(EXTRA_INSTALLS)
test: testbin $(RUN_TESTS) $(RUN_AUTO_TESTS) $(RUN_OTHER_TESTS)
testbin: $(TEST_BINS) $(AUTO_TESTS) $(OTHER_AUTO_TESTS) $(BUILD_TESTS)
clean: ; rm -f $(JUNK) $(EXTRA_CLEANS) $(LIB_NAME) $(TARGET) $(TEST_BINS)
localcleaner: clean
uninst: $(EXTRA_UNINSTALLS) 
	rm -rf $(RM_INCDIR) $(LIBRARY_DEST) $(TARGET_DEST)

#############################################
# targets for entire subtree
DO_SUBDIRS = @for dir in $(SUBDIRS); do $(MAKE) -C $$dir $@ ; done;
DO_LEGACIES = @for dir in $(LEGACY_SUBDIRS); do $(MAKE) -C $$dir target ; done;

all: $(INC_DIR) $(INCLUDE_DEST) local 
	$(DO_LEGACIES:target=install)
	$(DO_SUBDIRS)  
include: $(INC_DIR) $(INCLUDE_DEST) 
	$(DO_LEGACIES:target=install)
	$(DO_SUBDIRS)
install: inst 
	$(DO_LEGACIES:target=install)
	$(DO_SUBDIRS)
testall: test; $(DO_SUBDIRS)
cleanall: cleansubdirs clean
cleansubdirs:
	@for dir in $(SUBDIRS); do $(MAKE) -C $$dir cleanall; done;
	$(DO_LEGACIES:target=clean)
cleaner: localcleaner
	$(DO_SUBDIRS)

# when deleting stuff, reverse the order of installation
AWKREV_ = awk '{for (i=NF; i>0; i--) print $$(i)}'
uninstall:  uninstallsubdirs uninst
uninstallsubdirs:
	@for dir in  `echo $(SUBDIRS) | $(AWKREV_)` ;  do \
		$(MAKE) -C $$dir uninstall; \
	done;

#############################################
# generating dependencies

%.d: %.cc 
	@echo Generating dependencies for $<
	@$(SHELL) -ec '$(CXX) -M $(1) $(DEPFLAGS) $(CPPFLAGS) $< \
		| sed '\''s/\($*\.o\)[ :]*/\1 $@ : /g'\'' > $@ '

%.d: %.c
	@echo Generating dependencies for $<
	@$(SHELL) -ec '$(CC) -M $(1) $(DEPFLAGS) $(CPPFLAGS) $< \
		| sed '\''s/\($*\.o\)[ :]*/\1 $@ : /g'\'' > $@ '

# force relink of known programs when library changes
$(EXTRA_BUILDS) $(EXTRA_DEPENDS:%.o=%) $(TESTDEPS_:%.o=%): $(LIB_NAME)

ALLOBJS_ = $(OBJS) $(TARGET_OBJS) $(EXTRA_DEPENDS) $(TESTDEPS_)
ifneq "$(strip $(ALLOBJS_))" ""
-include $(ALLOBJS_:.o=.d) 
endif
