#
# Makefile
#
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: 2026 Zeepunt

Q := @

ifeq ($(V),1)
	quiet =
	cmd = $(cmd_$(1))
else
	quiet = quiet_
	cmd = $(Q)$(if $(quiet_cmd_$(1)),echo '  $(quiet_cmd_$(1))' &&) $(cmd_$(1))
endif

BUILD_DIR := build

TARGET    := main

CC_PREFIX :=
AS        := $(CC_PREFIX)as
CC        := $(CC_PREFIX)gcc
LD        := $(CC_PREFIX)ld
NM        := $(CC_PREFIX)nm
AR        := $(CC_PREFIX)ar
OBJCOPY   := $(CC_PREFIX)objcopy
OBJDUMP   := $(CC_PREFIX)objdump
SIZE      := $(CC_PREFIX)size
STRIP     := $(CC_PREFIX)strip

ELF := $(BUILD_DIR)/$(TARGET).elf
MAP := $(BUILD_DIR)/$(TARGET).map

CFLAGS := \
	-std=c11 \
	-g \
	-O0

CFLAGS += \
	-fdata-sections \
	-ffunction-sections

# _DEFAULT_SOURCE 用于开启 glibc 的所有扩展声明
# MSYS2 的 libc 没有 MAP_32BIT, 这里需要添加
CFLAGS += \
	-D_GNU_SOURCE \
	-DMAP_32BIT=0

LDFLAGS := \
	-Wl,-Map=$(MAP) \
	-Wl,--gc-sections \
	-Wl,--print-memory-usage

LDLIBS :=

####################################################################################
WAMR_ROOT   := wasm-micro-runtime
WAMR_CORE   := $(WAMR_ROOT)/core

IWASM_DIR   := $(WAMR_CORE)/iwasm
SHARED_DIR  := $(WAMR_CORE)/shared

# WAMR compilation flags

## interpreter
WAMR_BUILD_INTERP                ?= 1
## fast interpreter
WAMR_BUILD_FAST_INTERP           ?= 1
## mini loader
WAMR_BUILD_MINI_LOADER           ?= 0

## garbage collection
WAMR_BUILD_GC                    ?= 0
## String reference support
WAMR_BUILD_STRINGREF             ?= 0
## reference types
WAMR_BUILD_REF_TYPES             ?= 0

## AoT runtime
WAMR_BUILD_AOT                   ?= 0
## AoT validator
WAMR_BUILD_AOT_VALIDATOR         ?= 0

## JIT compilation
WAMR_BUILD_JIT                   ?= 0
## fast JIT
WAMR_BUILD_FAST_JIT              ?= 0
## fast JIT dump
WAMR_BUILD_FAST_JIT_DUMP         ?= 0

# libc builtin functions
WAMR_BUILD_LIBC_BUILTIN          ?= 1
# libc uvwasi compatibility
WAMR_BUILD_LIBC_UVWASI           ?= 0
# wasi libc
WAMR_BUILD_LIBC_WASI             ?= 1
# module instance context
WAMR_BUILD_MODULE_INST_CONTEXT   ?= 0

# multi-module support
WAMR_BUILD_MULTI_MODULE          ?= 0

# copy call stack
WAMR_BUILD_COPY_CALL_STACK       ?= 0

## SIMD support
WAMR_BUILD_SIMD                  ?= 1

## pthread library
WAMR_BUILD_LIB_PTHREAD           ?= 0
## pthread semaphore support
WAMR_BUILD_LIB_PTHREAD_SEMAPHORE ?= 0

## wasi threads
WAMR_BUILD_LIB_WASI_THREADS      ?= 0

## debug interpreter
WAMR_BUILD_DEBUG_INTERP          ?= 0

ifneq ($(filter 1,$(WAMR_BUILD_FAST_JIT) $(WAMR_BUILD_JIT)),)
WAMR_BUILD_INTERP      := 1
WAMR_BUILD_FAST_INTERP := 0
endif

ifeq ($(WAMR_BUILD_JIT),1)
WAMR_BUILD_AOT := 1
endif

ifeq ($(WAMR_BUILD_STRINGREF),1)
WAMR_BUILD_GC := 1
endif

ifeq ($(WAMR_BUILD_GC),1)
WAMR_BUILD_REF_TYPES := 1
endif

ifeq ($(WAMR_BUILD_LIBC_UVWASI),1)
CFLAGS += -DWASM_ENABLE_MODULE_INST_CONTEXT=1

WAMR_BUILD_MODULE_INST_CONTEXT := 1
else ifeq ($(WAMR_BUILD_LIBC_WASI),1)
CFLAGS += -DWASM_ENABLE_MODULE_INST_CONTEXT=1

WAMR_BUILD_MODULE_INST_CONTEXT := 1
endif

ifeq ($(WAMR_BUILD_LIB_PTHREAD_SEMAPHORE),1)
WAMR_BUILD_LIB_PTHREAD := 1
endif

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

