
#------------------------------------------------------------------------------------- Compiler

ifeq ($(origin CC),default) # CC not explicitly overridden
	ifeq ($(GCC),1)
		override CC=gcc
	else ifeq ($(CLANG),1)
		override CC=clang
	endif
endif

ifeq ($(origin CXX),default) # CXX not explicitly overridden
	ifeq ($(GCC),1)
		override CXX=g++
	else ifeq ($(CLANG),1)
		override CXX=clang++
	endif
endif

export CC
export CXX

#--------------------------------------------------------------------------------- Preprocessor

define CC_FLAGS.ccdeps
	-MMD
	-MF $(@:.o=.d)
endef

CC_FLAGS.defs=$(foreach d,$(call flatten,$(CC_DEFS)),-D$(d))

CC_INCLUDES += $(CC_INCLUDES.$(OSNICK)) $(CC_INCLUDES.$(OS))  $(CC_INCLUDES.$(ARCH))
CC_FLAGS.includes=$(foreach d,$(call flatten,$(CC_INCLUDES)),-I$(d))

CC_COMMON_H ?= $(SRCDIR)/common.h
_CC_COMMON_H=$(realpath $(CC_COMMON_H))
ifneq ($(CC_COMMON_H),0)
	ifneq ($(wildcard $(_CC_COMMON_H)),)
		CC_FLAGS.common += -include $(_CC_COMMON_H)
	endif
endif

#----------------------------------------------------------------------------------------------

define CC_FLAGS.common +=
	-fPIC
	-pthread
	-fno-strict-aliasing
endef

#-------------------------------------------------------------------------------------- Codegen

CC_FLAGS.debug += -g -ggdb
ifeq ($(DEBUG),1)
	CC_FLAGS.opt += -fno-omit-frame-pointer -O0
	CC_FLAGS.debug += -DDEBUG -D_DEBUG
	CC_DEFS += DEBUG _DEBUG
else
	ifeq ($(PROFILE),1)
		CC_FLAGS.opt += -fno-omit-frame-pointer -O2
	else
		CC_FLAGS.opt += -O3
	endif
endif

#------------------------------------------------------------------------------------- Language

ifeq ($(CC_PEDANTIC),1)
define CC_FLAGS.warnings +=
	-Wall
	-Wpedantic
endef
endif

define CC_FLAGS.warnings +=
	-Wno-unused-function
	-Wno-unused-variable
	-Wno-sign-compare
endef

#----------------------------------------------------------------------------------------------

define CC_C_FLAGS.warnings +=
	-Werror=incompatible-pointer-types
	-Werror=implicit-function-declaration
endef

#	-Wno-error=incompatible-pointer-types-discards-qualifiers

ifneq ($(CC_C_STD),)
CC_C_FLAGS.lang += -std=$(CC_C_STD)
endif

#----------------------------------------------------------------------------------------------

ifneq ($(CC_CXX_STD),)
CC_CXX_FLAGS.lang += -std=$(CC_CXX_STD)
endif

ifeq ($(CC_EXCEPTIONS),0)
CC_CXX_FLAGS.lang += -fno-exceptions
endif

ifeq ($(CC_RTTI),0)
CC_CXX_FLAGS.lang += -fno-rtti
endif

#-------------------------------------------------------------------------------------- Summary

define _CC_FLAGS.core
	$(CC_FLAGS.common)
	$(CC_FLAGS.includes)
	$(CC_FLAGS.opt)
	$(CC_FLAGS.warnings)
	$(CC_FLAGS.debug)
	$(CC_FLAGS.coverage)
	$(CC_FLAGS.sanitizer)
	$(CC_FLAGS.$(OS))
endef
CC_FLAGS.core=$(call flatten,$(_CC_FLAGS.core))

#----------------------------------------------------------------------------------------------

define _CC_FLAGS
	$(CC_FLAGS.core)
	$(CC_FLAGS.ccdeps)
	$(CC_FLAGS.defs)
endef
CC_FLAGS += $(call flatten,$(_CC_FLAGS))

define _CC_C_FLAGS +=
	-fcommon
	$(CC_C_FLAGS.lang)
	$(CC_C_FLAGS.warnings)
endef
CC_C_FLAGS=$(call flatten,$(_CC_C_FLAGS))

