# SPDX-FileCopyrightText: 2013 Stefano Babic <sbabic@denx.de>
#
# SPDX-License-Identifier: GPL-2.0-only

# ==========================================================================
# Build system
# ==========================================================================

SWU_VER = $(shell git describe --tags --always --dirty)
export SWU_VER
SKIP_STRIP ?= n

ifneq ($(CC),clang)
GCC_MAJOR = $(shell echo __GNUC__ | $(CC) -E -x c - | tail -n 1)
GCC_MINOR = $(shell echo __GNUC_MINOR__ | $(CC) -E -x c - | tail -n 1)
GCC_VERSION = $(GCC_MAJOR)$(GCC_MINOR)
endif

# -std=gnu99 needed for [U]LLONG_MAX on some systems
KBUILD_CPPFLAGS += $(call cc-option,-std=gnu99,)

KBUILD_CPPFLAGS += -D_GNU_SOURCE -DNDEBUG \
		   -D"SWU_VER=\"$(SWU_VER)\""

KBUILD_CFLAGS += $(call cc-option,-Wall,)
KBUILD_CFLAGS += $(call cc-option,-Wshadow,)
KBUILD_CFLAGS += $(call cc-option,-Wwrite-strings,)
KBUILD_CFLAGS += $(call cc-option,-Wundef,)
KBUILD_CFLAGS += $(call cc-option,-Wstrict-prototypes,)
KBUILD_CFLAGS += $(call cc-option,-Wunused -Wunused-parameter,)
KBUILD_CFLAGS += $(call cc-option,-Wunused-function -Wunused-value,)
KBUILD_CFLAGS += $(call cc-option,-Wmissing-prototypes -Wmissing-declarations,)
KBUILD_CFLAGS += $(call cc-option,-Wno-format-security,)
ifneq ($(CC),clang)
ifeq ($(shell test $(GCC_VERSION) -ge 70 && echo 1), 1)
KBUILD_CFLAGS += $(call cc-option,-Wno-format-truncation,)
endif
endif
# If you want to add more -Wsomething above, make sure that it is
# still possible to build bbox without warnings.

ifeq ($(CONFIG_WERROR),y)
KBUILD_CFLAGS += $(call cc-option,-Werror,)
## TODO:
## gcc version 4.4.0 20090506 (Red Hat 4.4.0-4) (GCC) is a PITA:
## const char *ptr; ... off_t v = *(off_t*)ptr; -> BOOM
## and no easy way to convince it to shut the hell up.
## We have a lot of such things all over the place.
## Classic *(off_t*)(void*)ptr does not work,
## and I am unwilling to do crazy gcc specific ({ void *ppp = ...; })
## stuff in macros. This would obfuscate the code too much.
## Maybe try __attribute__((__may_alias__))?
#KBUILD_CFLAGS += $(call cc-ifversion, -eq, 0404, -fno-strict-aliasing)
endif
# gcc 3.x emits bogus "old style proto" warning on find.c:alloc_action()
KBUILD_CFLAGS += $(call cc-ifversion, -ge, 0400, -Wold-style-definition)

ifneq ($(CC),clang)
KBUILD_CFLAGS += $(call cc-option, -finline-limit=0,)
endif
KBUILD_CFLAGS += $(call cc-option,-fno-builtin-strlen -fomit-frame-pointer -ffunction-sections -fdata-sections,)
# -fno-guess-branch-probability: prohibit pseudo-random guessing
# of branch probabilities (hopefully makes bloatcheck more stable):
KBUILD_CFLAGS += $(call cc-option,-fno-guess-branch-probability,)
KBUILD_CFLAGS += $(call cc-option,-funsigned-char,)
ifneq ($(CC),clang)
KBUILD_CFLAGS += $(call cc-option,-falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1 -static-libgcc,)
endif
# Defeat .eh_frame bloat (gcc 4.6.3 x86-32 defconfig: 20% smaller binary):
KBUILD_CFLAGS += $(call cc-option,-fno-unwind-tables,)
KBUILD_CFLAGS += $(call cc-option,-fno-asynchronous-unwind-tables,)

