+### 3.1 Selecting compiler (default = gcc)
+CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS)
+DEPENDFLAGS += -std=c++17
+LDFLAGS += $(EXTRALDFLAGS)
+
+ifeq ($(COMP),)
+ COMP=gcc
+endif
+
+ifeq ($(COMP),gcc)
+ comp=gcc
+ CXX=g++
+ CXXFLAGS += -pedantic -Wextra -Wshadow
+
+ ifeq ($(arch),$(filter $(arch),armv7 armv8))
+ ifeq ($(OS),Android)
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+ else
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+
+ ifeq ($(arch),$(filter $(arch),armv7))
+ LDFLAGS += -latomic
+ endif
+
+ ifneq ($(KERNEL),Darwin)
+ LDFLAGS += -Wl,--no-as-needed
+ endif
+endif
+
+ifeq ($(COMP),mingw)
+ comp=mingw
+
+ ifeq ($(KERNEL),Linux)
+ ifeq ($(bits),64)
+ ifeq ($(shell which x86_64-w64-mingw32-c++-posix),)
+ CXX=x86_64-w64-mingw32-c++
+ else
+ CXX=x86_64-w64-mingw32-c++-posix
+ endif
+ else
+ ifeq ($(shell which i686-w64-mingw32-c++-posix),)
+ CXX=i686-w64-mingw32-c++
+ else
+ CXX=i686-w64-mingw32-c++-posix
+ endif
+ endif
+ else
+ CXX=g++
+ endif
+
+ CXXFLAGS += -Wextra -Wshadow
+ LDFLAGS += -static
+endif
+
+ifeq ($(COMP),icc)
+ comp=icc
+ CXX=icpc
+ CXXFLAGS += -diag-disable 1476,10120 -Wcheck -Wabi -Wdeprecated -strict-ansi
+endif
+
+ifeq ($(COMP),clang)
+ comp=clang
+ CXX=clang++
+ CXXFLAGS += -pedantic -Wextra -Wshadow
+
+ ifneq ($(KERNEL),Darwin)
+ ifneq ($(KERNEL),OpenBSD)
+ LDFLAGS += -latomic
+ endif
+ endif
+
+ ifeq ($(arch),$(filter $(arch),armv7 armv8))
+ ifeq ($(OS),Android)
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+ else
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+endif
+
+ifeq ($(KERNEL),Darwin)
+ CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.14
+ LDFLAGS += -arch $(arch) -mmacosx-version-min=10.14
+ XCRUN = xcrun
+endif
+
+# To cross-compile for Android, NDK version r21 or later is recommended.
+# In earlier NDK versions, you'll need to pass -fno-addrsig if using GNU binutils.
+# Currently we don't know how to make PGO builds with the NDK yet.
+ifeq ($(COMP),ndk)
+ CXXFLAGS += -stdlib=libc++ -fPIE
+ comp=clang
+ ifeq ($(arch),armv7)
+ CXX=armv7a-linux-androideabi16-clang++
+ CXXFLAGS += -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=neon
+ STRIP=arm-linux-androideabi-strip
+ endif
+ ifeq ($(arch),armv8)
+ CXX=aarch64-linux-android21-clang++
+ STRIP=aarch64-linux-android-strip
+ endif
+ LDFLAGS += -static-libstdc++ -pie -lm -latomic
+endif
+
+ifeq ($(comp),icc)
+ profile_make = icc-profile-make
+ profile_use = icc-profile-use
+else ifeq ($(comp),clang)
+ profile_make = clang-profile-make
+ profile_use = clang-profile-use
+else
+ profile_make = gcc-profile-make
+ profile_use = gcc-profile-use
+endif
+
+### Travis CI script uses COMPILER to overwrite CXX
+ifdef COMPILER
+ COMPCXX=$(COMPILER)
+endif
+
+### Allow overwriting CXX from command line
+ifdef COMPCXX
+ CXX=$(COMPCXX)
+endif
+
+### Sometimes gcc is really clang
+ifeq ($(COMP),gcc)
+ gccversion = $(shell $(CXX) --version)
+ gccisclang = $(findstring clang,$(gccversion))
+ ifneq ($(gccisclang),)
+ profile_make = clang-profile-make
+ profile_use = clang-profile-use
+ endif
+endif
+
+### On mingw use Windows threads, otherwise POSIX
+ifneq ($(comp),mingw)
+ CXXFLAGS += -DUSE_PTHREADS
+ # On Android Bionic's C library comes with its own pthread implementation bundled in
+ ifneq ($(OS),Android)
+ # Haiku has pthreads in its libroot, so only link it in on other platforms
+ ifneq ($(KERNEL),Haiku)
+ ifneq ($(COMP),ndk)
+ LDFLAGS += -lpthread
+ endif
+ endif
+ endif
+endif
+
+### 3.2.1 Debugging
+ifeq ($(debug),no)
+ CXXFLAGS += -DNDEBUG
+else
+ CXXFLAGS += -g
+endif
+
+### 3.2.2 Debugging with undefined behavior sanitizers
+ifneq ($(sanitize),no)
+ CXXFLAGS += -g3 -fsanitize=$(sanitize)
+ LDFLAGS += -fsanitize=$(sanitize)
+endif
+
+### 3.3 Optimization
+ifeq ($(optimize),yes)
+
+ CXXFLAGS += -O3
+
+ ifeq ($(comp),gcc)
+ ifeq ($(OS), Android)
+ CXXFLAGS += -fno-gcse -mthumb -march=armv7-a -mfloat-abi=softfp
+ endif
+ endif
+
+ ifeq ($(comp),$(filter $(comp),gcc clang icc))
+ ifeq ($(KERNEL),Darwin)
+ CXXFLAGS += -mdynamic-no-pic
+ endif
+ endif
+endif
+
+### 3.4 Bits
+ifeq ($(bits),64)
+ CXXFLAGS += -DIS_64BIT
+endif
+
+### 3.5 prefetch
+ifeq ($(prefetch),yes)
+ ifeq ($(sse),yes)
+ CXXFLAGS += -msse
+ endif
+else
+ CXXFLAGS += -DNO_PREFETCH
+endif
+
+### 3.6 popcnt
+ifeq ($(popcnt),yes)
+ ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8 arm64))
+ CXXFLAGS += -DUSE_POPCNT
+ else ifeq ($(comp),icc)
+ CXXFLAGS += -msse3 -DUSE_POPCNT
+ else
+ CXXFLAGS += -msse3 -mpopcnt -DUSE_POPCNT
+ endif
+endif
+
+
+ifeq ($(avx2),yes)
+ CXXFLAGS += -DUSE_AVX2
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mavx2
+ endif
+endif
+
+ifeq ($(avx512),yes)
+ CXXFLAGS += -DUSE_AVX512
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mavx512f -mavx512bw
+ endif
+endif
+
+ifeq ($(vnni256),yes)
+ CXXFLAGS += -DUSE_VNNI
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mavx512f -mavx512bw -mavx512vnni -mavx512dq -mavx512vl -mprefer-vector-width=256
+ endif
+endif
+
+ifeq ($(vnni512),yes)
+ CXXFLAGS += -DUSE_VNNI
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mavx512vnni -mavx512dq -mavx512vl
+ endif
+endif
+
+ifeq ($(sse41),yes)
+ CXXFLAGS += -DUSE_SSE41
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -msse4.1
+ endif
+endif
+
+ifeq ($(ssse3),yes)
+ CXXFLAGS += -DUSE_SSSE3
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mssse3
+ endif
+endif
+
+ifeq ($(sse2),yes)
+ CXXFLAGS += -DUSE_SSE2
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -msse2
+ endif
+endif
+
+ifeq ($(mmx),yes)
+ CXXFLAGS += -DUSE_MMX
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mmmx
+ endif
+endif
+
+ifeq ($(neon),yes)
+ CXXFLAGS += -DUSE_NEON
+ ifeq ($(KERNEL),Linux)
+ ifneq ($(COMP),ndk)
+ ifneq ($(arch),armv8)
+ CXXFLAGS += -mfpu=neon
+ endif
+ endif
+ endif
+endif
+
+### 3.7 pext
+ifeq ($(pext),yes)
+ CXXFLAGS += -DUSE_PEXT
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mbmi2
+ endif
+endif
+
+### 3.8 Link Time Optimization
+### This is a mix of compile and link time options because the lto link phase
+### needs access to the optimization flags.
+ifeq ($(optimize),yes)
+ifeq ($(debug), no)
+ ifeq ($(comp),clang)
+ CXXFLAGS += -flto=thin
+ ifneq ($(findstring MINGW,$(KERNEL)),)
+ CXXFLAGS += -fuse-ld=lld
+ else ifneq ($(findstring MSYS,$(KERNEL)),)
+ CXXFLAGS += -fuse-ld=lld
+ endif
+ LDFLAGS += $(CXXFLAGS)
+
+# GCC and CLANG use different methods for parallelizing LTO and CLANG pretends to be
+# GCC on some systems.
+ else ifeq ($(comp),gcc)
+ ifeq ($(gccisclang),)
+ CXXFLAGS += -flto
+ LDFLAGS += $(CXXFLAGS) -flto=jobserver
+ ifneq ($(findstring MINGW,$(KERNEL)),)
+ LDFLAGS += -save-temps
+ else ifneq ($(findstring MSYS,$(KERNEL)),)
+ LDFLAGS += -save-temps
+ endif
+ else
+ CXXFLAGS += -flto=thin
+ LDFLAGS += $(CXXFLAGS)
+ endif
+
+# To use LTO and static linking on windows, the tool chain requires a recent gcc:
+# gcc version 10.1 in msys2 or TDM-GCC version 9.2 are known to work, older might not.
+# So, only enable it for a cross from Linux by default.
+ else ifeq ($(comp),mingw)
+ ifeq ($(KERNEL),Linux)
+ ifneq ($(arch),i386)
+ CXXFLAGS += -flto
+ LDFLAGS += $(CXXFLAGS) -flto=jobserver
+ endif
+ endif
+ endif
+endif
+endif
+
+### 3.9 Android 5 can only run position independent executables. Note that this
+### breaks Android 4.0 and earlier.
+ifeq ($(OS), Android)
+ CXXFLAGS += -fPIE
+ LDFLAGS += -fPIE -pie
+endif