<commit_before># Generic makefile that captures some of the ideas of GNU Automake,
# especially with respect to naming targets.
#
# Author: <NAME>
#
# This makefile requires GNU Make, it has been tested with version
# 3.81.
#
# All variables listed in the section CONFIG VARIABLES are available
# for modification in config.mk, and they may also be overridden on
# the command line. For example, to enable PTHREADS and disable
# automatic dependency tracking, you could do this:
#
#   make CFLAGS_PTHREAD=-pthread CFLAGS_AUTODEP=""
#
# If CFLAGS is specified in the environment or on the command line, it
# will replace the value of CFLAGS_GENERAL. Similarly with LDFLAGS and
# ARFLAGS.
#
# If EXTRA_CFLAGS is specified on the command line, its contents will
# be added to CFLAGS_GENERAL. Similarly with LDFLAGS.
#
# If CC, CXX, LD, or AR is specified in the environment or on the
# command line, its value will be respected.
#
# NOTE: When you change the configuration specified via the
# environment or the command line from one invocation of make to the
# next, you should always start with a 'make clean'. MAKE does this
# automatically when you change config.mk.
#
# A function CC_CXX_AND_LD_ARE is made available to check for a
# specific compiler in config.mk. For example:
#
#   ifneq ($(call CC_CXX_AND_LD_ARE,clang),)
#   # Clang specific stuff
#   endif
#
# Likewise, a variable CC_CXX_AND_LD_ARE_GCC_LIKE is made available to
# check for any GCC like compiler in config.mk (gcc, llvm-gcc,
# clang). For example:
#
#   ifneq ($(CC_CXX_AND_LD_ARE_GCC_LIKE),)
#   # GCC specific stuff
#   endif



# CONFIG VARIABLES

# Relative path to root of source tree. If specified, a corresponding
# include option (-I) is added to the compiler command
# line. Specifying it, also permits installation of headers. Headers
# will be installed under the same relative path as they have with
# respect to the directory specified here. Headers are marked for
# installation by adding them to the INST_HEADERS variable in the
# local Makefile.
SOURCE_ROOT =

CFLAGS_OPTIM          =
CFLAGS_DEBUG          =
CFLAGS_COVER          =
CFLAGS_SHARED         =
CFLAGS_PTHREAD        =
CFLAGS_GENERAL        =
CFLAGS_CXX            =
CFLAGS_OBJC           =
CFLAGS_ARCH           =
CFLAGS_INCLUDE        =
CFLAGS_AUTODEP        =
LDFLAGS_OPTIM         = $(CFLAGS_OPTIM)
LDFLAGS_DEBUG         = $(CFLAGS_DEBUG)
LDFLAGS_COVER         = $(CFLAGS_COVER)
LDFLAGS_SHARED        =
LDFLAGS_PTHREAD       = $(CFLAGS_PTHREAD)
LDFLAGS_GENERAL       =
LDFLAGS_ARCH          = $(CFLAGS_ARCH)
ARFLAGS_GENERAL       = csr

PROJECT_CFLAGS        =
PROJECT_CFLAGS_OPTIM  =
PROJECT_CFLAGS_DEBUG  =
PROJECT_CFLAGS_COVER  =
PROJECT_LDFLAGS       =
PROJECT_LDFLAGS_OPTIM =
PROJECT_LDFLAGS_DEBUG =
PROJECT_LDFLAGS_COVER =

LIB_SUFFIX_STATIC     = .a
LIB_SUFFIX_SHARED     = .so

BASE_DENOM            =
OBJ_DENOM_SHARED      = .pic
OBJ_DENOM_OPTIM       =
OBJ_DENOM_DEBUG       = .dbg
OBJ_DENOM_COVER       = .cov
LIB_DENOM_OPTIM       =
LIB_DENOM_DEBUG       = -dbg
LIB_DENOM_COVER       = -cov
PROG_DENOM_OPTIM      =
PROG_DENOM_DEBUG      = -dbg
PROG_DENOM_COVER      = -cov

# When set to an empty value, 'make install' will also attempt to
# build everything as if by 'make all'. Set this variable to a
# nonempty value if you would rather want 'install' to simply accept
# what is there and attempt an installation from that.
NO_BUILD_ON_INSTALL =

# When set to an empty value, 'make install' will not install the
# static versions of the libraries mentioned in lib_LIBRARIES, and a
# plain 'make' will not even build them. When set to a nonempty value,
# the opposite is true.
ENABLE_INSTALL_STATIC_LIBS =

# When set to an empty value, 'make install' will not install the
# debug versions of the libraries mentioned in lib_LIBRARIES, and a
# plain 'make' will not even build them. When set to a nonempty value,
# the opposite is true.
ENABLE_INSTALL_DEBUG_LIBS =

# When set to an empty value, 'make install' will not install the
# debug versions of the programs mentioned in bin_PROGRAMS, and a
# plain 'make' will not even build them. When set to a nonempty value,
# the opposite is true.
ENABLE_INSTALL_DEBUG_PROGS =

# Installation (GNU style)
prefix          = /usr/local
exec_prefix     = $(prefix)
includedir      = $(prefix)/include
bindir          = $(exec_prefix)/bin
libdir          = $(if $(USE_LIB64),$(exec_prefix)/lib64,$(exec_prefix)/lib)
INSTALL         = install
INSTALL_DIR     = $(INSTALL) -d
INSTALL_DATA    = $(INSTALL) -m 644
INSTALL_LIBRARY = $(INSTALL)
INSTALL_PROGRAM = $(INSTALL)

# Alternative filesystem root for installation
DESTDIR =



# UTILITY FUNCTIONS

EMPTY =
EQUALS = $(if $(word 2,$(sort $(1) $(2))),,$(1))
COND_PREPEND = $(if $(2),$(1)$(2),)
COND_APPEND = $(if $(1),$(1)$(2),)
# ARGS: predicate, list, optional_arg
FIND = $(call FIND_1,$(1),$(strip $(2)),$(3))
FIND_1 = $(if $(2),$(call FIND_2,$(1),$(2),$(3),$(word 1,$(2))),)
FIND_2 = $(if $(call $(1),$(4),$(3)),$(4),$(call FIND_1,$(1),$(wordlist 2,$(words $(2)),$(2)),$(3)))
# ARGS: func, init_accum, list
FOLD_LEFT = $(call FOLD_LEFT_1,$(1),$(2),$(strip $(3)))
FOLD_LEFT_1 = $(if $(3),$(call FOLD_LEFT_1,$(1),$(call $(1),$(2),$(word 1,$(3))),$(wordlist 2,$(words $(3)),$(3))),$(2))
UNION = $(call FOLD_LEFT,UNION_1,$(1),$(2))
UNION_1 = $(if $(call FIND,EQUALS,$(1),$(2)),$(1),$(1) $(2))
PATH_DIFF = $(call PATH_DIFF_1,$(subst /, ,$(abspath $(1))),$(subst /, ,$(abspath $(2))))
PATH_DIFF_1 = $(if $(and $(1),$(2),$(call EQUALS,$(word 1,$(1)),$(word 1,$(2)))),$(call PATH_DIFF_1,$(wordlist 2,$(words $(1)),$(1)),$(wordlist 2,$(words $(2)),$(2))),$(subst $(EMPTY) ,/,$(strip $(patsubst %,..,$(2)) $(1))))
MAKE_ABS_PATH = $(if $(filter /%,$(1)),$(1),$(abspath $(2)/$(1)))
IN_THIS_DIR = $(call EQUALS,$(realpath $(dir $(1))),$(realpath ./))
HAVE_CMD = $(shell which $(1))
MATCH_CMD = $(filter $(1) $(1)-%,$(notdir $(2)))
MAP_CMD = $(if $(call MATCH_CMD,$(1),$(3)),$(if $(findstring /,$(3)),$(dir $(3)),)$(patsubst $(1)%,$(2)%,$(notdir $(3))),)
CAT_OPT_FILE = $(and $(wildcard $(1)),$(shell cat $(1)))



# PLATFORM SPECIFICS

OS        = $(shell uname)
ARCH      = $(shell uname -m)

USE_LIB64 =
ifeq ($(OS),Linux)
IS_64BIT = $(filter x86_64 ia64,$(ARCH))
ifneq ($(IS_64BIT),)
ifeq ($(shell [ -e /etc/redhat-release -o -e /etc/SuSE-release ] && echo yes),yes)
USE_LIB64 = 1
else ifneq ($(shell [ -e /etc/system-release ] && grep Amazon /etc/system-release),)
USE_LIB64 = 1
endif
endif
endif

GET_SPECIAL_SHARED_LIB_OPTS =
ifeq ($(OS),Darwin)
LIB_SUFFIX_SHARED           = .dylib
GET_SPECIAL_SHARED_LIB_OPTS = -install_name @rpath/$(1)
endif



