## makefile.base - common make-file for compiling exhale on Linux and MacOS platforms
 # written by C. R. Helmrich, last modified in 2021 - see License.htm for legal notices
 #
 # The copyright in this software is being made available under the exhale Copyright License
 # and comes with ABSOLUTELY NO WARRANTY. This software may be subject to other third-
 # party rights, including patent rights. No such rights are granted under this License.
 #
 # Copyright (c) 2018-2021 Christian R. Helmrich, project ecodis. All rights reserved.
 ##

## verification of config parameter
ifneq ($(CONFIG), CONSOLE)
 ifneq ($(CONFIG), LIBRARY)
  CONFIG_ERR = TRUE
 endif
endif

# specification of used executables
AR    = ar
ASM   = nasm
CPP   = g++
LD    = $(CPP)

# location and name of output files
ifeq ($(CONFIG), CONSOLE)
  STAT_DEBUG_OUT    = $(DIR_BIN)/$(PRD_NAME)d
  STAT_RELEASE_OUT  = $(DIR_BIN)/$(PRD_NAME)
  DYN_DEBUG_OUT     = $(DIR_BIN)/$(PRD_NAME)Dynd
  DYN_RELEASE_OUT   = $(DIR_BIN)/$(PRD_NAME)Dyn
else
 ifeq ($(CONFIG), LIBRARY)
  STAT_DEBUG_OUT    = $(DIR_LIB)/lib$(PRD_NAME)d.a
  STAT_RELEASE_OUT  = $(DIR_LIB)/lib$(PRD_NAME).a
  DYN_DEBUG_OUT     = $(DIR_LIB)/lib$(PRD_NAME)Dynd.so
  DYN_RELEASE_OUT   = $(DIR_LIB)/lib$(PRD_NAME)Dyn.so
 endif
endif

# type of debug and release objects
DEBUG_OBJS    = $(OBJS:.o=.d.o)
RELEASE_OBJS  = $(OBJS:.o=.r.o)


## specification of compiler flags
CPPFLAGS          = -fPIC $(DEFS) -I$(CURDIR)/$(DIR_INC) -Wall -Werror -Wshadow -D_FILE_OFFSET_BITS=64 -std=c++11 $(CXXFLAGS)

# setting of 32-bit compiler flags
MM32?=0
ifeq ($(MM32), 1)
  CPPFLAGS+=-m32
endif

# setting of MacOSX compiler flags
UNIVERSAL2?=0
ifeq ($(UNIVERSAL2), 1)
  CPPFLAGS+=-arch x86_64 -arch arm64 -mmacosx-version-min=10.9
endif

# debug and release compiler flags
DEBUG_CPPFLAGS    = -g  -D_DEBUG
RELEASE_CPPFLAGS  = -O3 -Wuninitialized


## specification of linker flags
ALL_LDFLAGS       = -Wall $(ADDITIONAL_LDFLAGS)
ifeq ($(OS), Windows_NT)
  ALL_LDFLAGS+=-municode
endif

# setting of 32-bit linker flags
ifeq ($(MM32), 1)
  ALL_LDFLAGS+=-m32
endif

# setting of MacOSX linker flags
ifeq ($(UNIVERSAL2), 1)
  ALL_LDFLAGS+=-arch x86_64 -arch arm64 -mmacosx-version-min=10.9
endif

# debug and release linker flags
ifeq ($(CONFIG), CONSOLE)
  LDFLAGS           = $(ALL_LDFLAGS)
  DEBUG_LDFLAGS     =
  RELEASE_LDFLAGS   =
else
 ifeq ($(CONFIG), LIBRARY)
  LDFLAGS           = $(ALL_LDFLAGS) -shared
  DEBUG_LDFLAGS     = -Wl, -soname, lib$(PRD_NAME)Dynd.so
  RELEASE_LDFLAGS   = -Wl, -soname, lib$(PRD_NAME)Dyn.so
 endif
endif


## specification of assembler flags
ASMFLAGS          = -f elf $(DEFS)
DEBUG_ASMFLAGS    = -g
RELEASE_ASMFLAGS  =

# creation of ASM debug objects
$(DIR_OBJ)/%.d.o: $(DIR_SRC)/%.asm
	$(ASM) $(ASMFLAGS) $(DEBUG_ASMFLAGS) -o $@ $<

# creation of ASM release objects
$(DIR_OBJ)/%.r.o: $(DIR_SRC)/%.asm
	$(ASM) $(ASMFLAGS) $(RELEASE_ASMFLAGS) -o $@ $<


## specification of C and C++ flags
define COMPILE_AND_DEPEND_DEBUG
	$(CPP) -c -MMD -MF $(DIR_OBJ)/$*.d.d -MT $(DIR_OBJ)/$*.d.o $(CPPFLAGS) $(DEBUG_CPPFLAGS) -o $@ $(CURDIR)/$<
	@cp $(DIR_OBJ)/$*.d.d $(DIR_OBJ)/$*.d.p; \
		sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
		-e '/^$$/ d' -e 's/$$/ :/' < $(DIR_OBJ)/$*.d.d >> $(DIR_OBJ)/$*.d.p; \
		rm -f $(DIR_OBJ)/$*.d.d
