# BlinkenLib
# Copyright 2004-2023 Stefan Schuermans <stefan@schuermans.info>
# Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
# a blinkenarea.org project

include version.mk

SUFFIXES :=
.SUFFIXES:

.SECONDARY:

##################
# default target #
##################

.PHONY: all
all: build_all

###########
# cleanup #
###########

.PHONY: clean
clean:
	rm -rf build lib bin

.PHONY: distclean
distclean: clean
	rm -rf cfg

############
# settings #
############

CC := gcc
AR := ar
RANLIB := ranlib
INSTALL := install

#################
# configuration #
#################

CFG_INCDIR := -I/sw/include
CFG_LIBDIR := -L/sw/lib

CONFS := cfg/config.mk cfg/include/BlinkenLib/config.h

.PHONY: conf
conf: $(CONFS) ;

cfg:
	mkdir $@

cfg/win.cfg: config/win.c | cfg
	if $(CC) -E -o /dev/null $<; \
	  then echo "WIN=1"; \
	  else echo "WIN=0"; \
	  fi >$@

cfg/osx.cfg: | cfg
	if [ "$$(uname -s)" == "Darwin" ]; \
	  then echo "OSX=1"; \
	  else echo "OSX=0"; \
	  fi >$@

cfg/bin: | cfg
	mkdir $@

cfg/mng.cfg: | cfg/bin
	if $(CC) $(CFG_INCDIR) $(CFG_LIBDIR) -o cfg/bin/mng config/mng.c -lmng \
	  && cfg/bin/mng; \
	  then echo "MNG=1"; \
	  else echo "MNG=0"; \
	  fi >>$@

cfg/gif%.cfg: | cfg/bin
	if $(CC) $(CFG_INCDIR) $(CFG_LIBDIR) -o cfg/bin/gif$* config/gif$*.c -lgif \
	  && ./cfg/bin/gif$*; \
	  then echo "GIF$*=1"; \
	  else echo "GIF$*=0"; \
	  fi >$@

cfg/gif.cfg: cfg/gif4.cfg cfg/gif5.cfg
	if grep -q 1 $^; \
	  then echo "GIF=1"; \
	  else echo "GIF=0"; \
	  fi >$@

cfg/config.cfg: $(addprefix cfg/,$(addsuffix .cfg,win osx mng gif gif4 gif5))
	cat $^ >$@

cfg/config.mk: cfg/config.cfg
	sed 's/^\([A-Z0-9]*\)=\([01]\)$$/BLINKENLIB_CFG_\1:=\2/' <$< >$@

cfg/include: | cfg
	mkdir $@

cfg/include/BlinkenLib: | cfg/include
	mkdir $@

cfg/include/BlinkenLib/config.h: cfg/config.cfg version.mk \
                                 | cfg/include/BlinkenLib
	sed 's/^\([A-Z0-9]*\)=0$$/#undef BLINKENLIB_CFG_\1/;s/^\([A-Z0-9]*\)=1$$/#define BLINKENLIB_CFG_\1/' <$< >$@
	echo '#define BLINKENLIB_CONFIG "' | tr -d '\n' >>$@
	sed 's/^\([A-Z0-9]*\)=0$$/\1-/;s/^\([A-Z0-9]*\)=1$$/\1+/' <$< | tr '\n' ' ' | sed 's/ *$$//' | tr -d '\n' >>$@
	echo '"' >>$@
	grep '^VERSION_[A-Z]* *:= *[0-9]*' version.mk | sed 's/^/#define BLINKENLIB_/;s/ *:= */ /' >>$@

###############
# compilation #
###############

-include cfg/config.mk

CFLAGS := -Wall -Wextra -Werror -fPIC -O2 -Iinclude -Icfg/include
LIB_LDFLAGS :=
LIB_LDLIBS :=
TOOLS_LDFLAGS := -Llib
TOOLS_LDLIBS :=

LIB_LIST := BlinkenColorizer BlinkenFrame BlinkenMovie BlinkenProto BlinkenTools Tools
TOOLS_HELP_LIST := Tools2
TOOLS_LIST := BlinkenConv BlinkenRecv BlinkenSend

ifeq ($(BLINKENLIB_CFG_MNG),1)
  LIB_LIST += BlinkenMng
  LIB_LDLIBS += -lmng -lz
endif

ifeq ($(BLINKENLIB_CFG_GIF),1)
  LIB_LIST += BlinkenGif
  LIB_LDLIBS += -lgif
endif

ifeq ($(BLINKENLIB_CFG_WIN),1)
  SHLIBEXT := dll
  TOOLS_SUFFIX := .exe
  LIB_LDLIBS += -lws2_32
  TOOLS_LDLIBS += -lws2_32
  TOOLS_LIST += BlinkenOutputWin
else
  ifeq ($(BLINKENLIB_CFG_OSX),1)
    CFLAGS += -I/sw/include
    SHLIBEXT := dylib
    TOOLS_SUFFIX :=
    LIB_LDFLAGS += -L/sw/lib
    TOOLS_LDFLAGS += -L/sw/lib -Wl,-rpath,'$$ORIGIN/../lib'
    TOOLS_LIST += BlinkenDeviceOutput BlinkenOutput
  else
    SHLIBEXT := so
    TOOLS_SUFFIX :=
    LIB_LDFLAGS += -Wl,-soname,libBlinkenLib.$(SHLIBEXT).$(VERSION_MAJOR)
    TOOLS_LDFLAGS += -Wl,-rpath,'$$ORIGIN/../lib'
    TOOLS_LIST += BlinkenDeviceOutput BlinkenOutput
  endif
endif

