From 446b95b6eeb2778eac80817ec2ad236cc6cdb7f0 Mon Sep 17 00:00:00 2001 From: ChinYikMing Date: Mon, 11 Mar 2024 15:28:04 +0800 Subject: [PATCH] Tweak build rules for WebAssembly The "emcc --version" command displays information about the version of emcc, which contains the "gcc" or "clang" string. As a result, the build rule should only match one compiler and stop checking anymore. If not, the build could be failed by a mix of different compiler's CFLAGS. For example, -flto from clang and -flto=thin from emcc. After refactoring the riscv.[ch] public APIs in commit 820cd9b, it is now possible to adjust the memory size to accommodate varying runtime requirements. The memory size must align to a 4KB page size for the WASM runtime and I set 1GB as default memory size for WASM runtime. The LTO is not supported to build emscripten-port SDL library, so disable it when both ENABLE_LTO=1 and ENABLE_SDL=1 are set. Related to: #75 Close #375 --- Makefile | 40 ++++++++++++++++++++++++++++++++++++---- mk/toolchain.mk | 33 +++++++++++++++++++++++++++------ src/main.c | 5 ++++- 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 63b55fdd9..773b44a93 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ CONFIG_FILE := $(OUT)/.config CFLAGS = -std=gnu99 -O2 -Wall -Wextra CFLAGS += -Wno-unused-label CFLAGS += -include src/common.h +CFLAGS_emcc ?= # Enable link-time optimization (LTO) ENABLE_LTO ?= 1 @@ -21,7 +22,14 @@ endif endif $(call set-feature, LTO) ifeq ($(call has, LTO), 1) -ifeq ("$(CC_IS_GCC)$(CC_IS_EMCC)", "1") +ifeq ("$(CC_IS_EMCC)", "1") +ifeq ($(call has, SDL), 1) +$(warning LTO is not supported to build emscripten-port SDL using emcc.) +else +CFLAGS += -flto +endif +endif +ifeq ("$(CC_IS_GCC)", "1") CFLAGS += -flto endif ifeq ("$(CC_IS_CLANG)", "1") @@ -136,6 +144,13 @@ ifeq ("$(CC_IS_EMCC)", "1") CFLAGS += -mtail-call endif +# Build emscripten-port SDL +ifeq ("$(CC_IS_EMCC)", "1") +ifeq ($(call has, SDL), 1) +CFLAGS_emcc += -sUSE_SDL=2 -sSDL2_MIXER_FORMATS=wav,mid -sUSE_SDL_MIXER=2 +endif +endif + ENABLE_UBSAN ?= 0 ifeq ("$(ENABLE_UBSAN)", "1") CFLAGS += -fsanitize=undefined -fno-sanitize=alignment -fno-sanitize-recover=all @@ -148,6 +163,13 @@ $(OUT)/emulate.o: CFLAGS += -foptimize-sibling-calls -fomit-frame-pointer -fno-s # to the first target after .DEFAULT_GOAL is not set. .DEFAULT_GOAL := +WEB_FILES += $(BIN).js \ + $(BIN).wasm \ + $(BIN).worker.js +ifeq ("$(CC_IS_EMCC)", "1") +BIN := $(BIN).js +endif + all: config $(BIN) OBJS := \ @@ -167,13 +189,23 @@ OBJS := \ OBJS := $(addprefix $(OUT)/, $(OBJS)) deps := $(OBJS:%.o=%.o.d) +EXPORTED_FUNCS := _main +ifeq ("$(CC_IS_EMCC)", "1") +CFLAGS_emcc += -sINITIAL_MEMORY=2GB \ + -sALLOW_MEMORY_GROWTH \ + -s"EXPORTED_FUNCTIONS=$(EXPORTED_FUNCS)" \ + --embed-file build \ + -DMEM_SIZE=0x40000000 \ + -w +endif + $(OUT)/%.o: src/%.c $(VECHO) " CC\t$@\n" - $(Q)$(CC) -o $@ $(CFLAGS) -c -MMD -MF $@.d $< + $(Q)$(CC) -o $@ $(CFLAGS) $(CFLAGS_emcc) -c -MMD -MF $@.d $< $(BIN): $(OBJS) $(VECHO) " LD\t$@\n" - $(Q)$(CC) -o $@ $^ $(LDFLAGS) + $(Q)$(CC) -o $@ $(CFLAGS_emcc) $^ $(LDFLAGS) config: $(CONFIG_FILE) $(CONFIG_FILE): @@ -236,7 +268,7 @@ endif endif clean: - $(RM) $(BIN) $(OBJS) $(HIST_BIN) $(HIST_OBJS) $(deps) $(CACHE_OUT) src/rv32_jit.c + $(RM) $(BIN) $(OBJS) $(HIST_BIN) $(HIST_OBJS) $(deps) $(WEB_FILES) $(CACHE_OUT) src/rv32_jit.c distclean: clean -$(RM) $(DOOM_DATA) $(QUAKE_DATA) $(RM) -r $(OUT)/id1 diff --git a/mk/toolchain.mk b/mk/toolchain.mk index f75bd02eb..814497f71 100644 --- a/mk/toolchain.mk +++ b/mk/toolchain.mk @@ -3,12 +3,33 @@ CC_IS_CLANG := CC_IS_GCC := ifneq ($(shell $(CC) --version | head -n 1 | grep emcc),) CC_IS_EMCC := 1 -endif -ifneq ($(shell $(CC) --version | head -n 1 | grep clang),) - CC_IS_CLANG := 1 -endif -ifneq ($(shell $(CC) --version | grep "Free Software Foundation"),) - CC_IS_GCC := 1 + + # see commit 165c1a3 of emscripten + MIMALLOC_SUPPORT_SINCE_MAJOR := 3 + MIMALLOC_SUPPORT_SINCE_MINOR := 1 + MIMALLOC_SUPPORT_SINCE_PATCH := 50 + MIMALLOC_UNSUPPORTED_WARNING := mimalloc is supported after version $(MIMALLOC_SUPPORT_SINCE_MAJOR).$(MIMALLOC_SUPPORT_SINCE_MINOR).$(MIMALLOC_SUPPORT_SINCE_PATCH) + EMCC_VERSION := $(shell $(CC) --version | head -n 1 | cut -f10 -d ' ') + EMCC_MAJOR := $(shell echo $(EMCC_VERSION) | cut -f1 -d.) + EMCC_MINOR := $(shell echo $(EMCC_VERSION) | cut -f2 -d.) + EMCC_PATCH := $(shell echo $(EMCC_VERSION) | cut -f3 -d.) + ifeq ($(shell echo $(EMCC_MAJOR)\>=$(MIMALLOC_SUPPORT_SINCE_MAJOR) | bc), 1) + ifeq ($(shell echo $(EMCC_MINOR)\>=$(MIMALLOC_SUPPORT_SINCE_MINOR) | bc), 1) + ifeq ($(shell echo $(EMCC_PATCH)\>=$(MIMALLOC_SUPPORT_SINCE_PATCH) | bc), 1) + CFLAGS_emcc += -sMALLOC=mimalloc + else + $(warning $(MIMALLOC_UNSUPPORTED_WARNING)) + endif + else + $(warning $(MIMALLOC_UNSUPPORTED_WARNING)) + endif + else + $(warning $(MIMALLOC_UNSUPPORTED_WARNING)) + endif +else ifneq ($(shell $(CC) --version | head -n 1 | grep clang),) + CC_IS_CLANG := 1 +else ifneq ($(shell $(CC) --version | grep "Free Software Foundation"),) + CC_IS_GCC := 1 endif CFLAGS_NO_CET := diff --git a/src/main.c b/src/main.c index e4c129d72..f10fdcd41 100644 --- a/src/main.c +++ b/src/main.c @@ -168,7 +168,10 @@ static void dump_test_signature(const char *prog_name) elf_delete(elf); } -#define MEM_SIZE 0xFFFFFFFFULL /* 2^32 - 1 */ +/* MEM_SIZE shall be defined on different runtime */ +#ifndef MEM_SIZE +#define MEM_SIZE 0xFFFFFFFFULL /* 2^32 - 1 */ +#endif #define STACK_SIZE 0x1000 /* 4096 */ #define ARGS_OFFSET_SIZE 0x1000 /* 4096 */