ifndef MAKE
MAKE := make
endif
ifndef HOSTMAKE
HOSTMAKE = $(MAKE)
endif
HOSTMAKE := $(shell which $(HOSTMAKE) || type -p $(HOSTMAKE) || echo make)

# If BR2_JLEVEL is 0, scale the maximum concurrency with the number of
# CPUs. An additional job is used in order to keep processors busy
# while waiting on I/O.
# If the number of processors is not available, assume one.
ifeq ($(BR2_JLEVEL),0)
PARALLEL_JOBS := $(shell echo \
	$$((1 + `getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1`)))
else
PARALLEL_JOBS := $(BR2_JLEVEL)
endif

MAKE1 := $(HOSTMAKE) -j1
override MAKE = $(HOSTMAKE) \
	$(if $(findstring j,$(filter-out --%,$(MAKEFLAGS))),,-j$(PARALLEL_JOBS))

ifeq ($(BR2_TOOLCHAIN_BUILDROOT),y)
TARGET_VENDOR = $(call qstrip,$(BR2_TOOLCHAIN_BUILDROOT_VENDOR))
else
TARGET_VENDOR = buildroot
endif

# Sanity checks
ifeq ($(TARGET_VENDOR),)
$(error BR2_TOOLCHAIN_BUILDROOT_VENDOR is not allowed to be empty)
endif
ifeq ($(TARGET_VENDOR),unknown)
$(error BR2_TOOLCHAIN_BUILDROOT_VENDOR cannot be 'unknown'. \
	It might be confused with the native toolchain)
endif

# Compute GNU_TARGET_NAME
GNU_TARGET_NAME = $(ARCH)-$(TARGET_VENDOR)-$(TARGET_OS)-$(LIBC)$(ABI)

# FLAT binary format needs uclinux
ifeq ($(BR2_BINFMT_FLAT),y)
TARGET_OS = uclinux
else
TARGET_OS = linux
endif

ifeq ($(BR2_TOOLCHAIN_USES_UCLIBC),y)
LIBC = uclibc
else ifeq ($(BR2_TOOLCHAIN_USES_MUSL),y)
LIBC = musl
else
LIBC = gnu
endif

# The ABI suffix is a bit special on ARM, as it needs to be
# -uclibcgnueabi for uClibc EABI, and -gnueabi for glibc EABI.
# This means that the LIBC and ABI aren't strictly orthogonal,
# which explains why we need the test on LIBC below.
ifeq ($(BR2_arm)$(BR2_armeb),y)
ifeq ($(LIBC),uclibc)
ABI = gnueabi
else
ABI = eabi
endif

ifeq ($(BR2_ARM_EABIHF),y)
ABI := $(ABI)hf
endif
endif

# For C-SKY abiv1 & abiv2
ifeq ($(BR2_csky),y)
ifeq ($(BR2_ck610),y)
ABI = abiv1
else
ABI = abiv2
endif
endif

# For FSL PowerPC there's SPE
ifeq ($(BR2_powerpc_SPE),y)
ABI = spe
# MPC8540s are e500v1 with single precision FP
ifeq ($(BR2_powerpc_8540),y)
TARGET_ABI += -mabi=spe -mfloat-gprs=single -Wa,-me500
endif
ifeq ($(BR2_powerpc_8548),y)
TARGET_ABI += -mabi=spe -mfloat-gprs=double -Wa,-me500x2
endif
ifeq ($(BR2_powerpc_e500mc),y)
TARGET_ABI += -mabi=spe -mfloat-gprs=double -Wa,-me500mc
endif
endif

# Use longcalls option for Xtensa globally.
# The 'longcalls' option allows calls across a greater range of addresses,
# and is required for some packages. While this option can degrade both
# code size and performance, the linker can usually optimize away the
# overhead when a call ends up within a certain range.
#
# Use auto-litpools for Xtensa globally.
# Collecting literals into separate section can be advantageous if that
# section is placed into DTCM at link time. This is applicable for code
# running on bare metal, but makes no sense under linux, where userspace
# is isolated from the physical memory details. OTOH placing literals into
# separate section breaks build of huge source files, because l32r
# instruction can only access literals in 256 KBytes range.
#
ifeq ($(BR2_xtensa),y)
TARGET_ABI += -mlongcalls -mauto-litpools
endif