# SETUP A GCC-LIKE DEFAULT COMPILER IF POSSIBLE

# The general idea is as follows: If neither CC nor CXX is specified,
# then check for available C compilers, and set CC and CXX
# accordingly. Otherwise, if CC is specified, but CXX is not, then set
# CXX to the C++ version of CC.

# Note: No correspondence is required between the compilers
# mentioned in GCC_LIKE_COMPILERS, and those mentioned in
# MAP_CC_TO_CXX
ifeq ($(OS),Darwin)
GCC_LIKE_COMPILERS = clang llvm-gcc gcc
else
GCC_LIKE_COMPILERS = gcc llvm-gcc clang
endif
MAP_CC_TO_CXX = $(or $(call MAP_CMD,gcc,g++,$(1)),$(call MAP_CMD,llvm-gcc,llvm-g++,$(1)),$(call MAP_CMD,clang,clang++,$(1)))

GXX_LIKE_COMPILERS = $(strip $(foreach x,$(GCC_LIKE_COMPILERS),$(call MAP_CC_TO_CXX,$(x))))
IS_GCC_LIKE = $(strip $(foreach x,$(GCC_LIKE_COMPILERS),$(call MATCH_CMD,$(x),$(1))))
IS_GXX_LIKE = $(strip $(foreach x,$(GXX_LIKE_COMPILERS),$(call MATCH_CMD,$(x),$(1))))

# C and C++
CC_SPECIFIED        = $(filter-out undefined default,$(origin CC))
CXX_SPECIFIED       = $(filter-out undefined default,$(origin CXX))
CC_OR_CXX_SPECIFIED = $(or $(CC_SPECIFIED),$(CXX_SPECIFIED))
ifeq ($(CC_OR_CXX_SPECIFIED),)
# Neither CC nor CXX is specified
X := $(call FIND,HAVE_CMD,$(GCC_LIKE_COMPILERS))
ifneq ($(X),)
CC := $(X)
X := $(call MAP_CC_TO_CXX,$(CC))
ifneq ($(X),)
CXX := $(X)
endif
endif
else ifeq ($(CXX_SPECIFIED),)
# CXX is not specified, but CC is
X := $(call MAP_CC_TO_CXX,$(CC))
ifneq ($(X),)
CXX := $(X)
endif
endif
CC_AND_CXX_ARE_GCC_LIKE = $(and $(call IS_GCC_LIKE,$(CC)),$(or $(call IS_GCC_LIKE,$(CXX)),$(call IS_GXX_LIKE,$(CXX))))
ifneq ($(CC_AND_CXX_ARE_GCC_LIKE),)
CFLAGS_OPTIM   = -O3
CFLAGS_DEBUG   = -ggdb
CFLAGS_COVER   = --coverage
CFLAGS_SHARED  = -fPIC -DPIC
CFLAGS_GENERAL = -Wall
CFLAGS_AUTODEP = -MMD -MP
endif

# Objective-C and Objective-C++
OCC_SPECIFIED         = $(filter-out undefined default,$(origin OCC))
OCXX_SPECIFIED        = $(filter-out undefined default,$(origin OCXX))
OCC_OR_OCXX_SPECIFIED = $(or $(OCC_SPECIFIED),$(OCXX_SPECIFIED))
ifeq ($(OCC_OR_OCXX_SPECIFIED),)
# Neither OCC nor OCXX is specified
OCC  := $(CC)
OCXX := $(CXX)
else ifeq ($(OCXX_SPECIFIED),)
# OCXX is not specified, but OCC is
X := $(call MAP_CC_TO_CXX,$(OCC))
ifneq ($(X),)
OCXX := $(X)
endif
endif
OCC_AND_OCXX_ARE_GCC_LIKE = $(and $(call IS_GCC_LIKE,$(OCC)),$(or $(call IS_GCC_LIKE,$(OCXX)),$(call IS_GXX_LIKE,$(OCXX))))



# SETUP A GCC-LIKE DEFAULT LINKER IF POSSIBLE

ifneq ($(CC_AND_CXX_ARE_GCC_LIKE),)
ifeq ($(LD_SPECIFIED),)
LD := $(CXX)
endif
endif
LD_IS_GCC_LIKE = $(or $(call IS_GCC_LIKE,$(LD)),$(call IS_GXX_LIKE,$(LD)))
ifneq ($(LD_IS_GCC_LIKE),)
LDFLAGS_SHARED = -shared
endif

# Workaround for CLANG < v3.2 ignoring LIBRARY_PATH
LD_IS_CLANG = $(or $(call MATCH_CMD,clang,$(LD)),$(call MATCH_CMD,clang++,$(LD)))
ifneq ($(LD_IS_CLANG),)
CLANG_VERSION = $(shell $(LD) --version | grep -i 'clang version' | sed 's/.*clang version \([^ ][^ ]*\).*/\1/' | sed 's/[._-]/ /g')
CLANG_MAJOR = $(word 1,$(CLANG_VERSION))
CLANG_MINOR = $(word 2,$(CLANG_VERSION))
ifeq ($(shell echo $$(($(CLANG_MAJOR) < 3 || ($(CLANG_MAJOR) == 3 && $(CLANG_MINOR) < 2)))),1)
LDFLAGS_LIBRARY_PATH = $(foreach x,$(subst :, ,$(LIBRARY_PATH)),-L$(x))
endif
endif



# LOAD PROJECT SPECIFIC CONFIGURATION

CC_CXX_AND_LD_ARE = $(call CC_CXX_AND_LD_ARE_1,$(1),$(call MAP_CC_TO_CXX,$(1)))
CC_CXX_AND_LD_ARE_1 = $(and $(call MATCH_CMD,$(1),$(CC)),$(strip $(foreach x,$(1) $(2),$(call MATCH_CMD,$(x),$(CXX)))),$(strip $(foreach x,$(1) $(2),$(call MATCH_CMD,$(x),$(LD)))))
CC_CXX_AND_LD_ARE_GCC_LIKE = $(strip $(foreach x,$(GCC_LIKE_COMPILERS),$(call CC_CXX_AND_LD_ARE,$(x))))

THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
ROOT = $(patsubst %/,%,$(dir $(THIS_MAKEFILE)))
ABS_ROOT = $(abspath $(ROOT))
CONFIG_MK = $(ROOT)/config.mk
-include $(CONFIG_MK)



# SETUP BUILD COMMANDS

CFLAGS_SPECIFIED  = $(filter-out undefined default,$(origin CFLAGS))
LDFLAGS_SPECIFIED = $(filter-out undefined default,$(origin LDFLAGS))
ARFLAGS_SPECIFIED = $(filter-out undefined default,$(origin ARFLAGS))
ifneq ($(CFLAGS_SPECIFIED),)
CFLAGS_GENERAL = $(CFLAGS)
endif
ifneq ($(LDFLAGS_SPECIFIED),)
PROJECT_GENERAL = $(LDFLAGS)
endif
ifneq ($(ARFLAGS_SPECIFIED),)
ARFLAGS_GENERAL = $(ARFLAGS)
endif
EXTRA_CFLAGS  =
EXTRA_LDFLAGS =
CFLAGS_GENERAL  += $(EXTRA_CFLAGS)
LDFLAGS_GENERAL += $(EXTRA_LDFLAGS)

CC_STATIC_OPTIM   = $(CC) $(CFLAGS_OPTIM) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)
CC_SHARED_OPTIM   = $(CC) $(CFLAGS_OPTIM) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)
CC_STATIC_DEBUG   = $(CC) $(CFLAGS_DEBUG) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)
CC_SHARED_DEBUG   = $(CC) $(CFLAGS_DEBUG) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)
CC_STATIC_COVER   = $(CC) $(CFLAGS_COVER) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)
CC_SHARED_COVER   = $(CC) $(CFLAGS_COVER) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)

CXX_STATIC_OPTIM  = $(CXX) $(CFLAGS_OPTIM) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)
CXX_SHARED_OPTIM  = $(CXX) $(CFLAGS_OPTIM) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)
CXX_STATIC_DEBUG  = $(CXX) $(CFLAGS_DEBUG) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)
CXX_SHARED_DEBUG  = $(CXX) $(CFLAGS_DEBUG) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)
CXX_STATIC_COVER  = $(CXX) $(CFLAGS_COVER) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)
CXX_SHARED_COVER  = $(CXX) $(CFLAGS_COVER) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)