endef
define COMPILE_AND_DEPEND_RELEASE
	$(CPP) -c -MMD -MF $(DIR_OBJ)/$*.r.d -MT $(DIR_OBJ)/$*.r.o $(CPPFLAGS) $(RELEASE_CPPFLAGS) -o $@ $(CURDIR)/$<
	@cp $(DIR_OBJ)/$*.r.d $(DIR_OBJ)/$*.r.p; \
		sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
		-e '/^$$/ d' -e 's/$$/ :/' < $(DIR_OBJ)/$*.r.d >> $(DIR_OBJ)/$*.r.p; \
		rm -f $(DIR_OBJ)/$*.r.d
endef

# creation of C++ debug objects
$(DIR_OBJ)/%.d.o: $(DIR_SRC)/%.cpp
	$(COMPILE_AND_DEPEND_DEBUG)

# creation of C++ release objects
$(DIR_OBJ)/%.r.o: $(DIR_SRC)/%.cpp
	$(COMPILE_AND_DEPEND_RELEASE)

# creation of C debug objects
$(DIR_OBJ)/%.d.o: $(DIR_SRC)/%.c
	$(COMPILE_AND_DEPEND_DEBUG)

# creation of C release objects
$(DIR_OBJ)/%.r.o: $(DIR_SRC)/%.c
	$(COMPILE_AND_DEPEND_RELEASE)


## config dependent directory setup
ifeq ($(CONFIG), CONSOLE)
  CHECK_DIRS = $(DIR_OBJ) $(DIR_BIN)
else
 ifeq ($(CONFIG), LIBRARY)
  CHECK_DIRS = $(DIR_OBJ) $(DIR_LIB)
 endif
endif


## specification of build targets
all:        check_errors debug release

debug:      check_errors \
			$(CHECK_DIRS) \
			$(STAT_DEBUG_OUT)

# $(DYN_DEBUG_OUT) \

release:    check_errors \
			$(CHECK_DIRS) \
			$(STAT_RELEASE_OUT)

# $(DYN_RELEASE_OUT) \


## check for configuration errors
check_errors:
	@if [ "$(CONFIG_ERR)" = "TRUE" ]; then\
		echo "ERROR: Wrong CONFIG parameter specified: $(CONFIG)";\
	false;\
	fi


## creation of output directories
$(DIR_BIN):
	@if [ ! -d $(DIR_BIN) ]; then\
		mkdir $(DIR_BIN);\
	fi

$(DIR_OBJ):
	@if [ ! -d $(DIR_OBJ) ]; then\
		mkdir $(DIR_OBJ);\
	fi

$(DIR_LIB):
	@if [ ! -d $(DIR_LIB) ]; then\
		mkdir $(DIR_LIB);\
	fi


## creation of binary output files
ifeq ($(CONFIG), CONSOLE)
# creation of static debug output
$(STAT_DEBUG_OUT): $(DEBUG_OBJS) $(STAT_DEBUG_PREREQS)
	$(LD) -o $@ $(LDFLAGS) $(DEBUG_LDFLAGS) $(DEBUG_OBJS) -L$(DIR_LIB) $(LIBS) $(STAT_LIBS) $(STAT_DEBUG_LIBS)
# creation of static release output
$(STAT_RELEASE_OUT): $(RELEASE_OBJS) $(STAT_RELEASE_PREREQS)
	$(LD) -o $@ $(LDFLAGS) $(RELEASE_LDFLAGS) $(RELEASE_OBJS) -L$(DIR_LIB) $(LIBS) $(STAT_LIBS) $(STAT_RELEASE_LIBS)
# creation of dynamic debug output
$(DYN_DEBUG_OUT): $(DEBUG_OBJS) $(DYN_DEBUG_PREREQS)
	$(LD) -o $@ $(LDFLAGS) $(DEBUG_LDFLAGS) $(DEBUG_OBJS) -L$(DIR_LIB) $(LIBS) $(DYN_LIBS) $(DYN_DEBUG_LIBS)
# creation of dynamic release output
$(DYN_RELEASE_OUT): $(RELEASE_OBJS) $(DYN_RELEASE_PREREQS)
	$(LD) -o $@ $(LDFLAGS) $(RELEASE_LDFLAGS) $(RELEASE_OBJS) -L$(DIR_LIB) $(LIBS) $(DYN_LIBS) $(DYN_RELEASE_LIBS)
else
 ifeq ($(CONFIG), LIBRARY)
# creation of static debug output
$(STAT_DEBUG_OUT): $(DEBUG_OBJS)
	$(AR) -crs $@ $(DEBUG_OBJS)
# creation of static release output
$(STAT_RELEASE_OUT): $(RELEASE_OBJS)
	$(AR) -crs $@ $(RELEASE_OBJS)
# creation of dynamic debug output
$(DYN_DEBUG_OUT): $(DYN_DEBUG_OUT)
	ln -fs lib$(PRD_NAME)Dynd.so $@
# creation of dynamic release output
$(DYN_RELEASE_OUT): $(DYN_RELEASE_OUT)
	ln -fs lib$(PRD_NAME)Dyn.so $@
 endif
endif


## clean: delete all created files
clean:
	/bin/rm -rf $(DYN_DEBUG_OUT)
	/bin/rm -rf $(DYN_RELEASE_OUT)
	/bin/rm -rf $(STAT_DEBUG_OUT)
	/bin/rm -rf $(STAT_RELEASE_OUT)
	/bin/rm -rf $(DIR_OBJ)


## include needed dependency files
-include $(OBJS:.o=.d.p)
-include $(OBJS:.o=.r.p)
