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 */