# $(lastword,) for GNU Make older than 3.81
lastword = $(word $(words $(1)),$(1))
this-makefile := $(call lastword,$(MAKEFILE_LIST))

# This is the correct place to edit the build version.
# All other places this is stored (eg. compile.h) should be autogenerated.
export XEN_VERSION       = 4
export XEN_SUBVERSION    = 17
export XEN_EXTRAVERSION ?= .5$(XEN_VENDORVERSION)
export XEN_FULLVERSION   = $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION)
-include xen-version

export XEN_WHOAMI	?= $(USER)
ifeq ($(origin XEN_DOMAIN), undefined)
export XEN_DOMAIN	:= $(shell ([ -x /bin/dnsdomainname ] && /bin/dnsdomainname) || ([ -x /bin/domainname ] && /bin/domainname || echo [unknown]))
endif
ifeq ($(origin XEN_BUILD_DATE), undefined)
export XEN_BUILD_DATE	:= $(shell LC_ALL=C date)
endif
ifeq ($(origin XEN_BUILD_TIME), undefined)
export XEN_BUILD_TIME	:= $(shell LC_ALL=C date +%T)
endif
ifeq ($(origin XEN_BUILD_HOST), undefined)
export XEN_BUILD_HOST	:= $(shell hostname)
endif

# Best effort attempt to find a python interpreter, defaulting to Python 3 if
# available.  Fall back to just `python`.
PYTHON_INTERPRETER	:= $(word 1,$(shell command -v python3 || command -v python || command -v python2) python)
export PYTHON		?= $(PYTHON_INTERPRETER)

export CHECKPOLICY	?= checkpolicy

$(if $(filter __%, $(MAKECMDGOALS)), \
    $(error targets prefixed with '__' are only for internal use))

# That's our default target when none is given on the command line
PHONY := __all
__all:

# Do not use make's built-in rules and variables
MAKEFLAGS += -rR

EFI_MOUNTPOINT ?= $(BOOT_DIR)/efi

# Allow someone to change their config file
export KCONFIG_CONFIG ?= .config

export TARGET := xen

.PHONY: dist
dist: install

ifneq ($(root-make-done),y)
# section to run before calling Rules.mk, but only once.

ifneq ($(origin crash_debug),undefined)
$(error "You must use e.g. 'make menuconfig' to enable/disable crash_debug now.")
endif
ifeq ($(origin debug),command line)
$(warning "You must use e.g. 'make menuconfig' to enable/disable debug now.")
endif
ifneq ($(origin frame_pointer),undefined)
$(error "You must use e.g. 'make menuconfig' to enable/disable frame_pointer now.")
endif
ifneq ($(origin kexec),undefined)
$(error "You must use e.g. 'make menuconfig' to enable/disable kexec now.")
endif
ifneq ($(origin lock_profile),undefined)
$(error "You must use e.g. 'make menuconfig' to enable/disable lock_profile now.")
endif
ifneq ($(origin perfc),undefined)
$(error "You must use e.g. 'make menuconfig' to enable/disable perfc now.")
endif
ifneq ($(origin verbose),undefined)
$(error "You must use e.g. 'make menuconfig' to enable/disable verbose now.")
endif

# Beautify output
# ---------------------------------------------------------------------------
#
# Normally, we echo the whole command before executing it. By making
# that echo $($(quiet)$(cmd)), we now have the possibility to set
# $(quiet) to choose other forms of output instead, e.g.
#
#         quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
#         cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
#
# If $(quiet) is empty, the whole command will be printed.
# If it is set to "quiet_", only the short version will be printed.
# If it is set to "silent_", nothing will be printed at all, since
# the variable $(silent_cmd_cc_o_c) doesn't exist.
#
# A simple variant is to prefix commands with $(Q) - that's useful
# for commands that shall be hidden in non-verbose mode.
#
#	$(Q)ln $@ :<
#
# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
# If KBUILD_VERBOSE equals 1 then the above command is displayed.
#
# To put more focus on warnings, be less verbose as default
# Use 'make V=1' to see the full commands

ifeq ("$(origin V)", "command line")
    KBUILD_VERBOSE := $(V)
endif
ifndef KBUILD_VERBOSE
    KBUILD_VERBOSE := 0
endif

ifeq ($(KBUILD_VERBOSE),1)
    quiet :=
    Q :=