ALL_LIST := $(LIB_LIST) $(TOOLS_LIST) $(TOOLS_HELP_LIST)
ALL_DEPS := $(addprefix build/,$(addsuffix .d,$(ALL_LIST)))
ALL_OBJS := $(addprefix build/,$(addsuffix .o,$(ALL_LIST)))
LIB_OBJS := $(addprefix build/,$(addsuffix .o,$(LIB_LIST)))
TOOLS_HELP_OBJS := $(addprefix build/,$(addsuffix .o,$(TOOLS_HELP_LIST)))
TOOLS_BINS := $(addprefix bin/,$(addsuffix $(TOOLS_SUFFIX),$(TOOLS_LIST)))

-include $(ALL_DEPS)

.PHONY: build_all
build_all: conf $(ALL_DEPS) build_lib build_tools ;

.PHONY: build_lib
build_lib: lib/libBlinkenLib.a \
           lib/libBlinkenLib.$(SHLIBEXT).$(VERSION_MAJOR) \
           lib/libBlinkenLib.$(SHLIBEXT).$(VERSION) \
           lib/libBlinkenLib.$(SHLIBEXT) ;

.PHONY: build_tools
build_tools: $(TOOLS_BINS) ;

build:
	mkdir $@

build/%.d: src/%.c cfg/config.mk | build
	$(CC) $(CFLAGS) -MM -MT $(@:.d=.o) -o $@ $<

build/%.o: src/%.c | build
	$(CC) $(CFLAGS) -c -o $@ $<

lib:
	mkdir $@

lib/libBlinkenLib.a: $(LIB_OBJS) | lib
	$(AR) cr $@ $^
	$(RANLIB) $@

lib/libBlinkenLib.$(SHLIBEXT).$(VERSION): $(LIB_OBJS) | lib
	$(CC) -shared $(LIB_LDFLAGS) -o $@ $+ $(LIB_LDLIBS)

lib/libBlinkenLib.$(SHLIBEXT).$(VERSION_MAJOR): lib/libBlinkenLib.$(SHLIBEXT).$(VERSION)
	ln -fs $(notdir $<) $@

lib/libBlinkenLib.$(SHLIBEXT): lib/libBlinkenLib.$(SHLIBEXT).$(VERSION_MAJOR)
	ln -fs $(notdir $<) $@

build/%.d: tools/%.c | build
	$(CC) $(CFLAGS) -MM -MT $(@:.d=.o) -o $@ $<

build/%.o: tools/%.c | build
	$(CC) $(CFLAGS) -c -o $@ $<

build/libBlinkenLibToolsHelp.a: $(TOOLS_HELP_OBJS) | lib
	$(AR) cr $@ $^
	$(RANLIB) $@

bin:
	mkdir $@

bin/%$(TOOLS_SUFFIX): lib/libBlinkenLib.$(SHLIBEXT)

bin/%$(TOOLS_SUFFIX): build/%.o build/libBlinkenLibToolsHelp.a | bin
	$(CC) $(TOOLS_LDFLAGS) -o $@ $^ -lBlinkenLib $(TOOLS_LDLIBS)

################
# installation #
################

INSTALL_HEADER_LIST := BlinkenLib BlinkenMovie BlinkenFrame BlinkenColorizer \
                       BlinkenProto

ENV_PREFIX := $(shell echo $$PREFIX)
STOW_DIR := /usr/local/stow
STOW_PREFIX := $(STOW_DIR)/BlinkenLib-$(VERSION)
DEF_PREFIX := /usr/local
ifneq ($(ENV_PREFIX),)
  PREFIX := $(ENV_PREFIX)
else
  ifeq ($(shell if test -d $(STOW_DIR); then echo stow; fi),stow)
    PREFIX := $(STOW_PREFIX)
  else
    PREFIX := $(DEF_PREFIX)
  endif
endif

INSTALL_HEADERS := cfg/include/BlinkenLib/config.h \
                   $(addprefix include/BlinkenLib/,$(addsuffix .h,$(INSTALL_HEADER_LIST)))
INSTALL_LIBS := lib/libBlinkenLib.a lib/libBlinkenLib.$(SHLIBEXT).$(VERSION)
INSTALL_BINS := $(addprefix bin/,$(addsuffix $(TOOLS_SUFFIX),$(TOOLS_LIST)))

.PHONY: install
install:
	$(INSTALL) -d $(PREFIX)/include/BlinkenLib
	$(INSTALL) $(INSTALL_HEADERS) $(PREFIX)/include/BlinkenLib
	$(INSTALL) -d $(PREFIX)/lib
	$(INSTALL) $(INSTALL_LIBS) $(PREFIX)/lib
	ln -sf libBlinkenLib.$(SHLIBEXT).$(VERSION) $(PREFIX)/lib/libBlinkenLib.$(SHLIBEXT).$(VERSION_MAJOR)
	ln -sf libBlinkenLib.$(SHLIBEXT).$(VERSION_MAJOR) $(PREFIX)/lib/libBlinkenLib.$(SHLIBEXT)
	$(INSTALL) -d $(PREFIX)/bin
	$(INSTALL) $(INSTALL_BINS) $(PREFIX)/bin

.PHONY: uninstall
uninstall:
	rm -f $(addprefix $(PREFIX)/bin/,$(notdir $(INSTALL_BINS)))
	rm -f $(PREFIX)/lib/libBlinkenLib.$(SHLIBEXT)
	rm -f $(PREFIX)/lib/libBlinkenLib.$(SHLIBEXT).$(VERSION_MAJOR)
	rm -f $(addprefix $(PREFIX)/lib/,$(notdir $(INSTALL_LIBS)))
	rm -rf $(PREFIX)/include/BlinkenLib