STAGING_SUBDIR = $(GNU_TARGET_NAME)/sysroot
STAGING_DIR    = $(HOST_DIR)/$(STAGING_SUBDIR)

ifeq ($(BR2_OPTIMIZE_0),y)
TARGET_OPTIMIZATION = -O0
endif
ifeq ($(BR2_OPTIMIZE_1),y)
TARGET_OPTIMIZATION = -O1
endif
ifeq ($(BR2_OPTIMIZE_2),y)
TARGET_OPTIMIZATION = -O2
endif
ifeq ($(BR2_OPTIMIZE_3),y)
TARGET_OPTIMIZATION = -O3
endif
ifeq ($(BR2_OPTIMIZE_G),y)
TARGET_OPTIMIZATION = -Og
endif
ifeq ($(BR2_OPTIMIZE_S),y)
TARGET_OPTIMIZATION = -Os
endif
ifeq ($(BR2_OPTIMIZE_FAST),y)
TARGET_OPTIMIZATION = -Ofast
endif
ifeq ($(BR2_ENABLE_DEBUG),)
TARGET_DEBUGGING = -g0
endif
ifeq ($(BR2_DEBUG_1),y)
TARGET_DEBUGGING = -g1
endif
ifeq ($(BR2_DEBUG_2),y)
TARGET_DEBUGGING = -g2
endif
ifeq ($(BR2_DEBUG_3),y)
TARGET_DEBUGGING = -g3
endif

TARGET_LDFLAGS = $(call qstrip,$(BR2_TARGET_LDFLAGS))

# By design, _FORTIFY_SOURCE requires gcc optimization to be enabled.
# Therefore, we need to pass _FORTIFY_SOURCE and the optimization level
# through the same mechanism, i.e currently through CFLAGS. Passing
# _FORTIFY_SOURCE through the wrapper and the optimization level
# through CFLAGS would not work, because CFLAGS are sometimes
# ignored/overridden by packages, but the flags passed by the wrapper
# are enforced: this would cause _FORTIFY_SOURCE to be used without any
# optimization level, leading to a build / configure failure. So we keep
# passing _FORTIFY_SOURCE and the optimization level both through CFLAGS.
ifeq ($(BR2_FORTIFY_SOURCE_1),y)
TARGET_HARDENED += -D_FORTIFY_SOURCE=1
else ifeq ($(BR2_FORTIFY_SOURCE_2),y)
TARGET_HARDENED += -D_FORTIFY_SOURCE=2
endif

TARGET_CPPFLAGS += -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
TARGET_CFLAGS = $(TARGET_CPPFLAGS) $(TARGET_ABI) $(TARGET_OPTIMIZATION) $(TARGET_DEBUGGING) $(TARGET_HARDENED)
TARGET_CXXFLAGS = $(TARGET_CFLAGS)
TARGET_FCFLAGS = $(TARGET_ABI) $(TARGET_OPTIMIZATION) $(TARGET_DEBUGGING)

# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79509
ifeq ($(BR2_m68k_cf),y)
TARGET_CFLAGS += -fno-dwarf2-cfi-asm
TARGET_CXXFLAGS += -fno-dwarf2-cfi-asm
endif

ifeq ($(BR2_BINFMT_FLAT),y)
TARGET_CFLAGS += $(if $($(PKG)_FLAT_STACKSIZE),-Wl$(comma)-elf2flt=-s$($(PKG)_FLAT_STACKSIZE),\
	-Wl$(comma)-elf2flt)
TARGET_CXXFLAGS += $(if $($(PKG)_FLAT_STACKSIZE),-Wl$(comma)-elf2flt=-s$($(PKG)_FLAT_STACKSIZE),\
	-Wl$(comma)-elf2flt)
TARGET_FCFLAGS += $(if $($(PKG)_FLAT_STACKSIZE),-Wl$(comma)-elf2flt=-s$($(PKG)_FLAT_STACKSIZE),\
	-Wl$(comma)-elf2flt)
TARGET_LDFLAGS += $(if $($(PKG)_FLAT_STACKSIZE),-Wl$(comma)-elf2flt=-s$($(PKG)_FLAT_STACKSIZE),-Wl$(comma)-elf2flt)
endif