OCC_STATIC_OPTIM  = $(OCC) $(CFLAGS_OPTIM) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)
OCC_SHARED_OPTIM  = $(OCC) $(CFLAGS_OPTIM) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)
OCC_STATIC_DEBUG  = $(OCC) $(CFLAGS_DEBUG) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)
OCC_SHARED_DEBUG  = $(OCC) $(CFLAGS_DEBUG) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)
OCC_STATIC_COVER  = $(OCC) $(CFLAGS_COVER) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)
OCC_SHARED_COVER  = $(OCC) $(CFLAGS_COVER) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)

OCXX_STATIC_OPTIM = $(OCXX) $(CFLAGS_OPTIM) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)
OCXX_SHARED_OPTIM = $(OCXX) $(CFLAGS_OPTIM) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)
OCXX_STATIC_DEBUG = $(OCXX) $(CFLAGS_DEBUG) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)
OCXX_SHARED_DEBUG = $(OCXX) $(CFLAGS_DEBUG) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)
OCXX_STATIC_COVER = $(OCXX) $(CFLAGS_COVER) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)
OCXX_SHARED_COVER = $(OCXX) $(CFLAGS_COVER) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)

LD_LIB_OPTIM      = $(LD) $(LDFLAGS_SHARED) $(LDFLAGS_OPTIM) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)
LD_LIB_DEBUG      = $(LD) $(LDFLAGS_SHARED) $(LDFLAGS_DEBUG) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)
LD_LIB_COVER      = $(LD) $(LDFLAGS_SHARED) $(LDFLAGS_COVER) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)
LD_PROG_OPTIM     = $(LD) $(LDFLAGS_OPTIM) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)
LD_PROG_DEBUG     = $(LD) $(LDFLAGS_DEBUG) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)
LD_PROG_COVER     = $(LD) $(LDFLAGS_COVER) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)



BASE_DENOM_2            = $(if $(BASE_DENOM),-$(BASE_DENOM),)
SUFFIX_OBJ_STATIC_OPTIM = $(BASE_DENOM_2)$(OBJ_DENOM_OPTIM).o
SUFFIX_OBJ_SHARED_OPTIM = $(BASE_DENOM_2)$(OBJ_DENOM_OPTIM)$(OBJ_DENOM_SHARED).o
SUFFIX_OBJ_STATIC_DEBUG = $(BASE_DENOM_2)$(OBJ_DENOM_DEBUG).o
SUFFIX_OBJ_SHARED_DEBUG = $(BASE_DENOM_2)$(OBJ_DENOM_DEBUG)$(OBJ_DENOM_SHARED).o
SUFFIX_OBJ_STATIC_COVER = $(BASE_DENOM_2)$(OBJ_DENOM_COVER).o
SUFFIX_OBJ_SHARED_COVER = $(BASE_DENOM_2)$(OBJ_DENOM_COVER)$(OBJ_DENOM_SHARED).o
SUFFIX_LIB_STATIC_OPTIM = $(BASE_DENOM_2)$(LIB_DENOM_OPTIM)$(LIB_SUFFIX_STATIC)
SUFFIX_LIB_SHARED_OPTIM = $(BASE_DENOM_2)$(LIB_DENOM_OPTIM)$(LIB_SUFFIX_SHARED)
SUFFIX_LIB_STATIC_DEBUG = $(BASE_DENOM_2)$(LIB_DENOM_DEBUG)$(LIB_SUFFIX_STATIC)
SUFFIX_LIB_SHARED_DEBUG = $(BASE_DENOM_2)$(LIB_DENOM_DEBUG)$(LIB_SUFFIX_SHARED)
SUFFIX_LIB_STATIC_COVER = $(BASE_DENOM_2)$(LIB_DENOM_COVER)$(LIB_SUFFIX_STATIC)
SUFFIX_LIB_SHARED_COVER = $(BASE_DENOM_2)$(LIB_DENOM_COVER)$(LIB_SUFFIX_SHARED)
SUFFIX_PROG_OPTIM       = $(BASE_DENOM_2)$(PROG_DENOM_OPTIM)
SUFFIX_PROG_DEBUG       = $(BASE_DENOM_2)$(PROG_DENOM_DEBUG)
SUFFIX_PROG_COVER       = $(BASE_DENOM_2)$(PROG_DENOM_COVER)

FOLD_TARGET = $(subst /,_,$(subst .,_,$(subst -,_,$(1))))
GET_LIBRARY_NAME = $(patsubst %.a,%,$(1))
GET_OBJECTS_FROM_SOURCES = $(patsubst %.c,%$(2),$(patsubst %.cpp,%$(2),$(patsubst %.m,%$(2),$(patsubst %.mm,%$(2),$(1)))))
GET_OBJECTS_FOR_TARGET = $(call GET_OBJECTS_FROM_SOURCES,$($(call FOLD_TARGET,$(1))_SOURCES),$(2))
GET_FLAGS = $($(1)) $($(1)$(2))
GET_CFLAGS_FOR_TARGET = $(foreach x,PROJECT DIR $(foreach y,$(GMK_$(call FOLD_TARGET,$(1))_TARGETS) $(1),$(call FOLD_TARGET,$(y))),$(call GET_FLAGS,$(x)_CFLAGS,$(2)))
GET_LDFLAGS_FOR_TARGET = $(foreach x,PROJECT DIR $(call FOLD_TARGET,$(1)),$(call GET_FLAGS,$(x)_LDFLAGS,$(2)))
GET_DEPS_FOR_TARGET = $($(call FOLD_TARGET,$(1))_DEPS)

INC_FLAGS         = $(CFLAGS_INCLUDE)
INC_FLAGS_ABS     = $(CFLAGS_INCLUDE)
ifneq ($(SOURCE_ROOT),)
INC_FLAGS        += -I$(ROOT)/$(SOURCE_ROOT)
INC_FLAGS_ABS    += -I$(ABS_ROOT)/$(SOURCE_ROOT)
endif

INST_LIBRARIES = $(foreach x,lib $(EXTRA_INSTALL_PREFIXES),$($(x)_LIBRARIES))
INST_PROGRAMS  = $(foreach x,bin $(EXTRA_INSTALL_PREFIXES),$($(x)_PROGRAMS))

LIBRARIES = $(INST_LIBRARIES) $(NOINST_LIBRARIES)
PROGRAMS  = $(INST_PROGRAMS) $(NOINST_PROGRAMS) $(TEST_PROGRAMS)

OBJECTS_STATIC_OPTIM = $(foreach x,$(LIBRARIES) $(PROGRAMS),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_STATIC_OPTIM)))
OBJECTS_SHARED_OPTIM = $(foreach x,$(LIBRARIES),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_SHARED_OPTIM)))
OBJECTS_STATIC_DEBUG = $(foreach x,$(LIBRARIES) $(PROGRAMS),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_STATIC_DEBUG)))
OBJECTS_SHARED_DEBUG = $(foreach x,$(LIBRARIES),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_SHARED_DEBUG)))
OBJECTS_STATIC_COVER = $(foreach x,$(LIBRARIES) $(PROGRAMS),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_STATIC_COVER)))
OBJECTS_SHARED_COVER = $(foreach x,$(LIBRARIES),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_SHARED_COVER)))
OBJECTS = $(sort $(OBJECTS_STATIC_OPTIM) $(OBJECTS_SHARED_OPTIM) $(OBJECTS_STATIC_DEBUG) $(OBJECTS_SHARED_DEBUG) $(OBJECTS_STATIC_COVER) $(OBJECTS_SHARED_COVER))

TARGETS_LIB_STATIC_OPTIM  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_OPTIM))
TARGETS_LIB_SHARED_OPTIM  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_SHARED_OPTIM))
TARGETS_LIB_STATIC_DEBUG  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_DEBUG))
TARGETS_LIB_SHARED_DEBUG  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_SHARED_DEBUG))
TARGETS_LIB_STATIC_COVER  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_COVER))
TARGETS_LIB_SHARED_COVER  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_SHARED_COVER))
TARGETS_NOINST_LIB_OPTIM  = $(foreach x,$(NOINST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_OPTIM))
TARGETS_NOINST_LIB_DEBUG  = $(foreach x,$(NOINST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_DEBUG))
TARGETS_NOINST_LIB_COVER  = $(foreach x,$(NOINST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_COVER))
TARGETS_PROG_OPTIM        = $(foreach x,$(INST_PROGRAMS),$(x)$(SUFFIX_PROG_OPTIM))
TARGETS_PROG_DEBUG        = $(foreach x,$(INST_PROGRAMS),$(x)$(SUFFIX_PROG_DEBUG))
TARGETS_PROG_COVER        = $(foreach x,$(INST_PROGRAMS),$(x)$(SUFFIX_PROG_COVER))
TARGETS_NOINST_PROG_OPTIM = $(foreach x,$(NOINST_PROGRAMS),$(x)$(SUFFIX_PROG_OPTIM))
TARGETS_NOINST_PROG_DEBUG = $(foreach x,$(NOINST_PROGRAMS),$(x)$(SUFFIX_PROG_DEBUG))
TARGETS_NOINST_PROG_COVER = $(foreach x,$(NOINST_PROGRAMS),$(x)$(SUFFIX_PROG_COVER))
TARGETS_TEST_PROG_OPTIM   = $(foreach x,$(TEST_PROGRAMS),$(x)$(SUFFIX_PROG_OPTIM))
TARGETS_TEST_PROG_DEBUG   = $(foreach x,$(TEST_PROGRAMS),$(x)$(SUFFIX_PROG_DEBUG))
TARGETS_TEST_PROG_COVER   = $(foreach x,$(TEST_PROGRAMS),$(x)$(SUFFIX_PROG_COVER))

