# Makefile targets:
# - make 
# 		builds the main program
# - make debug 
#   	builds with DEBUG flag
# - make file 
#   	builds using camera_file.c, reads video from pipe
# - RESX=XXX RESY=XXX UPS=XXX ZPUPS=XXX make bench 
#   	compile using the line arguments values, useful for scripting

LIBS = -lm -lfftw3f -lv4l2 -lturbojpeg -lpthread

CFLAGS = -O2 -ftree-vectorize -funroll-loops -Wall #-fopt-info-vec 
# Profiling gprof
#CFLAGS += -pg -g3
# Profiling perf
#CFLAGS += -fno-omit-frame-pointer
# Sanitize
#CFLAGS += -fsanitize=address

# Hardware specification flags
# DE1-SoC needs to specify the fpu to auto-vectorize
check = $(shell grep "Altera SOCFPGA" /proc/cpuinfo)
ifneq ($(check),)
	CFLAGS+= -mcpu=cortex-a9 -mfloat-abi=hard -mfpu=neon  
else
# Default flags, works on all the hardware but it may have to be modified to support auto-vectorization
	CFLAGS+=-march=native 
endif

TARGET = sensor
BUILDDIR = build

SRCS = camera.c fft.c serial.c benchmark.c sensor.c misc.c
OBJS = $(patsubst %.c,$(BUILDDIR)/%.o,$(SRCS))
DEPS = $(patsubst %.c,$(BUILDDIR)/%.d,$(SRCS))
OBJSDBG = $(patsubst %.c,$(BUILDDIR)/%_debug.o,$(SRCS))
OBJSBNC = $(patsubst %.c,$(BUILDDIR)/%_bench.o,$(SRCS))

SRCSFILE = camera_file.c fft.c serial.c benchmark.c sensor.c misc.c
OBJSFILE = $(SRCSFILE:%.c=$(BUILDDIR)/%.o)
OBJSDBGFILE = $(OBJSFILE:%.o=%_debug.o)
OBJSBNCFILE = $(OBJSFILE:%.o=%_bench.o)

# rules executed even if files of those names exists
.PHONY: all clean debug cleaner file filedebug bench cppcheck $(TARGET) .FORCE

$(TARGET): dir $(TARGET)_

$(TARGET)_: $(OBJS) 
	$(CC) $(CFLAGS) $^ -o $(TARGET) $(LIBS)

all: dir $(TARGET) $(TARGET)_debug $(TARGET)_file $(TARGET)_file_debug

dir:
	@mkdir -p $(BUILDDIR)

debug: dir $(TARGET)_debug

$(TARGET)_debug: $(OBJSDBG) 
	$(CC) $(CFLAGS) -g $^ -o $@ $(LIBS) 

bench: BENCHFLAG=-D BRESX=$$RESX -D BRESY=$$RESY -D BUPS=$$UPS -D BZPUPS=$$ZPUPS -D BENCHMARK
bench: checkbench dir $(TARGET)_bench

$(TARGET)_bench: $(OBJSBNC) 
	$(CC) $(CFLAGS) -g $^ -o $@ $(LIBS) 

file: filetouch
file_: FILEFLAG=-D FILECAMERA
file_: dir $(TARGET)_file

filetouch:
	-mv ${BUILDDIR}/sensor.o ${BUILDDIR}/sensor.o.bk
	$(MAKE) file_
	-mv ${BUILDDIR}/sensor.o.bk ${BUILDDIR}/sensor.o

$(TARGET)_file: $(OBJSFILE)
	$(CC) $(CFLAGS) -g $^ -o $@ $(LIBS)

filedebug: FILEFLAG=-D FILECAMERA
filedebug: dir $(TARGET)_file_debug

$(TARGET)_file_debug : $(OBJSDBGFILE)
	$(CC) $(CFLAGS) -g $^ -o $@ $(LIBS) 

filebench: FILEFLAG=-D FILECAMERA 
filebench: BENCHFLAG=-D BRESX=$$RESX -D BRESY=$$RESY -D BUPS=$$UPS -D BZPUPS=$$ZPUPS -D BENCHMARK
filebench: checkbench dir $(TARGET)_file_bench

$(TARGET)_file_bench : $(OBJSBNCFILE)
	$(CC) $(CFLAGS) -g $^ -o $@ $(LIBS) 

checkbench:
ifndef RESX
	echo Please specify RESX, RESY, ZPUPS and UPS as environment variables
	exit 1
endif
ifndef RESY
	echo Please specify RESX, RESY, ZPUPS and UPS as environment variables
	exit 1
endif
ifndef ZPUPS
	echo Please specify RESX, RESY, ZPUPS and UPS as environment variables
	exit 1
endif
ifndef UPS
	echo Please specify RESX, RESY, ZPUPS and UPS as environment variables
	exit 1
endif

cppcheck: 
	cppcheck . --force --enable=all -U BRESX -U BRESY -U BUPS -U BZPUPS 1> /dev/null 

doc:
	doxygen -g
	doxygen Doxyfile

clean: 
	$(RM) -r $(DEPS) $(BUILDDIR) html latex gmon.out perf.data

cleaner: 
	$(RM) -r $(TARGET) $(DEPS) $(BUILDDIR) $(TARGET)_file $(TARGET)_debug $(TARGET)_file_debug $(TARGET)_bench $(TARGET)_file_bench Doxyfile Doxyfile.bak html latex gmon.out perf.data

.FORCE:

-include $(DEPS) 

$(BUILDDIR)/%.o : %.c Makefile config.h common.h
	$(CC) $(CFLAGS) -MMD -c $< -o $@ $(FILEFLAG)

$(BUILDDIR)/%_debug.o : %.c Makefile config.h common.h .FORCE
	$(CC) $(CFLAGS) -g -MMD -c $< -o $@ -D DEBUG $(FILEFLAG)

$(BUILDDIR)/%_bench.o : %.c Makefile config.h common.h .FORCE
	$(CC) $(CFLAGS) -g -MMD -c $< -o $@ $(BENCHFLAG) $(FILEFLAG)