#----------------------------------------------------------------------------------------------

define _CC_CXX_FLAGS +=
	$(CC_CXX_FLAGS.lang)
	$(CC_CXX_FLAGS.warnings)
	$(CC_CXX_FLAGS.sanitizer)
endef
CC_CXX_FLAGS=$(call flatten,$(_CC_CXX_FLAGS))

#--------------------------------------------------------------------------------------- Linker

ifeq ($(CC_STATIC_LIBSTDCXX),1)
LD_FLAGS.common += -static-libstdc++
endif

ifeq ($(CC_STATIC_LIBGCC),1)
LD_FLAGS.common += -static-libgcc
endif

#----------------------------------------------------------------------------------------------

define LD_FLAGS.common +=
	-pthread
endef

define _LD_FLAGS
	$(LD_FLAGS.common)
	$(LD_FLAGS.$(OS))
	$(LD_FLAGS.coverage)
	$(LD_FLAGS.sanitizer)
endef
LD_FLAGS += $(call flatten,$(_LD_FLAGS))

define _SO_LD_FLAGS
	$(SO_LD_FLAGS.common)
	$(SO_LD_FLAGS.$(OS))
endef
SO_LD_FLAGS += $(call flatten,$(_SO_LD_FLAGS))

define SO_LD_FLAGS.linux +=
	-shared
endef

define SO_LD_FLAGS.macos +=
	-dynamiclib
endef

LINK_SO_INTERNAL_BINDING ?= 1
ifeq ($(LINK_SO_INTERNAL_BINDING),1)
	SO_LD_FLAGS.linux += -Wl,-Bsymbolic,-Bsymbolic-functions
endif

#----------------------------------------------------------------------------------------------

define EXE_LD_FLAGS.common +=
endef

define _EXE_LD_FLAGS
	$(EXE_LD_FLAGS.common)
	$(EXE_LD_FLAGS.$(OS))
endef
EXE_LD_FLAGS += $(call flatten,$(_EXE_LD_FLAGS))

#----------------------------------------------------------------------------------------------

define DYLIB_LD_FLAGS.macos +=
	-dynamiclib
	 -undefined dynamic_lookup
endef

define _DYLIB_LD_FLAGS
	$(DYLIB_LD_FLAGS.common)
	$(DYLIB_LD_FLAGS.$(OS))
endef
DYLIB_LD_FLAGS += $(call flatten,$(_DYLIB_LD_FLAGS))

#----------------------------------------------------------------------------------------- Libs

define LD_LIBS.common +=
	c
	m
	dl
	pthread
endef

define LD_LIBS.linux +=
	rt
endef

define LD_LIBS.macos +=
endef

define _LD_LIBS
	$(LD_LIBS.common)
	$(LD_LIBS.$(OS))
	$(LD_LIBS.ext)
endef
_LD_LIBS.flat=$(call flatten,$(_LD_LIBS))
_LD_LIBS.qualified=$(filter /%,$(_LD_LIBS.flat)) $(filter -%,$(_LD_LIBS.flat))
LD_LIBS += \
	$(_LD_LIBS.qualified) \
	$(foreach LIB,$(filter-out $(_LD_LIBS.qualified),$(_LD_LIBS.flat)),-l$(LIB))

#---------------------------------------------------------------------------------------- CMake

export CMAKE_CC_FLAGS=\
	-UNDEBUG \
	$(CC_FLAGS.core)

export CMAKE_CC_C_FLAGS=$(CC_C_FLAGS)
export CMAKE_CC_CXX_FLAGS=$(CC_CXX_FLAGS)

export CMAKE_LD_FLAGS=$(LD_FLAGS)
export CMAKE_SO_LD_FLAGS=$(SO_LD_FLAGS)
export CMAKE_EXE_LD_FLAGS=$(EXE_LD_FLAGS)

export CMAKE_LD_FLAGS_LIST=$(LD_FLAGS)
export CMAKE_SO_LD_FLAGS_LIST=$(SO_LD_FLAGS)
export CMAKE_EXE_LD_FLAGS_LIST=$(EXE_LD_FLAGS)

export CMAKE_LD_LIBS=$(LD_LIBS)

#----------------------------------------------------------------------------------------------

include $(MK)/openmp.defs