TARGETS_DEFAULT     =
ifneq ($(ENABLE_INSTALL_STATIC_LIBS),)
TARGETS_DEFAULT    += $(TARGETS_LIB_STATIC_OPTIM)
endif
TARGETS_DEFAULT    += $(TARGETS_LIB_SHARED_OPTIM)
ifneq ($(or $(ENABLE_INSTALL_DEBUG_LIBS),$(ENABLE_INSTALL_DEBUG_PROGS)),)
TARGETS_DEFAULT    += $(TARGETS_LIB_SHARED_DEBUG)
endif
TARGETS_DEFAULT    += $(TARGETS_NOINST_LIB_OPTIM)
ifneq ($(ENABLE_INSTALL_DEBUG_PROGS),)
TARGETS_DEFAULT    += $(TARGETS_NOINST_LIB_DEBUG)
endif
TARGETS_DEFAULT    += $(TARGETS_PROG_OPTIM)
ifneq ($(ENABLE_INSTALL_DEBUG_PROGS),)
TARGETS_DEFAULT    += $(TARGETS_PROG_DEBUG)
endif
TARGETS_DEFAULT    += $(TARGETS_NOINST_PROG_OPTIM)

TARGETS_MINIMAL     = $(TARGETS_LIB_SHARED_OPTIM) $(TARGETS_NOINST_LIB_OPTIM) $(TARGETS_PROG_OPTIM) $(TARGETS_NOINST_PROG_OPTIM)
TARGETS_NODEBUG     = $(TARGETS_LIB_STATIC_OPTIM) $(TARGETS_LIB_SHARED_OPTIM) $(TARGETS_NOINST_LIB_OPTIM) $(TARGETS_PROG_OPTIM) $(TARGETS_NOINST_PROG_OPTIM)
TARGETS_DEBUG       = $(TARGETS_LIB_SHARED_DEBUG) $(TARGETS_NOINST_LIB_DEBUG) $(TARGETS_PROG_DEBUG) $(TARGETS_NOINST_PROG_DEBUG)
TARGETS_COVER       = $(TARGETS_LIB_SHARED_COVER) $(TARGETS_NOINST_LIB_COVER) $(TARGETS_PROG_COVER) $(TARGETS_NOINST_PROG_COVER)
TARGETS_EVERYTHING  = $(TARGETS_LIB_STATIC_OPTIM) $(TARGETS_LIB_SHARED_OPTIM) $(TARGETS_LIB_SHARED_DEBUG) $(TARGETS_NOINST_LIB_OPTIM) $(TARGETS_NOINST_LIB_DEBUG)
TARGETS_EVERYTHING += $(TARGETS_PROG_OPTIM) $(TARGETS_PROG_DEBUG) $(TARGETS_NOINST_PROG_OPTIM) $(TARGETS_NOINST_PROG_DEBUG) $(TARGETS_TEST_PROG_OPTIM) $(TARGETS_TEST_PROG_DEBUG)
TARGETS_TEST        = $(TARGETS_LIB_SHARED_OPTIM) $(TARGETS_NOINST_LIB_OPTIM) $(TARGETS_TEST_PROG_OPTIM)
TARGETS_TEST_DEBUG  = $(TARGETS_LIB_SHARED_DEBUG) $(TARGETS_NOINST_LIB_DEBUG) $(TARGETS_TEST_PROG_DEBUG)
TARGETS_TEST_COVER  = $(TARGETS_LIB_SHARED_COVER) $(TARGETS_NOINST_LIB_COVER) $(TARGETS_TEST_PROG_COVER)

TARGETS_LIB_STATIC  = $(TARGETS_LIB_STATIC_OPTIM) $(TARGETS_LIB_STATIC_DEBUG) $(TARGETS_LIB_STATIC_COVER)
TARGETS_LIB_SHARED  = $(TARGETS_LIB_SHARED_OPTIM) $(TARGETS_LIB_SHARED_DEBUG) $(TARGETS_LIB_SHARED_COVER)
TARGETS_NOINST_LIB  = $(TARGETS_NOINST_LIB_OPTIM) $(TARGETS_NOINST_LIB_DEBUG) $(TARGETS_NOINST_LIB_COVER)
TARGETS_PROG        = $(TARGETS_PROG_OPTIM) $(TARGETS_PROG_DEBUG) $(TARGETS_PROG_COVER)
TARGETS_NOINST_PROG = $(TARGETS_NOINST_PROG_OPTIM) $(TARGETS_NOINST_PROG_DEBUG) $(TARGETS_NOINST_PROG_COVER)
TARGETS_TEST_PROG   = $(TARGETS_TEST_PROG_OPTIM) $(TARGETS_TEST_PROG_DEBUG) $(TARGETS_TEST_PROG_COVER)

TARGETS  = $(TARGETS_LIB_STATIC) $(TARGETS_LIB_SHARED) $(TARGETS_NOINST_LIB)
TARGETS += $(foreach x,$(TARGETS_PROG),$(x) $(x)-noinst) $(TARGETS_NOINST_PROG) $(TARGETS_TEST_PROG)

RECURSIVE_MODES = default minimal nodebug debug cover everything clean install uninstall test-norun test-debug-norun test test-debug test-cover memtest memtest-debug

.PHONY: all
all: default

default/local:    $(TARGETS_DEFAULT) update-libdeps-files
minimal/local:    $(TARGETS_MINIMAL) update-libdeps-files
nodebug/local:    $(TARGETS_NODEBUG) update-libdeps-files
debug/local:      $(TARGETS_DEBUG) update-libdeps-files
cover/local:      $(TARGETS_COVER) update-libdeps-files
everything/local: $(TARGETS_EVERYTHING) update-libdeps-files
test-norun:       $(TARGETS_TEST) update-libdeps-files
test-debug-norun: $(TARGETS_TEST_DEBUG) update-libdeps-files


# Update everything if any makefile has changed
DEP_MAKEFILES = Makefile $(THIS_MAKEFILE)
ifneq ($(wildcard $(CONFIG_MK)),)
DEP_MAKEFILES += $(CONFIG_MK)
endif
$(GENERATED_SOURCES) $(OBJECTS) $(TARGETS): $(DEP_MAKEFILES)
$(OBJECTS): $(GENERATED_SOURCES)

# Disable all suffix rules and some interfering implicit pattern rules
.SUFFIXES:
%: %.o
%: %.c
%: %.cpp



# SUBDIRECTORIES

define SUBDIR_DEP_RULE
ifeq ($(3),.)
subdir/$(1)/$(2): $(2)/local
else
subdir/$(1)/$(2): subdir/$(3)/$(2)
endif
endef

define SUBDIR_MODE_RULES
.PHONY: subdir/$(1)/$(2)
$$(foreach x,$$($$(call FOLD_TARGET,$(1))_DEPS),$$(eval $$(call SUBDIR_DEP_RULE,$(1),$(2),$$(x))))
ifeq ($(2),default)
subdir/$(1)/$(2):
	@$$(MAKE) -C $(1)
else
subdir/$(1)/$(2):
	@$$(MAKE) -C $(1) $(2)
endif
endef

SUBDIR_RULES = $(foreach x,$(RECURSIVE_MODES),$(eval $(call SUBDIR_MODE_RULES,$(1),$(x))))

$(foreach x,$(SUBDIRS) $(PASSIVE_SUBDIRS),$(eval $(call SUBDIR_RULES,$(x))))