else
    quiet := quiet_
    Q := @
endif

# If the user is running make -s (silent mode), suppress echoing of
# commands

ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),)
    quiet := silent_
endif

export quiet Q KBUILD_VERBOSE

# $(realpath,) for GNU Make older than 3.81
realpath = $(wildcard $(foreach file,$(1),$(shell cd -P $(dir $(file)) && echo "$$PWD/$(notdir $(file))")))

ifeq ("$(origin O)", "command line")
    KBUILD_OUTPUT := $(O)
endif

ifneq ($(KBUILD_OUTPUT),)
# Make's built-in functions such as $(abspath ...), $(realpath ...) cannot
# expand a shell special character '~'. We use a somewhat tedious way here.
abs_objtree := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) && pwd)
$(if $(abs_objtree),, \
     $(error failed to create output directory "$(KBUILD_OUTPUT)"))

# $(realpath ...) resolves symlinks
abs_objtree := $(call realpath,$(abs_objtree))
else
abs_objtree := $(CURDIR)
endif

ifeq ($(abs_objtree),$(CURDIR))
# Suppress "Entering directory ..." unless we are changing the work directory.
MAKEFLAGS += --no-print-directory
else
need-sub-make := 1
endif

abs_srctree := $(call realpath,$(dir $(this-makefile)))

ifneq ($(words $(subst :, ,$(abs_srctree))), 1)
$(error source directory cannot contain spaces or colons)
endif

ifneq ($(abs_srctree),$(abs_objtree))
# Look for make include files relative to root of kernel src
#
# This does not become effective immediately because MAKEFLAGS is re-parsed
# once after the Makefile is read. We need to invoke sub-make.
MAKEFLAGS += --include-dir=$(abs_srctree)
need-sub-make := 1
endif

export abs_srctree abs_objtree
export root-make-done := y

ifeq ($(need-sub-make),1)

PHONY += $(MAKECMDGOALS) __sub-make

$(filter-out $(this-makefile), $(MAKECMDGOALS)) __all: __sub-make
	@:

# Invoke a second make in the output directory, passing relevant variables
__sub-make:
	$(Q)$(MAKE) -C $(abs_objtree) -f $(abs_srctree)/Makefile $(MAKECMDGOALS)

endif # need-sub-make
endif # root-make-done

# We process the rest of the Makefile if this is the final invocation of make
ifeq ($(need-sub-make),)

# Do not print "Entering directory ...",
# but we want to display it when entering to the output directory
# so that IDEs/editors are able to understand relative filenames.
MAKEFLAGS += --no-print-directory

ifeq ($(abs_srctree),$(abs_objtree))
    # building in the source tree
    srctree := .
    building_out_of_srctree :=
else
    ifeq ($(abs_srctree)/,$(dir $(abs_objtree)))
        # building in a subdirectory of the source tree
        srctree := ..
    else
        srctree := $(abs_srctree)
    endif
    building_out_of_srctree := 1
endif

objtree := .
VPATH := $(srctree)

export building_out_of_srctree srctree objtree VPATH

export XEN_ROOT := $(abs_srctree)/..

# To make sure we do not include .config for any of the *config targets
# catch them early, and hand them over to tools/kconfig/Makefile

clean-targets := %clean
no-dot-config-targets := $(clean-targets) \
                         uninstall debug cloc \
                         cscope TAGS tags gtags \
                         xenversion

config-build    := n
need-config     := y

ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
    ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
        need-config := n
    endif
endif

ifneq ($(filter %config,$(MAKECMDGOALS)),)
    config-build := y
endif

include scripts/Kbuild.include

# Don't break if the build process wasn't called from the top level
# we need XEN_TARGET_ARCH to generate the proper config
include $(XEN_ROOT)/Config.mk

# Set ARCH/SRCARCH appropriately.

ARCH := $(XEN_TARGET_ARCH)
SRCARCH := $(shell echo $(ARCH) | \
    sed -e 's/x86.*/x86/' -e 's/arm\(32\|64\)/arm/g' \
        -e 's/riscv.*/riscv/g')
export ARCH SRCARCH

export CONFIG_SHELL := $(SHELL)
export CC CXX LD NM OBJCOPY OBJDUMP ADDR2LINE
export YACC = $(if $(BISON),$(BISON),bison)
export LEX = $(if $(FLEX),$(FLEX),flex)