# WAMR iwasm
IWASM_INCLUDE := -I$(IWASM_DIR)/include
IWASM_SOURCE  :=

## common
WAMR_DISABLE_APP_ENTRY           ?= 0
WAMR_BUILD_INVOKE_NATIVE_GENERAL ?= 0

IWASM_INCLUDE += -I$(IWASM_DIR)/common

CFLAGS += -DBH_MALLOC=wasm_runtime_malloc
CFLAGS += -DBH_FREE=wasm_runtime_free

IWASM_SOURCE += \
	$(IWASM_DIR)/common/wasm_blocking_op.c \
	$(IWASM_DIR)/common/wasm_c_api.c \
	$(IWASM_DIR)/common/wasm_exec_env.c \
	$(IWASM_DIR)/common/wasm_loader_common.c \
	$(IWASM_DIR)/common/wasm_memory.c \
	$(IWASM_DIR)/common/wasm_native.c \
	$(IWASM_DIR)/common/wasm_runtime_common.c \
	$(IWASM_DIR)/common/wasm_shared_memory.c

ifeq ($(WAMR_BUILD_INTERP),1)
IWASM_SOURCE += $(IWASM_DIR)/common/wasm_application.c
endif

ifeq ($(WAMR_BUILD_INVOKE_NATIVE_GENERAL),1)
IWASM_SOURCE += $(IWASM_DIR)/common/arch/invokeNative_general.c
else
ifeq ($(WAMR_BUILD_SIMD),1)
IWASM_SOURCE += $(IWASM_DIR)/common/arch/invokeNative_mingw_x64_simd.s
else
IWASM_SOURCE += $(IWASM_DIR)/common/arch/invokeNative_mingw_x64.s
endif
endif

## interpreter
ifeq ($(WAMR_BUILD_INTERP),1)
CFLAGS += -DWASM_ENABLE_INTERP=1

IWASM_INCLUDE += -I$(IWASM_DIR)/interpreter

IWASM_SOURCE += $(IWASM_DIR)/interpreter/wasm_runtime.c

ifeq ($(WAMR_BUILD_FAST_INTERP),1)
CFLAGS += -DWASM_ENABLE_FAST_INTERP=1

IWASM_SOURCE += $(IWASM_DIR)/interpreter/wasm_interp_fast.c
else
IWASM_SOURCE += $(IWASM_DIR)/interpreter/wasm_interp_classic.c
endif

ifeq ($(WAMR_BUILD_MINI_LOADER),1)
IWASM_SOURCE += $(IWASM_DIR)/interpreter/wasm_mini_loader.c
else
IWASM_SOURCE += $(IWASM_DIR)/interpreter/wasm_loader.c
endif
endif

## fast-jit
ifeq ($(WAMR_BUILD_FAST_JIT),1)
endif

## compilation
ifeq ($(WAMR_BUILD_JIT),1)
endif

# aot
ifeq ($(WAMR_BUILD_AOT),1)
endif

## gc
ifeq ($(WAMR_BUILD_GC),1)
endif

## libraries
ifeq ($(WAMR_BUILD_LIBC_BUILTIN),1)
CFLAGS += -DWASM_ENABLE_LIBC_BUILTIN=1

IWASM_INCLUDE += -I$(IWASM_DIR)/libraries/libc-builtin

IWASM_SOURCE += $(IWASM_DIR)/libraries/libc-builtin/libc_builtin_wrapper.c
endif

ifeq ($(WAMR_BUILD_LIBC_UVWASI),1)
else ifeq ($(WAMR_BUILD_LIBC_WASI),1)
CFLAGS += -DWASM_ENABLE_LIBC_WASI=1

IWASM_INCLUDE += \
	-I$(IWASM_DIR)/libraries/libc-wasi \
	-I$(IWASM_DIR)/libraries/libc-wasi/sandboxed-system-primitives/include \
	-I$(IWASM_DIR)/libraries/libc-wasi/sandboxed-system-primitives/src

IWASM_SOURCE += \
	$(IWASM_DIR)/libraries/libc-wasi/libc_wasi_wrapper.c \
	$(IWASM_DIR)/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c \
	$(IWASM_DIR)/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c \
	$(IWASM_DIR)/libraries/libc-wasi/sandboxed-system-primitives/src/random.c \
	$(IWASM_DIR)/libraries/libc-wasi/sandboxed-system-primitives/src/str.c
endif

ifeq ($(WAMR_BUILD_LIB_PTHREAD),1)
endif

ifeq ($(WAMR_BUILD_LIB_WASI_THREADS),1)
endif

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

# WAMR shared
SHARED_INCLUDE :=
SHARED_SOURCE  :=

## platform (Linux)
CFLAGS += -DBH_PLATFORM_LINUX
CFLAGS += -DWASM_HAVE_MREMAP=0