define RECURSIVE_MODE_RULES
.PHONY: $(1) $(1)/local $(1)/after
$(1): $(1)/local $(patsubst %,subdir/%/$(1),$(SUBDIRS)) $(1)/after<commit_msg>generic.mk updated to same version as is used in core library<commit_after># Generic makefile that captures some of the ideas of GNU Automake,
# especially with respect to naming targets.
#
# Author: <NAME>
#
# This makefile requires GNU Make, it has been tested with version
# 3.81.
#
# All variables listed in the section CONFIG VARIABLES are available
# for modification in config.mk, and they may also be overridden on
# the command line. For example, to enable PTHREADS and disable
# automatic dependency tracking, you could do this:
#
#   make CFLAGS_PTHREAD=-pthread CFLAGS_AUTODEP=""
#
# If CFLAGS is specified in the environment or on the command line, it
# will replace the value of CFLAGS_GENERAL. Similarly with LDFLAGS and
# ARFLAGS.
#
# If EXTRA_CFLAGS is specified on the command line, its contents will
# be added to CFLAGS_GENERAL. Similarly with LDFLAGS.
#
# If CC, CXX, LD, or AR is specified in the environment or on the
# command line, its value will be respected.
#
# NOTE: When you change the configuration specified via the
# environment or the command line from one invocation of make to the
# next, you should always start with a 'make clean'. MAKE does this
# automatically when you change config.mk.
#
# A function CC_CXX_AND_LD_ARE is made available to check for a
# specific compiler in config.mk. For example:
#
#   ifneq ($(call CC_CXX_AND_LD_ARE,clang),)
#   # Clang specific stuff
#   endif
#
# Likewise, a variable CC_CXX_AND_LD_ARE_GCC_LIKE is made available to
# check for any GCC like compiler in config.mk (gcc, llvm-gcc,
# clang). For example:
#
#   ifneq ($(CC_CXX_AND_LD_ARE_GCC_LIKE),)
#   # GCC specific stuff
#   endif



# CONFIG VARIABLES

# Relative path to root of source tree. If specified, a corresponding
# include option (-I) is added to the compiler command
# line. Specifying it, also permits installation of headers. Headers
# will be installed under the same relative path as they have with
# respect to the directory specified here. Headers are marked for
# installation by adding them to the INST_HEADERS variable in the
# local Makefile.
SOURCE_ROOT =

CFLAGS_OPTIM          =
CFLAGS_DEBUG          =
CFLAGS_COVER          =
CFLAGS_SHARED         =
CFLAGS_PTHREAD        =
CFLAGS_GENERAL        =
CFLAGS_CXX            =
CFLAGS_OBJC           =
CFLAGS_ARCH           =
CFLAGS_INCLUDE        =
CFLAGS_AUTODEP        =
LDFLAGS_OPTIM         = $(CFLAGS_OPTIM)
LDFLAGS_DEBUG         = $(CFLAGS_DEBUG)
LDFLAGS_COVER         = $(CFLAGS_COVER)
LDFLAGS_SHARED        =
LDFLAGS_PTHREAD       = $(CFLAGS_PTHREAD)
LDFLAGS_GENERAL       =
LDFLAGS_ARCH          = $(CFLAGS_ARCH)
ARFLAGS_GENERAL       = csr

PROJECT_CFLAGS        =
PROJECT_CFLAGS_OPTIM  =
PROJECT_CFLAGS_DEBUG  =
PROJECT_CFLAGS_COVER  =
PROJECT_LDFLAGS       =
PROJECT_LDFLAGS_OPTIM =
PROJECT_LDFLAGS_DEBUG =
PROJECT_LDFLAGS_COVER =

LIB_SUFFIX_STATIC     = .a
LIB_SUFFIX_SHARED     = .so

BASE_DENOM            =
OBJ_DENOM_SHARED      = .pic
OBJ_DENOM_OPTIM       =
OBJ_DENOM_DEBUG       = .dbg
OBJ_DENOM_COVER       = .cov
LIB_DENOM_OPTIM       =
LIB_DENOM_DEBUG       = -dbg
LIB_DENOM_COVER       = -cov
PROG_DENOM_OPTIM      =
PROG_DENOM_DEBUG      = -dbg
PROG_DENOM_COVER      = -cov

# When set to an empty value, 'make install' will also attempt to
# build everything as if by 'make all'. Set this variable to a
# nonempty value if you would rather want 'install' to simply accept
# what is there and attempt an installation from that.
NO_BUILD_ON_INSTALL =

# When set to an empty value, 'make install' will not install the
# static versions of the libraries mentioned in lib_LIBRARIES, and a
# plain 'make' will not even build them. When set to a nonempty value,
# the opposite is true.
ENABLE_INSTALL_STATIC_LIBS =

# When set to an empty value, 'make install' will not install the
# debug versions of the libraries mentioned in lib_LIBRARIES, and a
# plain 'make' will not even build them. When set to a nonempty value,
# the opposite is true.
ENABLE_INSTALL_DEBUG_LIBS =

# When set to an empty value, 'make install' will not install the
# debug versions of the programs mentioned in bin_PROGRAMS, and a
# plain 'make' will not even build them. When set to a nonempty value,
# the opposite is true.
ENABLE_INSTALL_DEBUG_PROGS =

# Installation (GNU style)
prefix          = /usr/local
exec_prefix     = $(prefix)
includedir      = $(prefix)/include
bindir          = $(exec_prefix)/bin
libdir          = $(if $(USE_LIB64),$(exec_prefix)/lib64,$(exec_prefix)/lib)
INSTALL         = install
INSTALL_DIR     = $(INSTALL) -d
INSTALL_DATA    = $(INSTALL) -m 644
INSTALL_LIBRARY = $(INSTALL)
INSTALL_PROGRAM = $(INSTALL)

# Alternative filesystem root for installation
DESTDIR =



# UTILITY FUNCTIONS

EMPTY =
EQUALS = $(if $(word 2,$(sort $(1) $(2))),,$(1))
COND_PREPEND = $(if $(2),$(1)$(2),)
COND_APPEND = $(if $(1),$(1)$(2),)
# ARGS: predicate, list, optional_arg
FIND = $(call FIND_1,$(1),$(strip $(2)),$(3))
FIND_1 = $(if $(2),$(call FIND_2,$(1),$(2),$(3),$(word 1,$(2))),)
FIND_2 = $(if $(call $(1),$(4),$(3)),$(4),$(call FIND_1,$(1),$(wordlist 2,$(words $(2)),$(2)),$(3)))
# ARGS: func, init_accum, list
FOLD_LEFT = $(call FOLD_LEFT_1,$(1),$(2),$(strip $(3)))
FOLD_LEFT_1 = $(if $(3),$(call FOLD_LEFT_1,$(1),$(call $(1),$(2),$(word 1,$(3))),$(wordlist 2,$(words $(3)),$(3))),$(2))
UNION = $(call FOLD_LEFT,UNION_1,$(1),$(2))
UNION_1 = $(if $(call FIND,EQUALS,$(1),$(2)),$(1),$(1) $(2))
PATH_DIFF = $(call PATH_DIFF_1,$(subst /, ,$(abspath $(1))),$(subst /, ,$(abspath $(2))))
PATH_DIFF_1 = $(if $(and $(1),$(2),$(call EQUALS,$(word 1,$(1)),$(word 1,$(2)))),$(call PATH_DIFF_1,$(wordlist 2,$(words $(1)),$(1)),$(wordlist 2,$(words $(2)),$(2))),$(subst $(EMPTY) ,/,$(strip $(patsubst %,..,$(2)) $(1))))
MAKE_ABS_PATH = $(if $(filter /%,$(1)),$(1),$(abspath $(2)/$(1)))
IN_THIS_DIR = $(call EQUALS,$(realpath $(dir $(1))),$(realpath ./))
HAVE_CMD = $(shell which $(1))
MATCH_CMD = $(filter $(1) $(1)-%,$(notdir $(2)))
MAP_CMD = $(if $(call MATCH_CMD,$(1),$(3)),$(if $(findstring /,$(3)),$(dir $(3)),)$(patsubst $(1)%,$(2)%,$(notdir $(3))),)
CAT_OPT_FILE = $(and $(wildcard $(1)),$(shell cat $(1)))



# PLATFORM SPECIFICS

OS        = $(shell uname)
ARCH      = $(shell uname -m)

USE_LIB64 =
ifeq ($(OS),Linux)
IS_64BIT = $(filter x86_64 ia64,$(ARCH))
ifneq ($(IS_64BIT),)
ifeq ($(shell [ -e /etc/redhat-release -o -e /etc/SuSE-release ] && echo yes),yes)
USE_LIB64 = 1
else ifneq ($(shell [ -e /etc/system-release ] && grep Amazon /etc/system-release),)
USE_LIB64 = 1
endif
endif
endif

GET_SPECIAL_SHARED_LIB_OPTS =
ifeq ($(OS),Darwin)
LIB_SUFFIX_SHARED           = .dylib
GET_SPECIAL_SHARED_LIB_OPTS = -install_name @rpath/$(1)
endif



# SETUP A GCC-LIKE DEFAULT COMPILER IF POSSIBLE

# The general idea is as follows: If neither CC nor CXX is specified,
# then check for available C compilers, and set CC and CXX
# accordingly. Otherwise, if CC is specified, but CXX is not, then set
# CXX to the C++ version of CC.