# Default file for 'make defconfig'.
export KBUILD_DEFCONFIG := $(ARCH)_defconfig

# Copy CFLAGS generated by "Config.mk" so they can be reused later without
# reparsing Config.mk by e.g. arch/x86/boot/.
export XEN_TREEWIDE_CFLAGS := $(CFLAGS)

# CLANG_FLAGS needs to be calculated before calling Kconfig
ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
CLANG_FLAGS :=

ifeq ($(SRCARCH),x86)
# The tests to select whether the integrated assembler is usable need to happen
# before testing any assembler features, or else the result of the tests would
# be stale if the integrated assembler is not used.

# Older clang's built-in assembler doesn't understand .skip with labels:
# https://bugs.llvm.org/show_bug.cgi?id=27369
t1 = $(call as-insn,$(CC),".L0: .L1: .skip (.L1 - .L0)",,-no-integrated-as)

# Check whether clang asm()-s support .include.
t2 = $(call as-insn,$(CC) -I$(srctree)/arch/x86/include,".include \"asm/asm-defns.h\"",,-no-integrated-as)

# Check whether clang keeps .macro-s between asm()-s:
# https://bugs.llvm.org/show_bug.cgi?id=36110
t3 = $(call as-insn,$(CC),".macro FOO;.endm"$(close); asm volatile $(open)".macro FOO;.endm",-no-integrated-as)

CLANG_FLAGS += $(call or,$(t1),$(t2),$(t3))
endif

CLANG_FLAGS += -Werror=unknown-warning-option
CFLAGS += $(CLANG_FLAGS)
export CLANG_FLAGS
endif

export XEN_HAS_CHECKPOLICY := $(call success,$(CHECKPOLICY) -h 2>&1 | grep -q xen)

# ===========================================================================
# Rules shared between *config targets and build targets

PHONY += tools_fixdep
tools_fixdep:
	$(Q)$(MAKE) $(build)=tools tools/fixdep

PHONY += outputmakefile
# Before starting out-of-tree build, make sure the source tree is clean.
# outputmakefile generates a Makefile in the output directory, if using a
# separate output directory. This allows convenient use of make in the
# output directory.
# At the same time when output Makefile generated, generate .gitignore to
# ignore whole output directory

quiet_cmd_makefile = GEN     Makefile
cmd_makefile = { \
    echo "\# Automatically generated by $(srctree)/Makefile: don't edit"; \
    echo "include $(srctree)/Makefile"; \
    } > Makefile

outputmakefile:
	$(Q)ln -fsn $(srctree) source
ifdef building_out_of_srctree
	$(Q)if [ -f $(srctree)/.config -o \
		 -d $(srctree)/include/config -o \
		 -d $(srctree)/include/generated ]; then \
		echo >&2 "***"; \
		echo >&2 "*** The source tree is not clean, please run 'make$(if $(findstring command line, $(origin XEN_TARGET_ARCH)), XEN_TARGET_ARCH=$(XEN_TARGET_ARCH)) distclean'"; \
		echo >&2 "*** in $(abs_srctree)";\
		echo >&2 "***"; \
		false; \
	fi
	$(call cmd,makefile)
	$(Q)test -e .gitignore || \
	{ echo "# this is build directory, ignore it"; echo "*"; } > .gitignore
endif

ifeq ($(config-build),y)
# ===========================================================================
# *config targets only - make sure prerequisites are updated, and descend
# in tools/kconfig to make the *config target

# Create a file for KCONFIG_ALLCONFIG which depends on the environment.
# This will be use by kconfig targets allyesconfig/allmodconfig/allnoconfig/randconfig
filechk_kconfig_allconfig = \
    $(if $(findstring n,$(XEN_HAS_CHECKPOLICY)), echo 'CONFIG_XSM_FLASK_POLICY=n';) \
    $(if $(KCONFIG_ALLCONFIG), cat $(KCONFIG_ALLCONFIG);) \
    :

.allconfig.tmp: FORCE
	set -e; { $(call filechk_kconfig_allconfig); } > $@

config: tools_fixdep outputmakefile FORCE
	$(Q)$(MAKE) $(build)=tools/kconfig $@

# Config.mk tries to include .config file, don't try to remake it
%/.config: ;

%config: .allconfig.tmp tools_fixdep outputmakefile FORCE
	$(Q)$(MAKE) $(build)=tools/kconfig KCONFIG_ALLCONFIG=$< $@