ifeq ($(BR2_BINFMT_FLAT_SHARED),y)
TARGET_LDFLAGS += -mid-shared-library -mshared-library-id=0
TARGET_CFLAGS += -mid-shared-library -mshared-library-id=0
TARGET_FCFLAGS += -mid-shared-library -mshared-library-id=0
TARGET_CXXFLAGS += -mid-shared-library -mshared-library-id=0
endif

ifeq ($(BR2_TOOLCHAIN_BUILDROOT),y)
TARGET_CROSS = $(HOST_DIR)/bin/$(GNU_TARGET_NAME)-
else
TARGET_CROSS = $(HOST_DIR)/bin/$(TOOLCHAIN_EXTERNAL_PREFIX)-
endif

# Define TARGET_xx variables for all common binutils/gcc
TARGET_AR       = $(TARGET_CROSS)ar
TARGET_AS       = $(TARGET_CROSS)as
TARGET_CC       = $(TARGET_CROSS)gcc
TARGET_CPP      = $(TARGET_CROSS)cpp
TARGET_CXX      = $(TARGET_CROSS)g++
TARGET_FC       = $(TARGET_CROSS)gfortran
TARGET_LD       = $(TARGET_CROSS)ld
TARGET_NM       = $(TARGET_CROSS)nm
TARGET_RANLIB   = $(TARGET_CROSS)ranlib
TARGET_READELF  = $(TARGET_CROSS)readelf
TARGET_OBJCOPY  = $(TARGET_CROSS)objcopy
TARGET_OBJDUMP  = $(TARGET_CROSS)objdump

ifeq ($(BR2_STRIP_strip),y)
STRIP_STRIP_DEBUG := --strip-debug
TARGET_STRIP = $(TARGET_CROSS)strip
STRIPCMD = $(TARGET_CROSS)strip --remove-section=.comment --remove-section=.note
else
TARGET_STRIP = /bin/true
STRIPCMD = $(TARGET_STRIP)
endif
INSTALL := $(shell which install || type -p install)
UNZIP := $(shell which unzip || type -p unzip) -q

APPLY_PATCHES = PATH=$(HOST_DIR)/bin:$$PATH support/scripts/apply-patches.sh $(if $(QUIET),-s)

HOST_CPPFLAGS  = -I$(HOST_DIR)/include
HOST_CFLAGS   ?= -O2
HOST_CFLAGS   += $(HOST_CPPFLAGS)
HOST_CXXFLAGS += $(HOST_CFLAGS)
HOST_LDFLAGS  += -L$(HOST_DIR)/lib -Wl,-rpath,$(HOST_DIR)/lib

# host-intltool should be executed with the system perl, so we save
# the path to the system perl, before a host-perl built by Buildroot
# might get installed into $(HOST_DIR)/bin and therefore appears
# in our PATH. This system perl will be used as INTLTOOL_PERL.
export PERL=$(shell which perl)

# host-intltool needs libxml-parser-perl, which Buildroot installs in
# $(HOST_DIR)/lib/perl, so we must make sure that the system perl
# finds this perl module by exporting the proper value for PERL5LIB.
export PERL5LIB=$(HOST_DIR)/lib/perl

TARGET_MAKE_ENV = PATH=$(BR_PATH)