# Note: No correspondence is required between the compilers
# mentioned in GCC_LIKE_COMPILERS, and those mentioned in
# MAP_CC_TO_CXX
ifeq ($(OS),Darwin)
GCC_LIKE_COMPILERS = clang llvm-gcc gcc
else
GCC_LIKE_COMPILERS = gcc llvm-gcc clang
endif
MAP_CC_TO_CXX = $(or $(call MAP_CMD,gcc,g++,$(1)),$(call MAP_CMD,llvm-gcc,llvm-g++,$(1)),$(call MAP_CMD,clang,clang++,$(1)))

GXX_LIKE_COMPILERS = $(strip $(foreach x,$(GCC_LIKE_COMPILERS),$(call MAP_CC_TO_CXX,$(x))))
IS_GCC_LIKE = $(strip $(foreach x,$(GCC_LIKE_COMPILERS),$(call MATCH_CMD,$(x),$(1))))
IS_GXX_LIKE = $(strip $(foreach x,$(GXX_LIKE_COMPILERS),$(call MATCH_CMD,$(x),$(1))))

# C and C++
CC_SPECIFIED        = $(filter-out undefined default,$(origin CC))
CXX_SPECIFIED       = $(filter-out undefined default,$(origin CXX))
CC_OR_CXX_SPECIFIED = $(or $(CC_SPECIFIED),$(CXX_SPECIFIED))
ifeq ($(CC_OR_CXX_SPECIFIED),)
# Neither CC nor CXX is specified
X := $(call FIND,HAVE_CMD,$(GCC_LIKE_COMPILERS))
ifneq ($(X),)
CC := $(X)
X := $(call MAP_CC_TO_CXX,$(CC))
ifneq ($(X),)
CXX := $(X)
endif
endif
else ifeq ($(CXX_SPECIFIED),)
# CXX is not specified, but CC is
X := $(call MAP_CC_TO_CXX,$(CC))
ifneq ($(X),)
CXX := $(X)
endif
endif
CC_AND_CXX_ARE_GCC_LIKE = $(and $(call IS_GCC_LIKE,$(CC)),$(or $(call IS_GCC_LIKE,$(CXX)),$(call IS_GXX_LIKE,$(CXX))))
ifneq ($(CC_AND_CXX_ARE_GCC_LIKE),)
CFLAGS_OPTIM   = -O3
CFLAGS_DEBUG   = -ggdb
CFLAGS_COVER   = --coverage
CFLAGS_SHARED  = -fPIC -DPIC
CFLAGS_GENERAL = -Wall
CFLAGS_AUTODEP = -MMD -MP
endif

# Objective-C and Objective-C++
OCC_SPECIFIED         = $(filter-out undefined default,$(origin OCC))
OCXX_SPECIFIED        = $(filter-out undefined default,$(origin OCXX))
OCC_OR_OCXX_SPECIFIED = $(or $(OCC_SPECIFIED),$(OCXX_SPECIFIED))
ifeq ($(OCC_OR_OCXX_SPECIFIED),)
# Neither OCC nor OCXX is specified
OCC  := $(CC)
OCXX := $(CXX)
else ifeq ($(OCXX_SPECIFIED),)
# OCXX is not specified, but OCC is
X := $(call MAP_CC_TO_CXX,$(OCC))
ifneq ($(X),)
OCXX := $(X)
endif
endif
OCC_AND_OCXX_ARE_GCC_LIKE = $(and $(call IS_GCC_LIKE,$(OCC)),$(or $(call IS_GCC_LIKE,$(OCXX)),$(call IS_GXX_LIKE,$(OCXX))))



# SETUP A GCC-LIKE DEFAULT LINKER IF POSSIBLE

ifneq ($(CC_AND_CXX_ARE_GCC_LIKE),)
ifeq ($(LD_SPECIFIED),)
LD := $(CXX)
endif
endif
LD_IS_GCC_LIKE = $(or $(call IS_GCC_LIKE,$(LD)),$(call IS_GXX_LIKE,$(LD)))
ifneq ($(LD_IS_GCC_LIKE),)
LDFLAGS_SHARED = -shared
endif

# Workaround for CLANG < v3.2 ignoring LIBRARY_PATH
LD_IS_CLANG = $(or $(call MATCH_CMD,clang,$(LD)),$(call MATCH_CMD,clang++,$(LD)))
ifneq ($(LD_IS_CLANG),)
CLANG_VERSION = $(shell $(LD) --version | grep -i 'clang version' | sed 's/.*clang version \([^ ][^ ]*\).*/\1/' | sed 's/[._-]/ /g')
CLANG_MAJOR = $(word 1,$(CLANG_VERSION))
CLANG_MINOR = $(word 2,$(CLANG_VERSION))
ifeq ($(shell echo $$(($(CLANG_MAJOR) < 3 || ($(CLANG_MAJOR) == 3 && $(CLANG_MINOR) < 2)))),1)
LDFLAGS_LIBRARY_PATH = $(foreach x,$(subst :, ,$(LIBRARY_PATH)),-L$(x))
endif
endif



# LOAD PROJECT SPECIFIC CONFIGURATION

CC_CXX_AND_LD_ARE = $(call CC_CXX_AND_LD_ARE_1,$(1),$(call MAP_CC_TO_CXX,$(1)))
CC_CXX_AND_LD_ARE_1 = $(and $(call MATCH_CMD,$(1),$(CC)),$(strip $(foreach x,$(1) $(2),$(call MATCH_CMD,$(x),$(CXX)))),$(strip $(foreach x,$(1) $(2),$(call MATCH_CMD,$(x),$(LD)))))
CC_CXX_AND_LD_ARE_GCC_LIKE = $(strip $(foreach x,$(GCC_LIKE_COMPILERS),$(call CC_CXX_AND_LD_ARE,$(x))))

THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
ROOT = $(patsubst %/,%,$(dir $(THIS_MAKEFILE)))
ABS_ROOT = $(abspath $(ROOT))
CONFIG_MK = $(ROOT)/config.mk
-include $(CONFIG_MK)



# SETUP BUILD COMMANDS

CFLAGS_SPECIFIED  = $(filter-out undefined default,$(origin CFLAGS))
LDFLAGS_SPECIFIED = $(filter-out undefined default,$(origin LDFLAGS))
ARFLAGS_SPECIFIED = $(filter-out undefined default,$(origin ARFLAGS))
ifneq ($(CFLAGS_SPECIFIED),)
CFLAGS_GENERAL = $(CFLAGS)
endif
ifneq ($(LDFLAGS_SPECIFIED),)
PROJECT_GENERAL = $(LDFLAGS)
endif
ifneq ($(ARFLAGS_SPECIFIED),)
ARFLAGS_GENERAL = $(ARFLAGS)
endif
EXTRA_CFLAGS  =
EXTRA_LDFLAGS =
CFLAGS_GENERAL  += $(EXTRA_CFLAGS)
LDFLAGS_GENERAL += $(EXTRA_LDFLAGS)

CC_STATIC_OPTIM   = $(CC) $(CFLAGS_OPTIM) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)
CC_SHARED_OPTIM   = $(CC) $(CFLAGS_OPTIM) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)
CC_STATIC_DEBUG   = $(CC) $(CFLAGS_DEBUG) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)
CC_SHARED_DEBUG   = $(CC) $(CFLAGS_DEBUG) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)
CC_STATIC_COVER   = $(CC) $(CFLAGS_COVER) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)
CC_SHARED_COVER   = $(CC) $(CFLAGS_COVER) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL)

CXX_STATIC_OPTIM  = $(CXX) $(CFLAGS_OPTIM) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)
CXX_SHARED_OPTIM  = $(CXX) $(CFLAGS_OPTIM) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)
CXX_STATIC_DEBUG  = $(CXX) $(CFLAGS_DEBUG) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)
CXX_SHARED_DEBUG  = $(CXX) $(CFLAGS_DEBUG) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)
CXX_STATIC_COVER  = $(CXX) $(CFLAGS_COVER) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)
CXX_SHARED_COVER  = $(CXX) $(CFLAGS_COVER) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_CXX)

OCC_STATIC_OPTIM  = $(OCC) $(CFLAGS_OPTIM) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)
OCC_SHARED_OPTIM  = $(OCC) $(CFLAGS_OPTIM) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)
OCC_STATIC_DEBUG  = $(OCC) $(CFLAGS_DEBUG) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)
OCC_SHARED_DEBUG  = $(OCC) $(CFLAGS_DEBUG) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)
OCC_STATIC_COVER  = $(OCC) $(CFLAGS_COVER) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)
OCC_SHARED_COVER  = $(OCC) $(CFLAGS_COVER) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC)