else # !config-build

ifeq ($(need-config),y)
-include include/config/auto.conf
# Read in dependencies to all Kconfig* files, make sure to run syncconfig if
# changes are detected.
-include include/config/auto.conf.cmd

# Allow people to just run `make` as before and not force them to configure
# Only run defconfig if $(KCONFIG_CONFIG) is missing
$(KCONFIG_CONFIG): tools_fixdep
	$(if $(wildcard $@), , $(Q)$(MAKE) $(build)=tools/kconfig defconfig)

# The actual configuration files used during the build are stored in
# include/generated/ and include/config/. Update them if .config is newer than
# include/config/auto.conf (which mirrors .config).
#
# This exploits the 'multi-target pattern rule' trick.
# The syncconfig should be executed only once to make all the targets.
include/config/%.conf include/config/%.conf.cmd: $(KCONFIG_CONFIG)
	$(Q)rm -f include/config/auto.conf
	$(Q)$(MAKE) $(build)=tools/kconfig syncconfig

ifeq ($(CONFIG_DEBUG),y)
CFLAGS += -O1
else
CFLAGS += -O2
endif

ifeq ($(CONFIG_FRAME_POINTER),y)
CFLAGS += -fno-omit-frame-pointer
else
CFLAGS += -fomit-frame-pointer
endif

CFLAGS-$(CONFIG_CC_SPLIT_SECTIONS) += -ffunction-sections -fdata-sections

CFLAGS += -nostdinc -fno-builtin -fno-common
CFLAGS += -Werror -Wredundant-decls -Wno-pointer-arith
CFLAGS += -Wdeclaration-after-statement
$(call cc-option-add,CFLAGS,CC,-Wvla)
CFLAGS += -pipe -D__XEN__ -include $(srctree)/include/xen/config.h
CFLAGS-$(CONFIG_DEBUG_INFO) += -g

ifneq ($(CONFIG_CC_IS_CLANG),y)
# Clang doesn't understand this command line argument, and doesn't appear to
# have a suitable alternative.  The resulting compiled binary does function,
# but has an excessively large symbol table.
CFLAGS += -Wa,--strip-local-absolute
endif

AFLAGS += -D__ASSEMBLY__

$(call cc-option-add,AFLAGS,CC,-Wa$$(comma)--noexecstack)

LDFLAGS-$(call ld-option,--warn-rwx-segments) += --no-warn-rwx-segments

CFLAGS += $(CFLAGS-y)
# allow extra CFLAGS externally via EXTRA_CFLAGS_XEN_CORE
CFLAGS += $(EXTRA_CFLAGS_XEN_CORE)

# Most CFLAGS are safe for assembly files:
#  -std=gnu{89,99} gets confused by #-prefixed end-of-line comments
#  -flto makes no sense and annoys clang
AFLAGS += $(filter-out -std=gnu% -flto,$(CFLAGS)) $(AFLAGS-y)

# LDFLAGS are only passed directly to $(LD)
LDFLAGS += $(LDFLAGS_DIRECT) $(LDFLAGS-y)

ifeq ($(CONFIG_UBSAN),y)
CFLAGS_UBSAN := -fsanitize=undefined
else
CFLAGS_UBSAN :=
endif

ifeq ($(CONFIG_LTO),y)
CFLAGS += -flto
LDFLAGS-$(CONFIG_CC_IS_CLANG) += -plugin LLVMgold.so
endif

ifdef building_out_of_srctree
    CFLAGS += -I$(objtree)/include
    CFLAGS += -I$(objtree)/arch/$(SRCARCH)/include
endif
CFLAGS += -I$(srctree)/include
CFLAGS += -I$(srctree)/arch/$(SRCARCH)/include

# Note that link order matters!
ALL_OBJS-y                := common/built_in.o
ALL_OBJS-y                += drivers/built_in.o
ALL_OBJS-y                += lib/built_in.o
ALL_OBJS-y                += xsm/built_in.o
ALL_OBJS-y                += arch/$(SRCARCH)/built_in.o
ALL_OBJS-$(CONFIG_CRYPTO) += crypto/built_in.o

ALL_LIBS-y                := lib/lib.a

include $(srctree)/arch/$(SRCARCH)/arch.mk

