# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2021-2022 , Chunguang Yang <yangchg@chinatelecom.cn>

SHELL := /usr/bin/env bash

include config.mak

# Set search path for all sources
VPATH = $(SRCDIR)

ARCH ?= $(shell uname -m | sed -e 's/i.86/i386/' \
    -e 's/armv[0-7]\w\+/arm/' \
    -e 's/aarch64/arm64/' \
    -e 's/ppc64le/powerpc/' \
)

ifeq ($(ARCH),x86_64)
    INSTALL_PATH = x86
else ifeq ($(ARCH),i386)
    INSTALL_PATH= x86
else ifeq ($(ARCH),arm)
    INSTALL_PATH = arm
else ifeq ($(ARCH),arm64)
    INSTALL_PATH = arm
else ifeq ($(ARCH),aarch64)
	INSTALL_PATH = arm
else
    INSTALL_PATH = $(ARCH)
endif


libdirs-get = $(shell [ -d "lib/$(1)" ] && echo "lib/$(1) lib/$(1)/asm")
ARCH_LIBDIRS := $(call libdirs-get,$(ARCH)) $(call libdirs-get,$(TEST_DIR))
OBJDIRS := $(ARCH_LIBDIRS)

DESTDIR := $(PREFIX)/share/kvm-unit-tests/

.PHONY: arch_clean clean distclean cscope

# cc-option
# Usage: OP_CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0)
cc-option = $(shell if $(CC) -Werror $(1) -S -o /dev/null -xc /dev/null \
              > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)

libcflat := lib/libcflat.a
cflatobjs := \
	lib/argv.o \
	lib/printf.o \
	lib/string.o \
	lib/abort.o \
	lib/report.o \
	lib/stack.o

# libfdt paths
LIBFDT_objdir = lib/libfdt
LIBFDT_srcdir = $(SRCDIR)/lib/libfdt
LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a

OBJDIRS += $(LIBFDT_objdir)

#include architecture specific make rules
include $(SRCDIR)/$(TEST_DIR)/Makefile

COMMON_CFLAGS += -Wignored-qualifiers -Wno-missing-braces $(CONFIG_WERROR)
COMMON_CFLAGS += -Wall -Wwrite-strings -Wempty-body -Wuninitialized
COMMON_CFLAGS += -g $(autodepend-flags) -fno-strict-aliasing -fno-common

frame-pointer-flag=-f$(if $(KEEP_FRAME_POINTER),no-,)omit-frame-pointer
fomit_frame_pointer := $(call cc-option, $(frame-pointer-flag), "")
fno_stack_protector := $(call cc-option, -fno-stack-protector, "")
fno_stack_protector_all := $(call cc-option, -fno-stack-protector-all, "")
wno_frame_address := $(call cc-option, -Wno-frame-address, "")
fno_pic := $(call cc-option, -fno-pic, "")
no_pie := $(call cc-option, -no-pie, "")
wclobbered := $(call cc-option, -Wclobbered, "")
wunused_but_set_parameter := $(call cc-option, -Wunused-but-set-parameter, "")
wmissing_parameter_type := $(call cc-option, -Wmissing-parameter-type, "")
wold_style_declaration := $(call cc-option, -Wold-style-declaration, "")

COMMON_CFLAGS += $(wunused_but_set_parameter)
COMMON_CFLAGS += $(wclobbered)
COMMON_CFLAGS += $(fno_pic)
COMMON_CFLAGS += $(if $(U32_LONG_FMT),-D__U32_LONG_FMT__,)
COMMON_CFLAGS += $(wno_frame_address)
COMMON_CFLAGS += $(fno_stack_protector_all)
COMMON_CFLAGS += $(fno_stack_protector)
COMMON_CFLAGS += $(fomit_frame_pointer)

CFLAGS += $(COMMON_CFLAGS)
CFLAGS += $(wold_style_declaration)
CFLAGS += $(wmissing_parameter_type)
CFLAGS += -Woverride-init -Wmissing-prototypes -Wstrict-prototypes

autodepend-flags = -MMD -MP -MF $(dir $*).$(notdir $*).d

LDFLAGS += -nostdlib $(no_pie) -z noexecstack

$(libcflat): $(cflatobjs)
	$(AR) rcs $@ $^

include $(LIBFDT_srcdir)/Makefile.libfdt
$(LIBFDT_archive): CFLAGS += -ffreestanding -I $(SRCDIR)/lib -I $(SRCDIR)/lib/libfdt -Wno-sign-compare
$(LIBFDT_archive): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
	$(AR) rcs $@ $^

libfdt_clean: SHAREDLIB_EXT = so
libfdt_clean: LIBFDT_dir = $(LIBFDT_objdir)
libfdt_clean: STD_CLEANFILES = *.o .*.d
libfdt_clean: VECHO = echo " "

# Build directory target
.PHONY: directories
directories:
	@mkdir -p $(OBJDIRS)

%.o: %.S
	$(CC) $(CFLAGS) -c -nostdlib -o $@ $<

-include */.*.d */*/.*.d

clean: arch_clean libfdt_clean
	$(RM) $(LIBFDT_archive)
	$(RM) lib/.*.d $(libcflat) $(cflatobjs)


install:
	mkdir -p $(DESTDIR)/$(INSTALL_PATH)
	install run.sh $(DESTDIR)
	install $(INSTALL_PATH)/*.flat $(DESTDIR)/$(INSTALL_PATH)