TARGET_CONFIGURE_OPTS = \
	$(TARGET_MAKE_ENV) \
	AR="$(TARGET_AR)" \
	AS="$(TARGET_AS)" \
	LD="$(TARGET_LD)" \
	NM="$(TARGET_NM)" \
	CC="$(TARGET_CC)" \
	GCC="$(TARGET_CC)" \
	CPP="$(TARGET_CPP)" \
	CXX="$(TARGET_CXX)" \
	FC="$(TARGET_FC)" \
	F77="$(TARGET_FC)" \
	RANLIB="$(TARGET_RANLIB)" \
	READELF="$(TARGET_READELF)" \
	STRIP="$(TARGET_STRIP)" \
	OBJCOPY="$(TARGET_OBJCOPY)" \
	OBJDUMP="$(TARGET_OBJDUMP)" \
	AR_FOR_BUILD="$(HOSTAR)" \
	AS_FOR_BUILD="$(HOSTAS)" \
	CC_FOR_BUILD="$(HOSTCC)" \
	GCC_FOR_BUILD="$(HOSTCC)" \
	CXX_FOR_BUILD="$(HOSTCXX)" \
	LD_FOR_BUILD="$(HOSTLD)" \
	CPPFLAGS_FOR_BUILD="$(HOST_CPPFLAGS)" \
	CFLAGS_FOR_BUILD="$(HOST_CFLAGS)" \
	CXXFLAGS_FOR_BUILD="$(HOST_CXXFLAGS)" \
	LDFLAGS_FOR_BUILD="$(HOST_LDFLAGS)" \
	FCFLAGS_FOR_BUILD="$(HOST_FCFLAGS)" \
	DEFAULT_ASSEMBLER="$(TARGET_AS)" \
	DEFAULT_LINKER="$(TARGET_LD)" \
	CPPFLAGS="$(TARGET_CPPFLAGS)" \
	CFLAGS="$(TARGET_CFLAGS)" \
	CXXFLAGS="$(TARGET_CXXFLAGS)" \
	LDFLAGS="$(TARGET_LDFLAGS)" \
	FCFLAGS="$(TARGET_FCFLAGS)" \
	FFLAGS="$(TARGET_FCFLAGS)" \
	PKG_CONFIG="$(PKG_CONFIG_HOST_BINARY)" \
	STAGING_DIR="$(STAGING_DIR)" \
	INTLTOOL_PERL=$(PERL)


HOST_MAKE_ENV = \
	PATH=$(BR_PATH) \
	PKG_CONFIG="$(PKG_CONFIG_HOST_BINARY)" \
	PKG_CONFIG_SYSROOT_DIR="/" \
	PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 \
	PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 \
	PKG_CONFIG_LIBDIR="$(HOST_DIR)/lib/pkgconfig:$(HOST_DIR)/share/pkgconfig"

HOST_CONFIGURE_OPTS = \
	$(HOST_MAKE_ENV) \
	AR="$(HOSTAR)" \
	AS="$(HOSTAS)" \
	LD="$(HOSTLD)" \
	NM="$(HOSTNM)" \
	CC="$(HOSTCC)" \
	GCC="$(HOSTCC)" \
	CXX="$(HOSTCXX)" \
	CPP="$(HOSTCPP)" \
	OBJCOPY="$(HOSTOBJCOPY)" \
	RANLIB="$(HOSTRANLIB)" \
	CPPFLAGS="$(HOST_CPPFLAGS)" \
	CFLAGS="$(HOST_CFLAGS)" \
	CXXFLAGS="$(HOST_CXXFLAGS)" \
	LDFLAGS="$(HOST_LDFLAGS)" \
	INTLTOOL_PERL=$(PERL)

# This is extra environment we can not export ourselves (eg. because some
# packages use that variable internally, eg. uboot), so we have to
# explicitly pass it to user-supplied external hooks (eg. post-build,
# post-images)
EXTRA_ENV = \
	PATH=$(BR_PATH) \
	BR2_DL_DIR=$(BR2_DL_DIR) \
	BUILD_DIR=$(BUILD_DIR) \
	CONFIG_DIR=$(CONFIG_DIR) \
	O=$(CANONICAL_O)

################################################################################
# settings we need to pass to configure

# does unaligned access trap?
BR2_AC_CV_TRAP_CHECK = ac_cv_lbl_unaligned_fail=yes
ifeq ($(BR2_i386),y)
BR2_AC_CV_TRAP_CHECK = ac_cv_lbl_unaligned_fail=no
endif
ifeq ($(BR2_x86_64),y)
BR2_AC_CV_TRAP_CHECK = ac_cv_lbl_unaligned_fail=no
endif
ifeq ($(BR2_m68k),y)
BR2_AC_CV_TRAP_CHECK = ac_cv_lbl_unaligned_fail=no
endif
ifeq ($(BR2_powerpc)$(BR2_powerpc64)$(BR2_powerpc64le),y)
BR2_AC_CV_TRAP_CHECK = ac_cv_lbl_unaligned_fail=no
endif