# define new variables to avoid the ones defined in Config.mk
export XEN_CFLAGS := $(CFLAGS)
export XEN_AFLAGS := $(AFLAGS)
export XEN_LDFLAGS := $(LDFLAGS)
export CFLAGS_UBSAN

endif # need-config

__all: build

main-targets := build install uninstall clean distclean MAP cppcheck cppcheck-html
.PHONY: $(main-targets)
ifneq ($(XEN_TARGET_ARCH),x86_32)
$(main-targets): %: _% ;
else
$(main-targets):
	echo "*** Xen x86/32 target no longer supported!"
endif

.PHONY: _build
_build: $(TARGET)$(CONFIG_XEN_INSTALL_SUFFIX)

# Strip
#
# INSTALL_EFI_STRIP, if defined, will cause xen.efi to be stripped before it
# is installed. If INSTALL_EFI_STRIP is '1', then the default option(s) below
# will be used. Otherwise, INSTALL_EFI_STRIP value will be used as the
# option(s) to the strip command.
ifdef INSTALL_EFI_STRIP

ifeq ($(INSTALL_EFI_STRIP),1)
efi-strip-opt := --strip-debug --keep-file-symbols
else
efi-strip-opt := $(INSTALL_EFI_STRIP)
endif

endif

.PHONY: _install
_install: D=$(DESTDIR)
_install: T=$(notdir $(TARGET))
_install: Z=$(CONFIG_XEN_INSTALL_SUFFIX)
_install: $(TARGET)$(CONFIG_XEN_INSTALL_SUFFIX)
	[ -d $(D)$(BOOT_DIR) ] || $(INSTALL_DIR) $(D)$(BOOT_DIR)
	$(INSTALL_DATA) $(TARGET)$(Z) $(D)$(BOOT_DIR)/$(T)-$(XEN_FULLVERSION)$(Z)
	ln -f -s $(T)-$(XEN_FULLVERSION)$(Z) $(D)$(BOOT_DIR)/$(T)-$(XEN_VERSION).$(XEN_SUBVERSION)$(Z)
	ln -f -s $(T)-$(XEN_FULLVERSION)$(Z) $(D)$(BOOT_DIR)/$(T)-$(XEN_VERSION)$(Z)
	ln -f -s $(T)-$(XEN_FULLVERSION)$(Z) $(D)$(BOOT_DIR)/$(T)$(Z)
	[ -d "$(D)$(DEBUG_DIR)" ] || $(INSTALL_DIR) $(D)$(DEBUG_DIR)
	$(INSTALL_DATA) $(TARGET)-syms $(D)$(DEBUG_DIR)/$(T)-syms-$(XEN_FULLVERSION)
	$(INSTALL_DATA) $(TARGET)-syms.map $(D)$(DEBUG_DIR)/$(T)-syms-$(XEN_FULLVERSION).map
	$(INSTALL_DATA) $(KCONFIG_CONFIG) $(D)$(BOOT_DIR)/$(T)-$(XEN_FULLVERSION).config
	if [ -r $(TARGET).efi -a -n '$(EFI_DIR)' ]; then \
		[ -d $(D)$(EFI_DIR) ] || $(INSTALL_DIR) $(D)$(EFI_DIR); \
		$(INSTALL_DATA) $(TARGET).efi $(D)$(EFI_DIR)/$(T)-$(XEN_FULLVERSION).efi; \
		if [ -e $(TARGET).efi.map ]; then \
			$(INSTALL_DATA) $(TARGET).efi.map $(D)$(DEBUG_DIR)/$(T)-$(XEN_FULLVERSION).efi.map; \
		fi; \
		ln -sf $(T)-$(XEN_FULLVERSION).efi $(D)$(EFI_DIR)/$(T)-$(XEN_VERSION).$(XEN_SUBVERSION).efi; \
		ln -sf $(T)-$(XEN_FULLVERSION).efi $(D)$(EFI_DIR)/$(T)-$(XEN_VERSION).efi; \
		ln -sf $(T)-$(XEN_FULLVERSION).efi $(D)$(EFI_DIR)/$(T).efi; \
		if [ -n '$(EFI_MOUNTPOINT)' -a -n '$(EFI_VENDOR)' ]; then \
			$(if $(efi-strip-opt), \
			     $(STRIP) $(efi-strip-opt) -p -o $(TARGET).efi.stripped $(TARGET).efi && \
			     $(INSTALL_DATA) $(TARGET).efi.stripped $(D)$(EFI_MOUNTPOINT)/efi/$(EFI_VENDOR)/$(T)-$(XEN_FULLVERSION).efi ||) \
			$(INSTALL_DATA) $(TARGET).efi $(D)$(EFI_MOUNTPOINT)/efi/$(EFI_VENDOR)/$(T)-$(XEN_FULLVERSION).efi; \
		elif [ "$(D)" = "$(patsubst $(shell cd $(XEN_ROOT) && pwd)/%,%,$(D))" ]; then \
			echo 'EFI installation only partially done (EFI_VENDOR not set)' >&2; \
		fi; \
	fi