SHARED_INCLUDE += \
	-I$(SHARED_DIR)/platform/include \
	-I$(SHARED_DIR)/platform/linux \
	-I$(SHARED_DIR)/platform/common/posix

SHARED_SOURCE += \
	$(SHARED_DIR)/platform/linux/platform_init.c \
	$(SHARED_DIR)/platform/common/memory/mremap.c \
	$(SHARED_DIR)/platform/common/posix/posix_blocking_op.c \
	$(SHARED_DIR)/platform/common/posix/posix_malloc.c \
	$(SHARED_DIR)/platform/common/posix/posix_memmap.c \
	$(SHARED_DIR)/platform/common/posix/posix_sleep.c \
	$(SHARED_DIR)/platform/common/posix/posix_socket.c \
	$(SHARED_DIR)/platform/common/posix/posix_thread.c \
	$(SHARED_DIR)/platform/common/posix/posix_time.c

ifeq ($(WAMR_BUILD_LIBC_WASI),1)
SHARED_SOURCE += \
	$(SHARED_DIR)/platform/common/posix/posix_clock.c \
	$(SHARED_DIR)/platform/common/posix/posix_file.c
endif

ifneq ($(filter 1,$(WAMR_BUILD_LIBC_WASI) $(WAMR_BUILD_DEBUG_INTERP)),)
SHARED_INCLUDE += -I$(SHARED_DIR)/platform/common/libc-util

SHARED_SOURCE += $(SHARED_DIR)/platform/common/libc-util/libc_errno.c
else
endif

## mem-alloc
SHARED_INCLUDE += -I$(SHARED_DIR)/mem-alloc

SHARED_SOURCE += \
	$(SHARED_DIR)/mem-alloc/mem_alloc.c \
	$(SHARED_DIR)/mem-alloc/ems/ems_alloc.c \
	$(SHARED_DIR)/mem-alloc/ems/ems_gc.c \
	$(SHARED_DIR)/mem-alloc/ems/ems_hmu.c \
	$(SHARED_DIR)/mem-alloc/ems/ems_kfc.c

## utils
SHARED_INCLUDE += \
	-I$(SHARED_DIR)/utils \
	-I$(SHARED_DIR)/utils/uncommon

SHARED_SOURCE += \
	$(SHARED_DIR)/utils/bh_assert.c \
	$(SHARED_DIR)/utils/bh_bitmap.c \
	$(SHARED_DIR)/utils/bh_common.c \
	$(SHARED_DIR)/utils/bh_hashmap.c \
	$(SHARED_DIR)/utils/bh_leb128.c \
	$(SHARED_DIR)/utils/bh_list.c \
	$(SHARED_DIR)/utils/bh_log.c \
	$(SHARED_DIR)/utils/bh_queue.c \
	$(SHARED_DIR)/utils/bh_vector.c \
	$(SHARED_DIR)/utils/runtime_timer.c \
	$(SHARED_DIR)/utils/uncommon/bh_getopt.c \
	$(SHARED_DIR)/utils/uncommon/bh_read_file.c

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

WAMR_RUNTIME_LIB_INCLUDE := \
	${IWASM_INCLUDE} \
	${SHARED_INCLUDE}

WAMR_RUNTIME_LIB_SOURCE := \
	${IWASM_SOURCE} \
	${SHARED_SOURCE}

INCLUDES := \
	$(WAMR_RUNTIME_LIB_INCLUDE)

SOURCES := \
	$(WAMR_RUNTIME_LIB_SOURCE) \
	main.c

OBJS := \
	$(patsubst %.c,$(BUILD_DIR)/%.o,$(filter %.c,$(SOURCES))) \
	$(patsubst %.s,$(BUILD_DIR)/%.o,$(filter %.s,$(SOURCES)))

quiet_cmd_as = AS      $<
cmd_as       = $(CC) $(CFLAGS) -c -o $@ $<

quiet_cmd_cc = CC      $<
cmd_cc       = $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<

quiet_cmd_ld = LD      $(TARGET)
cmd_ld       = $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)

quiet_cmd_size = SIZE    $(TARGET)
cmd_size       = $(SIZE) $@

PHONY :=
PHONY += all
all: $(ELF)

$(ELF): $(OBJS)
	$(call cmd,ld)
	$(call cmd,size)

$(BUILD_DIR)/%.o: %.c | $(BUILD_DIR)
	$(Q)mkdir -p $(dir $@)
	$(call cmd,cc)

$(BUILD_DIR)/%.o: %.s | $(BUILD_DIR)
	$(Q)mkdir -p $(dir $@)
	$(call cmd,as)

$(BUILD_DIR):
	$(Q)mkdir -p $(BUILD_DIR)

PHONY += clean
clean:
	$(Q)rm -rf $(BUILD_DIR)

PHONY += run
run: $(ELF)
	$(Q)$(ELF)

.PHONY: $(PHONY)
