# for release
MODEFLAGS := -O3
TARGETDIR := build

PRFX_PATH        ?= ~/opt/oclh
OPENCL_INCLUDES  := -I"/usr/local/cuda/include"
OPENCL_LIBRARIES := -L/usr/local/cuda/lib64 -L/opt/intel/opencl/lib64

OCLH_LIBRARY_NAME  := liboclh.so.0.0
OCLH_COMPILER_NAME := oclh_cr
OCLH_LINKER_NAME   := oclh_lr
OCLH_BUILDER_NAME  := oclh_br

RM          := rm -rf
CC          := gcc
LINKER      := gcc
CFLAGS      := -std=c11 -pedantic -Wall -Wextra -Wconversion
LDFLAGS     := $(OPENCL_LIBRARIES)
OUTPUTFLAGS := -c -fmessage-length=0
MISCFLAGS   := -pthread
INCLUDES    := -I"src/include_h/" -I"src/include_hd/" $(OPENCL_INCLUDES)
LIBS        := -lOpenCL

# Every subdirectory with source files must be described here
SRCDIR := src
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS        := $(wildcard $(SRCDIR)/*.c)
C_SRCS_LIB    := $(wildcard $(SRCDIR)/oclh_h*.c)
TARGETDIR_LIB := $(TARGETDIR)/lib.o
OBJS_LIB      := $(patsubst $(SRCDIR)/%.c,$(TARGETDIR_LIB)/%.o,$(C_SRCS_LIB))
C_DEPS_LIB    := $(wildcard $(TARGETDIR_LIB)/*.d)
TARGETDIR_CR  := $(TARGETDIR)/cr.o
OBJS_CR       := $(patsubst $(SRCDIR)/%.c,$(TARGETDIR_CR)/%.o,$(C_SRCS))
C_DEPS_CR     := $(wildcard $(TARGETDIR_CR)/*.d)
TARGETDIR_LR  := $(TARGETDIR)/lr.o
OBJS_LR       := $(patsubst $(SRCDIR)/%.c,$(TARGETDIR_LR)/%.o,$(C_SRCS))
C_DEPS_LR     := $(wildcard $(TARGETDIR_LR)/*.d)
TARGETDIR_BR  := $(TARGETDIR)/br.o
OBJS_BR       := $(patsubst $(SRCDIR)/%.c,$(TARGETDIR_BR)/%.o,$(C_SRCS))
C_DEPS_BR     := $(wildcard $(TARGETDIR_BR)/*.d)

# Each subdirectory must supply rules for building sources it contributes
$(TARGETDIR_BR)/%.o: $(SRCDIR)/%.c
	mkdir -p $(TARGETDIR_BR); \
	$(CC) $(INCLUDES) $(MODEFLAGS) $(CFLAGS) $(DEFS) $(OUTPUTFLAGS) \
	-MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
$(TARGETDIR_CR)/%.o: $(SRCDIR)/%.c
	mkdir -p $(TARGETDIR_CR); \
	$(CC) $(INCLUDES) $(MODEFLAGS) $(CFLAGS) $(DEFS) $(OUTPUTFLAGS) \
	-MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
$(TARGETDIR_LR)/%.o: $(SRCDIR)/%.c
	mkdir -p $(TARGETDIR_LR); \
	$(CC) $(INCLUDES) $(MODEFLAGS) $(CFLAGS) $(DEFS) $(OUTPUTFLAGS) \
	-MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
$(TARGETDIR_LIB)/%.o: $(SRCDIR)/%.c
	mkdir -p $(TARGETDIR_LIB); \
	$(CC) $(INCLUDES) $(MODEFLAGS) $(CFLAGS) $(DEFS) $(OUTPUTFLAGS) \
	-fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"

# Add inputs and outputs from these tool invocations to the build variables
# All Target
all: oclh_library oclh_compiler oclh_linker oclh_builder
debug: MODEFLAGS := -O0 -g3
debug: oclh_library oclh_compiler oclh_linker oclh_builder
# Tool invocations
oclh_compiler: DEFS := -D__OCLH_COMPILER_ONLY_FLAG -D__OCLH_BUILD_LOG_TO_STDOUT_FLAG
oclh_compiler: OUTPUTNAME := $(OCLH_COMPILER_NAME)
oclh_compiler: $(OBJS_CR)
	@echo 'Building target: $@'
	@echo 'Invoking C Linker'
	$(LINKER) $(LDFLAGS) $(MISCFLAGS) $(LIBS) $(OBJS_CR) \
	-o "$(TARGETDIR)/$(OUTPUTNAME)"
	@echo 'Finished building target: $@'
	@echo ' '
oclh_linker: DEFS := -D__OCLH_LINKER_ONLY_FLAG -D__OCLH_BUILD_LOG_TO_STDOUT_FLAG
oclh_linker: OUTPUTNAME := $(OCLH_LINKER_NAME)
oclh_linker: $(OBJS_LR)
	@echo 'Building target: $@'
	@echo 'Invoking C Linker'
	$(LINKER) $(LDFLAGS) $(MISCFLAGS) $(LIBS) $(OBJS_LR) \
	-o "$(TARGETDIR)/$(OUTPUTNAME)"
	@echo 'Finished building target: $@'
	@echo ' '
oclh_builder: DEFS := -D__OCLH_BUILDER_FLAG -D__OCLH_BUILD_LOG_TO_STDOUT_FLAG
oclh_builder: OUTPUTNAME := $(OCLH_BUILDER_NAME)
oclh_builder: $(OBJS_BR)
	@echo 'Building target: $@'
	@echo 'Invoking C Linker'
	$(LINKER) $(LDFLAGS) $(MISCFLAGS) $(LIBS) $(OBJS_BR) \
	-o "$(TARGETDIR)/$(OUTPUTNAME)"
	@echo 'Finished building target: $@'
	@echo ' '
oclh_library: OUTPUTNAME := $(OCLH_LIBRARY_NAME)
oclh_library: $(OBJS_LIB)
	@echo 'Building target: $@'
	@echo 'Invoking C Linker'
	$(LINKER) $(LDFLAGS) $(MISCFLAGS) $(LIBS) $(OBJS_LIB) \
	-shared -Wl,-soname,liboclh.so.0.0 -o "$(TARGETDIR)/$(OUTPUTNAME)"
	@echo 'Finished building target: $@'
	@echo ' '
install:
	mkdir -p $(PRFX_PATH)/bin
	    cp $(TARGETDIR)/$(OCLH_COMPILER_NAME) $(PRFX_PATH)/bin
	    cp $(TARGETDIR)/$(OCLH_LINKER_NAME)   $(PRFX_PATH)/bin
	    cp $(TARGETDIR)/$(OCLH_BUILDER_NAME)  $(PRFX_PATH)/bin
	mkdir -p $(PRFX_PATH)/lib
	    cp $(TARGETDIR)/$(OCLH_LIBRARY_NAME)  $(PRFX_PATH)/lib
	mkdir -p $(PRFX_PATH)/include/include_h
	    cp $(SRCDIR)/include_h/*  $(PRFX_PATH)/include/include_h
	mkdir -p $(PRFX_PATH)/include/include_hd
	    cp $(SRCDIR)/include_hd/* $(PRFX_PATH)/include/include_hd
	mkdir -p $(PRFX_PATH)/include/include_d
	    cp $(SRCDIR)/include_d/*  $(PRFX_PATH)/include/include_d
uninstall:
	$(RM) $(PRFX_PATH)/bin/$(OCLH_COMPILER_NAME) \
	      $(PRFX_PATH)/bin/$(OCLH_LINKER_NAME) \
	      $(PRFX_PATH)/bin/$(OCLH_LINKER_NAME)  $(PRFX_PATH)/bin \
	      $(PRFX_PATH)/lib/$(OCLH_LIBRARY_NAME) $(PRFX_PATH)/lib \
	      $(PRFX_PATH)/include/include_h/*  $(PRFX_PATH)/include/include_h \
	      $(PRFX_PATH)/include/include_hd/* $(PRFX_PATH)/include/include_hd \
	      $(PRFX_PATH)/include/include_d/*  $(PRFX_PATH)/include/include_d \
	      $(PRFX_PATH)/include $(PRFX_PATH)
clean:
	$(RM) \
	    $(OBJS_LIB) $(C_DEPS_LIB) $(TARGETDIR_LIB) \
	    $(OBJS_CR)  $(C_DEPS_CR)  $(TARGETDIR_CR) \
	    $(OBJS_LR)  $(C_DEPS_LR)  $(TARGETDIR_LR) \
	    $(OBJS_BR)  $(C_DEPS_BR)  $(TARGETDIR_BR) \
	    $(TARGETDIR)/$(OCLH_BUILDER_NAME) \
	    $(TARGETDIR)/$(OCLH_COMPILER_NAME) \
	    $(TARGETDIR)/$(OCLH_LINKER_NAME) \
	    $(TARGETDIR)/$(OCLH_LIBRARY_NAME)
	@echo ' '

.PHONY: all clean debug