OCXX_STATIC_OPTIM = $(OCXX) $(CFLAGS_OPTIM) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)
OCXX_SHARED_OPTIM = $(OCXX) $(CFLAGS_OPTIM) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)
OCXX_STATIC_DEBUG = $(OCXX) $(CFLAGS_DEBUG) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)
OCXX_SHARED_DEBUG = $(OCXX) $(CFLAGS_DEBUG) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)
OCXX_STATIC_COVER = $(OCXX) $(CFLAGS_COVER) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)
OCXX_SHARED_COVER = $(OCXX) $(CFLAGS_COVER) $(CFLAGS_SHARED) $(CFLAGS_PTHREAD) $(CFLAGS_GENERAL) $(CFLAGS_OBJC) $(CFLAGS_CXX)

LD_LIB_OPTIM      = $(LD) $(LDFLAGS_SHARED) $(LDFLAGS_OPTIM) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)
LD_LIB_DEBUG      = $(LD) $(LDFLAGS_SHARED) $(LDFLAGS_DEBUG) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)
LD_LIB_COVER      = $(LD) $(LDFLAGS_SHARED) $(LDFLAGS_COVER) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)
LD_PROG_OPTIM     = $(LD) $(LDFLAGS_OPTIM) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)
LD_PROG_DEBUG     = $(LD) $(LDFLAGS_DEBUG) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)
LD_PROG_COVER     = $(LD) $(LDFLAGS_COVER) $(LDFLAGS_PTHREAD) $(LDFLAGS_GENERAL)



BASE_DENOM_2            = $(if $(BASE_DENOM),-$(BASE_DENOM),)
SUFFIX_OBJ_STATIC_OPTIM = $(BASE_DENOM_2)$(OBJ_DENOM_OPTIM).o
SUFFIX_OBJ_SHARED_OPTIM = $(BASE_DENOM_2)$(OBJ_DENOM_OPTIM)$(OBJ_DENOM_SHARED).o
SUFFIX_OBJ_STATIC_DEBUG = $(BASE_DENOM_2)$(OBJ_DENOM_DEBUG).o
SUFFIX_OBJ_SHARED_DEBUG = $(BASE_DENOM_2)$(OBJ_DENOM_DEBUG)$(OBJ_DENOM_SHARED).o
SUFFIX_OBJ_STATIC_COVER = $(BASE_DENOM_2)$(OBJ_DENOM_COVER).o
SUFFIX_OBJ_SHARED_COVER = $(BASE_DENOM_2)$(OBJ_DENOM_COVER)$(OBJ_DENOM_SHARED).o
SUFFIX_LIB_STATIC_OPTIM = $(BASE_DENOM_2)$(LIB_DENOM_OPTIM)$(LIB_SUFFIX_STATIC)
SUFFIX_LIB_SHARED_OPTIM = $(BASE_DENOM_2)$(LIB_DENOM_OPTIM)$(LIB_SUFFIX_SHARED)
SUFFIX_LIB_STATIC_DEBUG = $(BASE_DENOM_2)$(LIB_DENOM_DEBUG)$(LIB_SUFFIX_STATIC)
SUFFIX_LIB_SHARED_DEBUG = $(BASE_DENOM_2)$(LIB_DENOM_DEBUG)$(LIB_SUFFIX_SHARED)
SUFFIX_LIB_STATIC_COVER = $(BASE_DENOM_2)$(LIB_DENOM_COVER)$(LIB_SUFFIX_STATIC)
SUFFIX_LIB_SHARED_COVER = $(BASE_DENOM_2)$(LIB_DENOM_COVER)$(LIB_SUFFIX_SHARED)
SUFFIX_PROG_OPTIM       = $(BASE_DENOM_2)$(PROG_DENOM_OPTIM)
SUFFIX_PROG_DEBUG       = $(BASE_DENOM_2)$(PROG_DENOM_DEBUG)
SUFFIX_PROG_COVER       = $(BASE_DENOM_2)$(PROG_DENOM_COVER)

FOLD_TARGET = $(subst /,_,$(subst .,_,$(subst -,_,$(1))))
GET_LIBRARY_NAME = $(patsubst %.a,%,$(1))
GET_OBJECTS_FROM_SOURCES = $(patsubst %.c,%$(2),$(patsubst %.cpp,%$(2),$(patsubst %.m,%$(2),$(patsubst %.mm,%$(2),$(1)))))
GET_OBJECTS_FOR_TARGET = $(call GET_OBJECTS_FROM_SOURCES,$($(call FOLD_TARGET,$(1))_SOURCES),$(2))
GET_FLAGS = $($(1)) $($(1)$(2))
GET_CFLAGS_FOR_TARGET = $(foreach x,PROJECT DIR $(foreach y,$(GMK_$(call FOLD_TARGET,$(1))_TARGETS) $(1),$(call FOLD_TARGET,$(y))),$(call GET_FLAGS,$(x)_CFLAGS,$(2)))
GET_LDFLAGS_FOR_TARGET = $(foreach x,PROJECT DIR $(call FOLD_TARGET,$(1)),$(call GET_FLAGS,$(x)_LDFLAGS,$(2)))
GET_DEPS_FOR_TARGET = $($(call FOLD_TARGET,$(1))_DEPS)

INC_FLAGS         = $(CFLAGS_INCLUDE)
INC_FLAGS_ABS     = $(CFLAGS_INCLUDE)
ifneq ($(SOURCE_ROOT),)
INC_FLAGS        += -I$(ROOT)/$(SOURCE_ROOT)
INC_FLAGS_ABS    += -I$(ABS_ROOT)/$(SOURCE_ROOT)
endif

INST_LIBRARIES = $(foreach x,lib $(EXTRA_INSTALL_PREFIXES),$($(x)_LIBRARIES))
INST_PROGRAMS  = $(foreach x,bin $(EXTRA_INSTALL_PREFIXES),$($(x)_PROGRAMS))

LIBRARIES = $(INST_LIBRARIES) $(NOINST_LIBRARIES)
PROGRAMS  = $(INST_PROGRAMS) $(NOINST_PROGRAMS) $(TEST_PROGRAMS)

OBJECTS_STATIC_OPTIM = $(foreach x,$(LIBRARIES) $(PROGRAMS),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_STATIC_OPTIM)))
OBJECTS_SHARED_OPTIM = $(foreach x,$(LIBRARIES),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_SHARED_OPTIM)))
OBJECTS_STATIC_DEBUG = $(foreach x,$(LIBRARIES) $(PROGRAMS),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_STATIC_DEBUG)))
OBJECTS_SHARED_DEBUG = $(foreach x,$(LIBRARIES),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_SHARED_DEBUG)))
OBJECTS_STATIC_COVER = $(foreach x,$(LIBRARIES) $(PROGRAMS),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_STATIC_COVER)))
OBJECTS_SHARED_COVER = $(foreach x,$(LIBRARIES),$(call GET_OBJECTS_FOR_TARGET,$(x),$(SUFFIX_OBJ_SHARED_COVER)))
OBJECTS = $(sort $(OBJECTS_STATIC_OPTIM) $(OBJECTS_SHARED_OPTIM) $(OBJECTS_STATIC_DEBUG) $(OBJECTS_SHARED_DEBUG) $(OBJECTS_STATIC_COVER) $(OBJECTS_SHARED_COVER))

TARGETS_LIB_STATIC_OPTIM  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_OPTIM))
TARGETS_LIB_SHARED_OPTIM  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_SHARED_OPTIM))
TARGETS_LIB_STATIC_DEBUG  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_DEBUG))
TARGETS_LIB_SHARED_DEBUG  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_SHARED_DEBUG))
TARGETS_LIB_STATIC_COVER  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_COVER))
TARGETS_LIB_SHARED_COVER  = $(foreach x,$(INST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_SHARED_COVER))
TARGETS_NOINST_LIB_OPTIM  = $(foreach x,$(NOINST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_OPTIM))
TARGETS_NOINST_LIB_DEBUG  = $(foreach x,$(NOINST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_DEBUG))
TARGETS_NOINST_LIB_COVER  = $(foreach x,$(NOINST_LIBRARIES),$(call GET_LIBRARY_NAME,$(x))$(SUFFIX_LIB_STATIC_COVER))
TARGETS_PROG_OPTIM        = $(foreach x,$(INST_PROGRAMS),$(x)$(SUFFIX_PROG_OPTIM))
TARGETS_PROG_DEBUG        = $(foreach x,$(INST_PROGRAMS),$(x)$(SUFFIX_PROG_DEBUG))
TARGETS_PROG_COVER        = $(foreach x,$(INST_PROGRAMS),$(x)$(SUFFIX_PROG_COVER))
TARGETS_NOINST_PROG_OPTIM = $(foreach x,$(NOINST_PROGRAMS),$(x)$(SUFFIX_PROG_OPTIM))
TARGETS_NOINST_PROG_DEBUG = $(foreach x,$(NOINST_PROGRAMS),$(x)$(SUFFIX_PROG_DEBUG))
TARGETS_NOINST_PROG_COVER = $(foreach x,$(NOINST_PROGRAMS),$(x)$(SUFFIX_PROG_COVER))
TARGETS_TEST_PROG_OPTIM   = $(foreach x,$(TEST_PROGRAMS),$(x)$(SUFFIX_PROG_OPTIM))
TARGETS_TEST_PROG_DEBUG   = $(foreach x,$(TEST_PROGRAMS),$(x)$(SUFFIX_PROG_DEBUG))
TARGETS_TEST_PROG_COVER   = $(foreach x,$(TEST_PROGRAMS),$(x)$(SUFFIX_PROG_COVER))