# FIXME: These warnings are at least partially to be concerned about and should
# be fixed..
#KBUILD_CFLAGS += $(call cc-option,-Wconversion,)

ifneq ($(CONFIG_DEBUG),y)
KBUILD_CFLAGS += $(call cc-option,-Os,$(call cc-option,-O2,))
else
KBUILD_CFLAGS += $(call cc-option,-g,)
#KBUILD_CFLAGS += "-D_FORTIFY_SOURCE=2"
ifeq ($(CONFIG_DEBUG_PESSIMIZE),y)
KBUILD_CFLAGS += $(call cc-option,-O0,)
else
KBUILD_CFLAGS += $(call cc-option,-Os,$(call cc-option,-O2,))
endif
endif

# Usage: $(eval $(call pkg_check_modules,VARIABLE-PREFIX,MODULES))
define pkg_check_modules
$(1)_CFLAGS := $(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --cflags $(2))
$(1)_LIBS := $(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --libs $(2))
$(1)_LDLIBS := $(patsubst -l%,%,$(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --libs-only-l $(2)))
endef

ifneq ($(CONFIG_EXTRA_CFLAGS),)
KBUILD_CFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_CFLAGS)))
#"))
endif

# Note: both "" (string consisting of two quote chars) and empty string
# are possible, and should be skipped below.
ifneq ($(subst "",,$(CONFIG_SYSROOT)),)
KBUILD_CFLAGS += --sysroot=$(CONFIG_SYSROOT)
export SYSROOT=$(CONFIG_SYSROOT)
endif

# Links always pthread
LDLIBS += pthread
# lua
ifneq ($(CONFIG_LUA),)
LDFLAGS_swupdate += -Wl,-E
$(eval $(call pkg_check_modules, LUABUILD, ${CONFIG_LUAPKG}))
KBUILD_CFLAGS += $(LUABUILD_CFLAGS)
KBUILD_LIBS += $(LUABUILD_LIBS)
LDLIBS += $(LUABUILD_LDLIBS)
LUAVER :=  $(shell $(PKG_CONFIG) $(PKG_CONFIG_FLAGS) --modversion ${CONFIG_LUAPKG} | cut -d'.' -f1,2)
endif

ifeq ($(CONFIG_LUA),y)
ifeq ($(CONFIG_HANDLER_IN_LUA),y)
ifeq ($(CONFIG_EMBEDDED_LUA_HANDLER),y)
ifneq ($(CONFIG_EMBEDDED_LUA_HANDLER_SOURCE),)
LDFLAGS_swupdate += -Wl,--format=binary -Wl,$(CONFIG_EMBEDDED_LUA_HANDLER_SOURCE) -Wl,--format=default
KBUILD_CPPFLAGS += -DEMBEDDED_LUA_SRC_START="_binary_$(subst ",,$(subst .,_,$(subst /,_,$(CONFIG_EMBEDDED_LUA_HANDLER_SOURCE))))_start"
KBUILD_CPPFLAGS += -DEMBEDDED_LUA_SRC_END="_binary_$(subst ",,$(subst .,_,$(subst /,_,$(CONFIG_EMBEDDED_LUA_HANDLER_SOURCE))))_end"
endif
endif
endif
endif

# Image downloading support
ifneq ($(CONFIG_CURL),)
LDLIBS += curl
endif

# libconfig is always compiled
ifeq ($(CONFIG_LIBCONFIG),y)
LDLIBS += config
endif

# libarchive
ifeq ($(CONFIG_ARCHIVE),y)
LDLIBS += archive
endif

# json-c
ifeq ($(CONFIG_JSON),y)
LDLIBS += json-c
endif

ifeq ($(CONFIG_SSL_IMPL_OPENSSL),y)
LDLIBS += crypto ssl
endif