.PHONY: tests
tests:
	$(Q)$(MAKE) $(build)=test
.PHONY: install-tests
install-tests:
	$(Q)$(MAKE) $(build)=test install

.PHONY: _uninstall
_uninstall: D=$(DESTDIR)
_uninstall: T=$(notdir $(TARGET))
_uninstall: Z=$(CONFIG_XEN_INSTALL_SUFFIX)
_uninstall:
	rm -f $(D)$(BOOT_DIR)/$(T)-$(XEN_FULLVERSION).config
	rm -f $(D)$(BOOT_DIR)/$(T)-$(XEN_FULLVERSION)$(Z)
	rm -f $(D)$(BOOT_DIR)/$(T)-$(XEN_VERSION).$(XEN_SUBVERSION)$(Z)
	rm -f $(D)$(BOOT_DIR)/$(T)-$(XEN_VERSION)$(Z)
	rm -f $(D)$(BOOT_DIR)/$(T)$(Z)
	rm -f $(D)$(DEBUG_DIR)/$(T)-syms-$(XEN_FULLVERSION)
	rm -f $(D)$(DEBUG_DIR)/$(T)-syms-$(XEN_FULLVERSION).map
	rm -f $(D)$(EFI_DIR)/$(T)-$(XEN_FULLVERSION).efi
	rm -f $(D)$(EFI_DIR)/$(T)-$(XEN_VERSION).$(XEN_SUBVERSION).efi
	rm -f $(D)$(DEBUG_DIR)/$(T)-$(XEN_FULLVERSION).efi.map
	rm -f $(D)$(EFI_DIR)/$(T)-$(XEN_VERSION).efi
	rm -f $(D)$(EFI_DIR)/$(T).efi
	if [ -n '$(EFI_MOUNTPOINT)' -a -n '$(EFI_VENDOR)' ]; then \
		rm -f $(D)$(EFI_MOUNTPOINT)/efi/$(EFI_VENDOR)/$(T)-$(XEN_FULLVERSION).efi; \
	fi

.PHONY: _debug
_debug:
	$(OBJDUMP) -D -S $(TARGET)-syms > $(TARGET).s