TARGETS_DEFAULT     =
ifneq ($(ENABLE_INSTALL_STATIC_LIBS),)
TARGETS_DEFAULT    += $(TARGETS_LIB_STATIC_OPTIM)
endif
TARGETS_DEFAULT    += $(TARGETS_LIB_SHARED_OPTIM)
ifneq ($(or $(ENABLE_INSTALL_DEBUG_LIBS),$(ENABLE_INSTALL_DEBUG_PROGS)),)
TARGETS_DEFAULT    += $(TARGETS_LIB_SHARED_DEBUG)
endif
TARGETS_DEFAULT    += $(TARGETS_NOINST_LIB_OPTIM)
ifneq ($(ENABLE_INSTALL_DEBUG_PROGS),)
TARGETS_DEFAULT    += $(TARGETS_NOINST_LIB_DEBUG)
endif
TARGETS_DEFAULT    += $(TARGETS_PROG_OPTIM)
ifneq ($(ENABLE_INSTALL_DEBUG_PROGS),)
TARGETS_DEFAULT    += $(TARGETS_PROG_DEBUG)
endif
TARGETS_DEFAULT    += $(TARGETS_NOINST_PROG_OPTIM)

TARGETS_MINIMAL     = $(TARGETS_LIB_SHARED_OPTIM) $(TARGETS_NOINST_LIB_OPTIM) $(TARGETS_PROG_OPTIM) $(TARGETS_NOINST_PROG_OPTIM)
TARGETS_NODEBUG     = $(TARGETS_LIB_STATIC_OPTIM) $(TARGETS_LIB_SHARED_OPTIM) $(TARGETS_NOINST_LIB_OPTIM) $(TARGETS_PROG_OPTIM) $(TARGETS_NOINST_PROG_OPTIM)
TARGETS_DEBUG       = $(TARGETS_LIB_SHARED_DEBUG) $(TARGETS_NOINST_LIB_DEBUG) $(TARGETS_PROG_DEBUG) $(TARGETS_NOINST_PROG_DEBUG)
TARGETS_COVER       = $(TARGETS_LIB_SHARED_COVER) $(TARGETS_NOINST_LIB_COVER) $(TARGETS_PROG_COVER) $(TARGETS_NOINST_PROG_COVER)
TARGETS_EVERYTHING  = $(TARGETS_LIB_STATIC_OPTIM) $(TARGETS_LIB_SHARED_OPTIM) $(TARGETS_LIB_SHARED_DEBUG) $(TARGETS_NOINST_LIB_OPTIM) $(TARGETS_NOINST_LIB_DEBUG)
TARGETS_EVERYTHING += $(TARGETS_PROG_OPTIM) $(TARGETS_PROG_DEBUG) $(TARGETS_NOINST_PROG_OPTIM) $(TARGETS_NOINST_PROG_DEBUG) $(TARGETS_TEST_PROG_OPTIM) $(TARGETS_TEST_PROG_DEBUG)
TARGETS_TEST        = $(TARGETS_LIB_SHARED_OPTIM) $(TARGETS_NOINST_LIB_OPTIM) $(TARGETS_TEST_PROG_OPTIM)
TARGETS_TEST_DEBUG  = $(TARGETS_LIB_SHARED_DEBUG) $(TARGETS_NOINST_LIB_DEBUG) $(TARGETS_TEST_PROG_DEBUG)
TARGETS_TEST_COVER  = $(TARGETS_LIB_SHARED_COVER) $(TARGETS_NOINST_LIB_COVER) $(TARGETS_TEST_PROG_COVER)

TARGETS_LIB_STATIC  = $(TARGETS_LIB_STATIC_OPTIM) $(TARGETS_LIB_STATIC_DEBUG) $(TARGETS_LIB_STATIC_COVER)
TARGETS_LIB_SHARED  = $(TARGETS_LIB_SHARED_OPTIM) $(TARGETS_LIB_SHARED_DEBUG) $(TARGETS_LIB_SHARED_COVER)
TARGETS_NOINST_LIB  = $(TARGETS_NOINST_LIB_OPTIM) $(TARGETS_NOINST_LIB_DEBUG) $(TARGETS_NOINST_LIB_COVER)
TARGETS_PROG        = $(TARGETS_PROG_OPTIM) $(TARGETS_PROG_DEBUG) $(TARGETS_PROG_COVER)
TARGETS_NOINST_PROG = $(TARGETS_NOINST_PROG_OPTIM) $(TARGETS_NOINST_PROG_DEBUG) $(TARGETS_NOINST_PROG_COVER)
TARGETS_TEST_PROG   = $(TARGETS_TEST_PROG_OPTIM) $(TARGETS_TEST_PROG_DEBUG) $(TARGETS_TEST_PROG_COVER)

TARGETS  = $(TARGETS_LIB_STATIC) $(TARGETS_LIB_SHARED) $(TARGETS_NOINST_LIB)
TARGETS += $(foreach x,$(TARGETS_PROG),$(x) $(x)-noinst) $(TARGETS_NOINST_PROG) $(TARGETS_TEST_PROG)

RECURSIVE_MODES = default minimal nodebug debug cover everything clean install uninstall test-norun test-debug-norun test test-debug test-cover memtest memtest-debug

.PHONY: all
all: default

default/local:    $(TARGETS_DEFAULT) update-libdeps-files
minimal/local:    $(TARGETS_MINIMAL) update-libdeps-files
nodebug/local:    $(TARGETS_NODEBUG) update-libdeps-files
debug/local:      $(TARGETS_DEBUG) update-libdeps-files
cover/local:      $(TARGETS_COVER) update-libdeps-files
everything/local: $(TARGETS_EVERYTHING) update-libdeps-files
test-norun:       $(TARGETS_TEST) update-libdeps-files
test-debug-norun: $(TARGETS_TEST_DEBUG) update-libdeps-files


# Update everything if any makefile has changed
DEP_MAKEFILES = Makefile $(THIS_MAKEFILE)
ifneq ($(wildcard $(CONFIG_MK)),)
DEP_MAKEFILES += $(CONFIG_MK)
endif
$(GENERATED_SOURCES) $(OBJECTS) $(TARGETS): $(DEP_MAKEFILES)
$(OBJECTS): $(GENERATED_SOURCES)

# Disable all suffix rules and some interfering implicit pattern rules
.SUFFIXES:
%: %.o
%: %.c
%: %.cpp



# SUBDIRECTORIES

# ARGS: subdir, mode, dep
define SUBDIR_DEP_RULE
ifeq ($(3),.)
subdir/$(1)/$(2): $(2)/local
else
subdir/$(1)/$(2): subdir/$(3)/$(2)
endif
endef

# ARGS: subdir, mode
define SUBDIR_MODE_RULES
.PHONY: subdir/$(1)/$(2)
$$(foreach x,$$($$(call FOLD_TARGET,$(1))_DEPS),$$(eval $$(call SUBDIR_DEP_RULE,$(1),$(2),$$(x))))
ifeq ($(2),default)
subdir/$(1)/$(2):
	@$$(MAKE) -C $(1)
else
subdir/$(1)/$(2):
	@$$(MAKE) -C $(1) $(2)
endif
endef

SUBDIR_RULES = $(foreach x,$(RECURSIVE_MODES),$(eval $(call SUBDIR_MODE_RULES,$(1),$(x))))

$(foreach x,$(SUBDIRS) $(PASSIVE_SUBDIRS),$(eval $(call SUBDIR_RULES,$(x))))

define RECURSIVE_MODE_RULES
.PHONY: $(1) $(1)/local $(1)/after
$(1): $(1)/local $(patsubst %,subdir/%/$(1),$(SUBDIRS)) $(1)/after
{'fraction_non_alphanumeric': 0.16137957660382216, 'fraction_numerical': 0.009051326598459988, 'mean_word_length': 6.735855317736851, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7072858', 'n_tokens_mistral': 19581, 'n_tokens_neox': 18552, 'n_words': 3482}