ifeq ($(CONFIG_SSL_IMPL_WOLFSSL),y)
KBUILD_CPPFLAGS += -DOPENSSL_ALL
LDLIBS += wolfssl
else ifeq ($(CONFIG_PKCS11),y)
LDLIBS += wolfssl
endif

ifeq ($(CONFIG_PKCS11),y)
LDLIBS += p11-kit
endif

ifeq ($(CONFIG_SSL_IMPL_MBEDTLS),y)
LDLIBS += mbedcrypto mbedtls mbedx509
endif

# MTD
ifeq ($(CONFIG_MTD),y)
LDLIBS += ubi mtd
endif

ifeq ($(CONFIG_GUNZIP),y)
LDLIBS += z
endif

ifeq ($(CONFIG_ZSTD),y)
LDLIBS += zstd
endif

ifeq ($(CONFIG_DISKPART),y)
LDLIBS += fdisk
endif

ifeq ($(CONFIG_DISKFORMAT_HANDLER),y)
LDLIBS += blkid
endif

ifeq ($(CONFIG_EXT_FILESYSTEM),y)
LDLIBS += ext2fs uuid blkid
endif

ifeq ($(CONFIG_UNIQUEUUID),y)
LDLIBS += blkid
endif

ifeq ($(CONFIG_RDIFFHANDLER),y)
LDLIBS += rsync
endif

ifeq ($(CONFIG_REMOTE_HANDLER),y)
LDLIBS += zmq
endif

ifeq ($(CONFIG_UCFWHANDLER),y)
LDLIBS += gpiod
endif

ifeq ($(CONFIG_UBOOT),y)
LDLIBS += dl
endif

ifeq ($(CONFIG_SYSTEMD),y)
LDLIBS += systemd
endif

ifeq ($(CONFIG_BOOTLOADER_EBG),y)
LDLIBS += dl
endif

ifeq ($(CONFIG_BOOTLOADER_DEFAULT_NONE),y)
KBUILD_CPPFLAGS += -DBOOTLOADER_DEFAULT="none"
else ifeq ($(CONFIG_BOOTLOADER_DEFAULT_GRUB),y)
KBUILD_CPPFLAGS += -DBOOTLOADER_DEFAULT="grub"
else ifeq ($(CONFIG_BOOTLOADER_DEFAULT_UBOOT),y)
KBUILD_CPPFLAGS += -DBOOTLOADER_DEFAULT="uboot"
else ifeq ($(CONFIG_BOOTLOADER_DEFAULT_EBG),y)
KBUILD_CPPFLAGS += -DBOOTLOADER_DEFAULT="ebg"
else
KBUILD_CPPFLAGS += -DBOOTLOADER_DEFAULT="none"
endif

# SWU forwarder
ifneq ($(CONFIG_SWUFORWARDER_HANDLER),)
LDLIBS += websockets uriparser
endif

# Delta Update
ifneq ($(CONFIG_DELTA),)
LDLIBS += zck
endif

# If a flat binary should be built, CFLAGS_swupdate="-elf2flt"
# env var should be set for make invocation.
# Here we check whether CFLAGS_swupdate indeed contains that flag.
# (For historical reasons, we also check LDFLAGS, which doesn't
# seem to be entirely correct variable to put "-elf2flt" into).
W_ELF2FLT = -elf2flt
ifneq (,$(findstring $(W_ELF2FLT),$(LDFLAGS) $(CFLAGS_swupdate)))
SKIP_STRIP = y
endif

ifneq ($(CONFIG_EXTRA_LDFLAGS),)
EXTRA_LDFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_LDFLAGS)))
#"))
endif

ifneq ($(CONFIG_EXTRA_LDLIBS),)
LDLIBS += $(strip $(subst ",,$(CONFIG_EXTRA_LDLIBS)))
#"))
endif

# Busybox is a stack-fatty so make sure we increase default size
# TODO: use "make stksizes" to find & fix big stack users
# (we stole scripts/checkstack.pl from the kernel... thanks guys!)
# Reduced from 20k to 16k in 1.9.0.
FLTFLAGS += -s 16000
