Skip to content

Commit

Permalink
Move WebAssembly related rules to wasm.mk
Browse files Browse the repository at this point in the history
  • Loading branch information
ChinYikMing committed Apr 8, 2024
1 parent 7c41eba commit d06a75a
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 122 deletions.
127 changes: 8 additions & 119 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
include mk/common.mk
include mk/color.mk
include mk/toolchain.mk

OUT ?= build
Expand All @@ -11,7 +10,11 @@ CONFIG_FILE := $(OUT)/.config
CFLAGS = -std=gnu99 -O2 -Wall -Wextra
CFLAGS += -Wno-unused-label
CFLAGS += -include src/common.h
CFLAGS_emcc ?=

# Color
YELLOW=\033[0;33m
GREEN=\033[0;32m
NC=\033[0m

# Enable link-time optimization (LTO)
ENABLE_LTO ?= 1
Expand Down Expand Up @@ -142,20 +145,6 @@ endif
# For tail-call elimination, we need a specific set of build flags applied.
# FIXME: On macOS + Apple Silicon, -fno-stack-protector might have a negative impact.

# Enable tail-call for emcc
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
OBJS_EXT += syscall_sdl.o
LDFLAGS += -pthread
endif
endif

ENABLE_UBSAN ?= 0
ifeq ("$(ENABLE_UBSAN)", "1")
CFLAGS += -fsanitize=undefined -fno-sanitize=alignment -fno-sanitize-recover=all
Expand All @@ -168,12 +157,9 @@ $(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
include mk/external.mk

include mk/wasm.mk

all: config $(BIN)

Expand All @@ -194,93 +180,6 @@ OBJS := \
OBJS := $(addprefix $(OUT)/, $(OBJS))
deps := $(OBJS:%.o=%.o.d)

include mk/external.mk

deps_emcc :=
ASSETS := assets
WEB_JS_RESOURCES := $(ASSETS)/js
EXPORTED_FUNCS := _main,_indirect_rv_halt
ifeq ("$(CC_IS_EMCC)", "1")
CFLAGS_emcc += -sINITIAL_MEMORY=2GB \
-sALLOW_MEMORY_GROWTH \
-s"EXPORTED_FUNCTIONS=$(EXPORTED_FUNCS)" \
-sSTACK_SIZE=4MB \
-sPTHREAD_POOL_SIZE=navigator.hardwareConcurrency \
--embed-file build@/ \
--embed-file build/timidity@/etc/timidity \
-DMEM_SIZE=0x40000000 \
-DCYCLE_PER_STEP=2000000 \
--pre-js $(WEB_JS_RESOURCES)/pre.js \
-O3 \
-w

# used to download all dependencies of elf executable and bundle into single wasm
deps_emcc += $(DOOM_DATA) $(QUAKE_DATA) $(TIMIDITY_DATA)

# check browser MAJOR version if supports TCO
CHROME_MAJOR :=
CHROME_MAJOR_VERSION_CHECK_CMD :=
CHROME_SUPPORT_TCO_AT_MAJOR := 112
CHROME_SUPPORT_TCO_INFO := Chrome supports TCO, you can use Chrome to request the wasm
CHROME_NO_SUPPORT_TCO_WARNING := Chrome not found or Chrome must have at least version $(CHROME_SUPPORT_TCO_AT_MAJOR) in MAJOR to serve wasm

FIREFOX_MAJOR :=
FIREFOX_MAJOR_VERSION_CHECK_CMD :=
FIREFOX_SUPPORT_TCO_AT_MAJOR := 121
FIREFOX_SUPPORT_TCO_INFO := Firefox supports TCO, you can use Firefox to request the wasm
FIREFOX_NO_SUPPORT_TCO_WARNING := Firefox not found or Firefox must have at least version $(FIREFOX_SUPPORT_TCO_AT_MAJOR) in MAJOR to serve wasm

# FIXME: for Windows
ifeq ($(UNAME_S),Darwin)
CHROME_MAJOR_VERSION_CHECK_CMD := "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --version | awk '{print $$3}' | cut -f1 -d.
FIREFOX_MAJOR_VERSION_CHECK_CMD := /Applications/Firefox.app/Contents/MacOS/firefox --version | awk '{print $$3}' | cut -f1 -d.
else ifeq ($(UNAME_S),Linux)
CHROME_MAJOR_VERSION_CHECK_CMD := google-chrome --version | awk '{print $$3}' | cut -f1 -d.
FIREFOX_MAJOR_VERSION_CHECK_CMD := firefox -v | awk '{print $$3}' | cut -f1 -d.
endif
CHROME_MAJOR := $(shell $(CHROME_MAJOR_VERSION_CHECK_CMD))
FIREFOX_MAJOR := $(shell $(FIREFOX_MAJOR_VERSION_CHECK_CMD))

# Chrome
ifeq ($(shell echo $(CHROME_MAJOR)\>=$(CHROME_SUPPORT_TCO_AT_MAJOR) | bc), 1)
$(info $(shell echo "$(GREEN)$(CHROME_SUPPORT_TCO_INFO)$(NC)"))
else
$(warning $(shell echo "$(YELLOW)$(CHROME_NO_SUPPORT_TCO_WARNING)$(NC)"))
endif

# Firefox
ifeq ($(shell echo $(FIREFOX_MAJOR)\>=$(FIREFOX_SUPPORT_TCO_AT_MAJOR) | bc), 1)
$(info $(shell echo "$(GREEN)$(FIREFOX_SUPPORT_TCO_INFO)$(NC)"))
else
$(warning $(shell echo "$(YELLOW)$(FIREFOX_NO_SUPPORT_TCO_WARNING)$(NC)"))
endif

# used to serve wasm locally
DEMO_DIR := demo
DEMO_IP := 127.0.0.1
DEMO_PORT := 8000

# check if demo root directory exists and create it if not
check-demo-dir-exist:
$(Q)if [ ! -d "$(DEMO_DIR)" ]; then \
mkdir -p "$(DEMO_DIR)"; \
fi

# FIXME: without $(info) generates errors
define cp-web-file
$(Q)cp $(1) $(DEMO_DIR)
$(info)
endef

# WEB_FILES could be cleaned and recompiled, thus do not mix these two files into WEB_FILES
STATIC_WEB_FILES := assets/html/index.html assets/js/coi-serviceworker.min.js

serve-wasm: $(BIN) check-demo-dir-exist
$(foreach T, $(WEB_FILES), $(call cp-web-file, $(T)))
$(foreach T, $(STATIC_WEB_FILES), $(call cp-web-file, $(T)))
$(Q)python3 -m http.server --bind $(DEMO_IP) $(DEMO_PORT) --directory $(DEMO_DIR)
endif

$(OUT)/%.o: src/%.c $(deps_emcc)
$(VECHO) " CC\t$@\n"
$(Q)$(CC) -o $@ $(CFLAGS) $(CFLAGS_emcc) -c -MMD -MF $@.d $<
Expand Down Expand Up @@ -340,22 +239,12 @@ misalign: $(BIN)
# Non-trivial demonstration programs
ifeq ($(call has, SDL), 1)
doom_action := (cd $(OUT); ../$(BIN) doom.elf)
ifeq ("$(CC_IS_EMCC)", "1")
# TODO: check Chrome or Firefox is available and serve python httpd and open the web page
# TODO: serve and open a web page, show warning if environment not support pthread runtime
doom_action :=
endif
doom_deps += $(DOOM_DATA) $(BIN)
doom: $(doom_deps)
$(doom_action)

ifeq ($(call has, EXT_F), 1)
quake_action := (cd $(OUT); ../$(BIN) quake.elf)
ifeq ("$(CC_IS_EMCC)", "1")
# TODO: check Chrome or Firefox is available and serve python httpd and open the web page
# TODO: serve and open a web page, show warning if environment not support pthread runtime
quake_action :=
endif
quake_deps += $(QUAKE_DATA) $(BIN)
quake: $(quake_deps)
$(quake_action)
Expand Down
3 changes: 0 additions & 3 deletions mk/color.mk

This file was deleted.

104 changes: 104 additions & 0 deletions mk/wasm.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
CFLAGS_emcc ?=
deps_emcc :=
ASSETS := assets
WEB_HTML_RESOURCES := $(ASSETS)/html
WEB_JS_RESOURCES := $(ASSETS)/js
EXPORTED_FUNCS := _main,_indirect_rv_halt

ifeq ("$(CC_IS_EMCC)", "1")
WEB_FILES := $(BIN).js \
$(BIN).wasm \
$(BIN).worker.js
BIN := $(BIN).js

# TCO
CFLAGS += -mtail-call

# Build emscripten-port SDL
ifeq ($(call has, SDL), 1)
CFLAGS_emcc += -sUSE_SDL=2 -sSDL2_MIXER_FORMATS=wav,mid -sUSE_SDL_MIXER=2
OBJS_EXT += syscall_sdl.o
LDFLAGS += -pthread
endif

# More build flags
CFLAGS_emcc += -sINITIAL_MEMORY=2GB \
-sALLOW_MEMORY_GROWTH \
-s"EXPORTED_FUNCTIONS=$(EXPORTED_FUNCS)" \
-sSTACK_SIZE=4MB \
-sPTHREAD_POOL_SIZE=navigator.hardwareConcurrency \
--embed-file build@/ \
--embed-file build/timidity@/etc/timidity \
-DMEM_SIZE=0x40000000 \
-DCYCLE_PER_STEP=2000000 \
--pre-js $(WEB_JS_RESOURCES)/pre.js \
-O3 \
-w

# used to download all dependencies of elf executable and bundle into single wasm
deps_emcc += $(DOOM_DATA) $(QUAKE_DATA) $(TIMIDITY_DATA)

# check browser MAJOR version if supports TCO
CHROME_MAJOR :=
CHROME_MAJOR_VERSION_CHECK_CMD :=
CHROME_SUPPORT_TCO_AT_MAJOR := 112
CHROME_SUPPORT_TCO_INFO := Chrome supports TCO, you can use Chrome to request the wasm
CHROME_NO_SUPPORT_TCO_WARNING := Chrome not found or Chrome must have at least version $(CHROME_SUPPORT_TCO_AT_MAJOR) in MAJOR to support TCO in wasm

FIREFOX_MAJOR :=
FIREFOX_MAJOR_VERSION_CHECK_CMD :=
FIREFOX_SUPPORT_TCO_AT_MAJOR := 121
FIREFOX_SUPPORT_TCO_INFO := Firefox supports TCO, you can use Firefox to request the wasm
FIREFOX_NO_SUPPORT_TCO_WARNING := Firefox not found or Firefox must have at least version $(FIREFOX_SUPPORT_TCO_AT_MAJOR) in MAJOR to support TCO in wasm

# FIXME: for Windows
ifeq ($(UNAME_S),Darwin)
CHROME_MAJOR_VERSION_CHECK_CMD := "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --version | awk '{print $$3}' | cut -f1 -d.
FIREFOX_MAJOR_VERSION_CHECK_CMD := /Applications/Firefox.app/Contents/MacOS/firefox --version | awk '{print $$3}' | cut -f1 -d.
else ifeq ($(UNAME_S),Linux)
CHROME_MAJOR_VERSION_CHECK_CMD := google-chrome --version | awk '{print $$3}' | cut -f1 -d.
FIREFOX_MAJOR_VERSION_CHECK_CMD := firefox -v | awk '{print $$3}' | cut -f1 -d.
endif
CHROME_MAJOR := $(shell $(CHROME_MAJOR_VERSION_CHECK_CMD))
FIREFOX_MAJOR := $(shell $(FIREFOX_MAJOR_VERSION_CHECK_CMD))

# Chrome
ifeq ($(shell echo $(CHROME_MAJOR)\>=$(CHROME_SUPPORT_TCO_AT_MAJOR) | bc), 1)
$(info $(shell echo "$(GREEN)$(CHROME_SUPPORT_TCO_INFO)$(NC)"))
else
$(warning $(shell echo "$(YELLOW)$(CHROME_NO_SUPPORT_TCO_WARNING)$(NC)"))
endif

# Firefox
ifeq ($(shell echo $(FIREFOX_MAJOR)\>=$(FIREFOX_SUPPORT_TCO_AT_MAJOR) | bc), 1)
$(info $(shell echo "$(GREEN)$(FIREFOX_SUPPORT_TCO_INFO)$(NC)"))
else
$(warning $(shell echo "$(YELLOW)$(FIREFOX_NO_SUPPORT_TCO_WARNING)$(NC)"))
endif

# used to serve wasm locally
DEMO_DIR := demo
DEMO_IP := 127.0.0.1
DEMO_PORT := 8000

# check if demo root directory exists and create it if not
check-demo-dir-exist:
$(Q)if [ ! -d "$(DEMO_DIR)" ]; then \
mkdir -p "$(DEMO_DIR)"; \
fi

# FIXME: without $(info) generates errors
define cp-web-file
$(Q)cp $(1) $(DEMO_DIR)
$(info)
endef

# WEB_FILES could be cleaned and recompiled, thus do not mix these two files into WEB_FILES
STATIC_WEB_FILES := $(WEB_HTML_RESOURCES)/index.html \
$(WEB_JS_RESOURCES)/coi-serviceworker.min.js

serve-wasm: $(BIN) check-demo-dir-exist
$(foreach T, $(WEB_FILES), $(call cp-web-file, $(T)))
$(foreach T, $(STATIC_WEB_FILES), $(call cp-web-file, $(T)))
$(Q)python3 -m http.server --bind $(DEMO_IP) $(DEMO_PORT) --directory $(DEMO_DIR)
endif

0 comments on commit d06a75a

Please sign in to comment.