ifeq ($(BR2_ENDIAN),"BIG")
BR2_AC_CV_C_BIGENDIAN = ac_cv_c_bigendian=yes
else
BR2_AC_CV_C_BIGENDIAN = ac_cv_c_bigendian=no
endif

# AM_GNU_GETTEXT misdetects musl gettext support.
# musl currently implements api level 1 and 2 (basic + ngettext)
# http://www.openwall.com/lists/musl/2015/04/16/3
#
# These autoconf variables should only be pre-seeded when the minimal
# gettext implementation of musl is used. When the full blown
# implementation provided by gettext libintl is used, auto-detection
# works fine, and pre-seeding those values is actually wrong.
ifeq ($(BR2_TOOLCHAIN_USES_MUSL):$(BR2_PACKAGE_GETTEXT_PROVIDES_LIBINTL),y:)
BR2_GT_CV_FUNC_GNUGETTEXT_LIBC = \
	gt_cv_func_gnugettext1_libc=yes \
	gt_cv_func_gnugettext2_libc=yes
endif

TARGET_CONFIGURE_ARGS = \
	$(BR2_AC_CV_TRAP_CHECK) \
	ac_cv_func_mmap_fixed_mapped=yes \
	ac_cv_func_memcmp_working=yes \
	ac_cv_have_decl_malloc=yes \
	gl_cv_func_malloc_0_nonnull=yes \
	ac_cv_func_malloc_0_nonnull=yes \
	ac_cv_func_calloc_0_nonnull=yes \
	ac_cv_func_realloc_0_nonnull=yes \
	lt_cv_sys_lib_search_path_spec="" \
	$(BR2_AC_CV_C_BIGENDIAN) \
	$(BR2_GT_CV_FUNC_GNUGETTEXT_LIBC)

################################################################################

ifeq ($(BR2_SYSTEM_ENABLE_NLS),y)
NLS_OPTS = --enable-nls
TARGET_NLS_DEPENDENCIES = host-gettext
ifeq ($(BR2_PACKAGE_GETTEXT_PROVIDES_LIBINTL),y)
TARGET_NLS_DEPENDENCIES += gettext
TARGET_NLS_LIBS += -lintl
endif
else
NLS_OPTS = --disable-nls
endif

# We need anything that is invalid. Traditionally, we'd have used 'false' (and
# we did so in the past). However, that breaks libtool for packages that have
# optional C++ support (e.g. gnutls), because libtool will *require* a *valid*
# C++ preprocessor as long as CXX is not 'no'.
# Now, whether we use 'no' or 'false' for CXX as the same side effect: it is an
# invalid C++ compiler, and thus will cause detection of C++ to fail (which is
# expected and what we want), while at the same time taming libtool into
# silence.
ifneq ($(BR2_INSTALL_LIBSTDCPP),y)
TARGET_CONFIGURE_OPTS += CXX=no
endif

ifeq ($(BR2_STATIC_LIBS),y)
SHARED_STATIC_LIBS_OPTS = --enable-static --disable-shared
TARGET_CFLAGS += -static
TARGET_CXXFLAGS += -static
TARGET_FCFLAGS += -static
TARGET_LDFLAGS += -static
else ifeq ($(BR2_SHARED_LIBS),y)
SHARED_STATIC_LIBS_OPTS = --disable-static --enable-shared
else ifeq ($(BR2_SHARED_STATIC_LIBS),y)
SHARED_STATIC_LIBS_OPTS = --enable-static --enable-shared
endif

ifeq ($(BR2_COMPILER_PARANOID_UNSAFE_PATH),y)
export BR_COMPILER_PARANOID_UNSAFE_PATH=enabled
endif

include package/pkg-download.mk
include package/pkg-autotools.mk
include package/pkg-cmake.mk
include package/pkg-luarocks.mk
include package/pkg-perl.mk
include package/pkg-python.mk
include package/pkg-virtual.mk
include package/pkg-generic.mk
include package/pkg-kconfig.mk
include package/pkg-rebar.mk
include package/pkg-kernel-module.mk
include package/pkg-waf.mk
include package/pkg-golang.mk
include package/pkg-meson.mk
include package/pkg-qmake.mk