.PHONY: _clean
_clean:
	$(Q)$(MAKE) $(clean)=tools
	$(Q)$(MAKE) $(clean)=include
	$(Q)$(MAKE) $(clean)=common
	$(Q)$(MAKE) $(clean)=drivers
	$(Q)$(MAKE) $(clean)=lib
	$(Q)$(MAKE) $(clean)=xsm
	$(Q)$(MAKE) $(clean)=crypto
	$(Q)$(MAKE) $(clean)=arch/arm
	$(Q)$(MAKE) $(clean)=arch/riscv
	$(Q)$(MAKE) $(clean)=arch/x86
	$(Q)$(MAKE) $(clean)=test
	$(Q)$(MAKE) $(clean)=tools/kconfig
	find . \( -name "*.o" -o -name ".*.d" -o -name ".*.d2" \
		-o -name ".*.o.tmp" -o -name "*~" -o -name "core" \
		-o -name '*.lex.c' -o -name '*.tab.[ch]' -o -name '*.c.cppcheck' \
		-o -name "*.gcno" -o -name ".*.cmd" -o -name "lib.a" \) -exec rm -f {} \;
	rm -f include/asm $(TARGET) $(TARGET).gz $(TARGET)-syms $(TARGET)-syms.map
	rm -f $(TARGET).efi $(TARGET).efi.map $(TARGET).efi.stripped
	rm -f asm-offsets.s arch/*/include/asm/asm-offsets.h
	rm -f .banner .allconfig.tmp include/xen/compile.h
	rm -f cppcheck-misra.* xen-cppcheck.xml

.PHONY: _distclean
_distclean: clean
	rm -f tags TAGS cscope.files cscope.in.out cscope.out cscope.po.out GTAGS GPATH GRTAGS GSYMS .config source
	rm -rf $(CPPCHECK_HTMLREPORT_OUTDIR)

$(TARGET).gz: $(TARGET)
	gzip -n -f -9 < $< > $@.new
	mv $@.new $@

$(TARGET): outputmakefile FORCE
	$(Q)$(MAKE) $(build)=tools
	$(Q)$(MAKE) $(build)=. include/xen/compile.h
	$(Q)$(MAKE) $(build)=include all
	$(Q)$(MAKE) $(build)=arch/$(SRCARCH) include
	$(Q)$(MAKE) $(build)=. arch/$(SRCARCH)/include/asm/asm-offsets.h
	$(Q)$(MAKE) $(build)=. MKRELOC=$(MKRELOC) 'ALL_OBJS=$(ALL_OBJS-y)' 'ALL_LIBS=$(ALL_LIBS-y)' $@

SUBDIRS = xsm arch/$(SRCARCH) common drivers lib test
define all_sources
    ( find include -type f -name '*.h' -print; \
      find $(SUBDIRS) -type f -name '*.[chS]' -print )
endef

define set_exuberant_flags
    exuberant_flags=`$1 --version 2>/dev/null | (grep -iq exuberant && \
	echo "-I __initdata,__exitdata,__acquires,__releases \
	    -I EXPORT_SYMBOL \
	    --extra=+f --c-kinds=+px") || true` 
endef

.PHONY: xenversion
xenversion:
	@echo $(XEN_FULLVERSION)

.PHONY: TAGS
TAGS:
	set -e; rm -f TAGS; \
	$(call set_exuberant_flags,etags); \
	$(all_sources) | xargs etags $$exuberant_flags -a

.PHONY: tags
tags:
	set -e; rm -f tags; \
	$(call set_exuberant_flags,ctags); \
	$(all_sources) | xargs ctags $$exuberant_flags -a

.PHONY: gtags
gtags:
	set -e; rm -f GTAGS GSYMS GPATH GRTAGS
	$(all_sources) | gtags -f -

.PHONY: cscope
cscope:
	$(all_sources) > cscope.files
	cscope -k -b -q

.PHONY: _MAP
_MAP: $(TARGET)
	$(NM) -n $(TARGET)-syms | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' > System.map

%.o %.i %.s: %.c tools_fixdep FORCE
	$(Q)$(MAKE) $(build)=$(*D) $(*D)/$(@F)

%.o %.s: %.S tools_fixdep FORCE
	$(Q)$(MAKE) $(build)=$(*D) $(*D)/$(@F)

%/: tools_fixdep FORCE
	$(Q)$(MAKE) $(build)=$* need-builtin=1

.PHONY: cloc
cloc:
	find . -name tools -prune -o -name '*.o.cmd' -print | while read f; do \
	    for sf in $$(grep -o "[a-zA-Z0-9_/-]*\.[cS]" $$f); do \
		test -f "$$sf" && echo "$$sf"; \
	    done; \
	done | cloc --list-file=-

# What cppcheck command to use.
# To get proper results, it is recommended to build cppcheck manually from the
# latest source and use CPPCHECK to give the full path to the built version.
CPPCHECK ?= cppcheck

# What cppcheck-htmlreport to use.
# If you give the full path to a self compiled cppcheck, this should be set
# to the full path to cppcheck-html in the htmlreport directory of cppcheck.
# On recent distribution, this is available in the standard path.
CPPCHECK_HTMLREPORT ?= cppcheck-htmlreport

# By default we generate the report in cppcheck-htmlreport directory in the
# build directory. This can be changed by giving a directory in this variable.
CPPCHECK_HTMLREPORT_OUTDIR ?= cppcheck-htmlreport

# By default we do not check misra rules, to enable pass "CPPCHECK_MISRA=y" to
# make command line.
CPPCHECK_MISRA ?= n

# Compile flags to pass to cppcheck:
# - include directories and defines Xen Makefile is passing (from CFLAGS)
# - include config.h as this is passed directly to the compiler.
# - define CPPCHECK as we use to disable or enable some specific part of the
#   code to solve some cppcheck issues.
# - explicitely enable some cppcheck checks as we do not want to use "all"
#   which includes unusedFunction which gives wrong positives as we check file
#   per file.
#
# Compiler defines are in compiler-def.h which is included in config.h
#
CPPCHECKFLAGS := -DCPPCHECK --max-ctu-depth=10 \
                 --enable=style,information,missingInclude \
                 --include=$(srctree)/include/xen/config.h \
                 -I $(srctree)/xsm/flask/include \
                 -I $(srctree)/include/xen/libfdt \
                 $(filter -D% -I%,$(CFLAGS))

# We need to find all C files (as we are not checking assembly files) so
# we find all generated .o files which have a .c corresponding file.
CPPCHECKFILES := $(wildcard $(patsubst $(objtree)/%.o,$(srctree)/%.c, \
                 $(filter-out $(objtree)/tools/%, \
                 $(shell find $(objtree) -name "*.o"))))

# Headers and files required to run cppcheck on a file
CPPCHECKDEPS := $(objtree)/include/generated/autoconf.h \
                $(objtree)/include/generated/compiler-def.h

ifeq ($(CPPCHECK_MISRA),y)
    CPPCHECKFLAGS += --addon=cppcheck-misra.json
    CPPCHECKDEPS += cppcheck-misra.json
endif

quiet_cmd_cppcheck_xml = CPPCHECK $(patsubst $(srctree)/%,%,$<)
cmd_cppcheck_xml = $(CPPCHECK) -v -q --xml $(CPPCHECKFLAGS) \
                   --output-file=$@ $<

quiet_cmd_merge_cppcheck_reports = CPPCHECK-MERGE $@
cmd_merge_cppcheck_reports = $(PYTHON) $(srctree)/tools/merge_cppcheck_reports.py $^ $@

quiet_cmd_cppcheck_html = CPPCHECK-HTML $<
cmd_cppcheck_html = $(CPPCHECK_HTMLREPORT) --file=$< --source-dir=$(srctree) \
                    --report-dir=$(CPPCHECK_HTMLREPORT_OUTDIR) --title=Xen

PHONY += _cppcheck _cppcheck-html cppcheck-version

_cppcheck-html: xen-cppcheck.xml
	$(call if_changed,cppcheck_html)

_cppcheck: xen-cppcheck.xml

xen-cppcheck.xml: $(patsubst $(srctree)/%.c,$(objtree)/%.c.cppcheck,$(CPPCHECKFILES))
ifeq ($(CPPCHECKFILES),)
	$(error Please build Xen before running cppcheck)
endif
	$(call if_changed,merge_cppcheck_reports)

$(objtree)/%.c.cppcheck: $(srctree)/%.c $(CPPCHECKDEPS) | cppcheck-version
	$(call if_changed,cppcheck_xml)

cppcheck-version:
	$(Q)if ! which $(CPPCHECK) > /dev/null 2>&1; then \
		echo "Cannot find cppcheck executable: $(CPPCHECK)"; \
		exit 1; \
	fi
	$(Q)if [ "$$($(CPPCHECK) --version | awk '{print ($$2 < 2.7)}')" -eq 1 ]; then \
		echo "Please upgrade your cppcheck to version 2.7 or greater"; \
		exit 1; \
	fi

# List of Misra rules to respect is written inside a doc.
# In order to have some helpful text in the cppcheck output, generate a text
# file containing the rules identifier, classification and text from the Xen
# documentation file. Also generate a json file with the right arguments for
# cppcheck in json format including the list of rules to ignore.
#
# convert_misra_doc.py, producing both targets at the same time, should be
# executed only once. Utilize a pattern rule to achieve this effect, with the
# stem kind of arbitrarily chosen to be "cppcheck".
.PRECIOUS: %-misra.json
%-misra.txt %-misra.json: $(XEN_ROOT)/docs/misra/rules.rst $(srctree)/tools/convert_misra_doc.py
	$(Q)$(PYTHON) $(srctree)/tools/convert_misra_doc.py -i $< -o $*-misra.txt -j $*-misra.json

# Put this in generated headers this way it is cleaned by include/Makefile
$(objtree)/include/generated/compiler-def.h:
	$(Q)$(CC) -dM -E -o $@ - < /dev/null

endif #config-build
endif # need-sub-make

PHONY += FORCE
FORCE:

# Declare the contents of the PHONY variable as phony.  We keep that
# information in a variable so we can use it in if_changed and friends.
.PHONY: $(PHONY)
