DOCKER := docker DOCKER_FLAGS := --rm -e DEBUG DEBUG ?= 0 USE_DOCKER ?= 1 ifeq ($(shell tty > /dev/null && echo 1 || echo 0), 1) DOCKER_FLAGS += -it endif DOCKER_WASM_BUILDER_IMAGE ?= openpolicyagent/opa-wasm-builder WASM_BUILDER_VERSION := 1.7 WASM_BUILDER_IMAGE := $(DOCKER_WASM_BUILDER_IMAGE):$(WASM_BUILDER_VERSION) WASM_TEST_NODE_VERSION := lts WASM_OBJ_DIR := _obj # Set compilers for local builds when not using Docker ifeq ($(USE_DOCKER), 0) CC ?= clang CXX ?= clang++ endif CFLAGS += \ -MD \ -MP \ -nodefaultlibs \ --target=wasm32-unknown-unknown-wasm \ -I src/lib \ -I src/libmpdec \ -DCONFIG_32 \ -DANSI \ -mno-bulk-memory \ -mno-bulk-memory-opt \ -mno-multivalue \ -mno-reference-types \ -mno-nontrapping-fptoint \ -mno-sign-ext \ -mno-mutable-globals \ -mno-call-indirect-overlong CPPFLAGS += \ -std=c++17 \ -MD \ -MP \ -nodefaultlibs \ --target=wasm32-unknown-unknown-wasm \ -fno-exceptions \ -fno-rtti \ -nostdinc++ \ -isystem src/libc++ \ -isystem /usr/lib/llvm-21/include/c++/v1 \ -isystem /usr/lib/llvm-21/lib/clang/21.1.7/include \ -isystem src/lib \ -I src/re2 \ -D_LIBCPP_HAS_NO_THREADS \ -D_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION \ -D_LIBCPP_HAS_NO_LOCALIZATION \ -D_LIBCPP_NO_EXCEPTIONS \ -mno-bulk-memory \ -mno-bulk-memory-opt \ -mno-multivalue \ -mno-reference-types \ -mno-nontrapping-fptoint \ -mno-sign-ext \ -mno-mutable-globals \ -mno-call-indirect-overlong ifeq ($(DEBUG), 1) CFLAGS += -O1 -gdwarf -DDEBUG CPPFLAGS += -O1 -gdwarf -DDEBUG else CFLAGS += -O3 CPPFLAGS += -O3 endif .PHONY: all all: build test .PHONY: clean clean: rm -fr $(WASM_OBJ_DIR) .PHONY: builder builder: Dockerfile $(DOCKER) build -t $(WASM_BUILDER_IMAGE) -f Dockerfile . .PHONY: ensure-builder ensure-builder: ifeq ($(USE_DOCKER), 1) @$(DOCKER) inspect $(WASM_BUILDER_IMAGE) > /dev/null || $(DOCKER) pull $(WASM_BUILDER_IMAGE) || $(MAKE) builder endif .PHONY: push-builder push-builder: $(DOCKER) pull $(WASM_BUILDER_IMAGE) || ($(MAKE) builder && $(DOCKER) push $(WASM_BUILDER_IMAGE)) .PHONY: build build: ifeq ($(USE_DOCKER), 1) @$(DOCKER) run $(DOCKER_FLAGS) -v $(CURDIR):/src:Z $(WASM_BUILDER_IMAGE) \ make --no-builtin-rules $(WASM_OBJ_DIR)/opa.wasm $(WASM_OBJ_DIR)/callgraph.csv else @$(MAKE) --no-builtin-rules $(WASM_OBJ_DIR)/opa.wasm $(WASM_OBJ_DIR)/callgraph.csv endif .PHONY: test test: ifeq ($(USE_DOCKER), 1) @$(DOCKER) run $(DOCKER_FLAGS) -v $(CURDIR):/src:Z $(WASM_BUILDER_IMAGE) make $(WASM_OBJ_DIR)/opa-test.wasm @$(DOCKER) run $(DOCKER_FLAGS) -e VERBOSE -v $(CURDIR):/src:Z -w /src node:$(WASM_TEST_NODE_VERSION) node test.js $(WASM_OBJ_DIR)/opa-test.wasm else @$(MAKE) $(WASM_OBJ_DIR)/opa-test.wasm @node test.js $(WASM_OBJ_DIR)/opa-test.wasm endif .PHONY: hack hack: @$(DOCKER) run $(DOCKER_FLAGS) -v $(CURDIR):/src:Z $(WASM_BUILDER_IMAGE) $(shell mkdir -p $(WASM_OBJ_DIR)/src/lib) $(shell mkdir -p $(WASM_OBJ_DIR)/src/libmpdec) $(shell mkdir -p $(WASM_OBJ_DIR)/src/libc++) $(shell mkdir -p $(WASM_OBJ_DIR)/src/re2/re2) $(shell mkdir -p $(WASM_OBJ_DIR)/src/re2/util) $(shell mkdir -p $(WASM_OBJ_DIR)/src) $(shell mkdir -p $(WASM_OBJ_DIR)/tests) SRCS := $(sort $(wildcard src/*.c)) CPP_SRCS := $(sort $(wildcard src/*.cc)) LIB_SRCS := $(sort $(wildcard src/lib/*.c)) LIB_MPDEC_SRCS := $(sort $(wildcard src/libmpdec/*.c)) LIB_CPP_SRCS := $(sort $(wildcard src/libc++/*.cc)) RE2_RE2_SRCS := $(sort $(wildcard src/re2/re2/*.cc)) RE2_UTIL_SRCS := $(sort $(wildcard src/re2/util/*.cc)) TEST_SRCS := $(sort $(wildcard tests/*.c)) TEST_CPP_SRCS := $(sort $(wildcard tests/*.cc)) -include $(patsubst %.c,$(WASM_OBJ_DIR)/%.d,$(SRCS)) -include $(patsubst %.cc,$(WASM_OBJ_DIR)/%.d,$(CPP_SRCS)) -include $(patsubst %.c,$(WASM_OBJ_DIR)/%.d,$(LIB_SRCS)) -include $(patsubst %.c,$(WASM_OBJ_DIR)/%.d,$(LIB_MPDEC_SRCS)) -include $(patsubst %.cc,$(WASM_OBJ_DIR)/%.d,$(LIB_CPP_SRCS)) -include $(patsubst %.cc,$(WASM_OBJ_DIR)/%.d,$(RE2_RE2_SRCS)) -include $(patsubst %.cc,$(WASM_OBJ_DIR)/%.d,$(RE2_UTIL_SRCS)) -include $(patsubst %.c,$(WASM_OBJ_DIR)/%.d,$(TEST_SRCS)) -include $(patsubst %.cc,$(WASM_OBJ_DIR)/%.d,$(TEST_CPP_SRCS)) OBJS := $(patsubst %.c, $(WASM_OBJ_DIR)/%.wasm, $(SRCS)) CPP_OBJS := $(patsubst %.cc, $(WASM_OBJ_DIR)/%.wasm, $(CPP_SRCS)) LIB_OBJS := $(patsubst %.c, $(WASM_OBJ_DIR)/%.wasm, $(LIB_SRCS)) LIB_MPDEC_OBJS := $(patsubst %.c, $(WASM_OBJ_DIR)/%.wasm, $(LIB_MPDEC_SRCS)) LIB_CPP_OBJS := $(patsubst %.cc, $(WASM_OBJ_DIR)/%.wasm, $(LIB_CPP_SRCS)) RE2_RE2_OBJS := $(patsubst %.cc, $(WASM_OBJ_DIR)/%.wasm, $(RE2_RE2_SRCS)) RE2_UTIL_OBJS := $(patsubst %.cc, $(WASM_OBJ_DIR)/%.wasm, $(RE2_UTIL_SRCS)) TEST_OBJS := $(patsubst %.c, $(WASM_OBJ_DIR)/%.wasm, $(TEST_SRCS)) TEST_CPP_OBJS := $(patsubst %.cc, $(WASM_OBJ_DIR)/%.wasm, $(TEST_CPP_SRCS)) $(OBJS): $(WASM_OBJ_DIR)/src/%.wasm: src/%.c $(CC) $(CFLAGS) -c -o $@ $< $(CPP_OBJS): $(WASM_OBJ_DIR)/src/%.wasm: src/%.cc $(CXX) $(CPPFLAGS) -c -o $@ $< $(LIB_OBJS): $(WASM_OBJ_DIR)/src/lib/%.wasm: src/lib/%.c $(CC) $(CFLAGS) -c -o $@ $< $(LIB_MPDEC_OBJS): $(WASM_OBJ_DIR)/src/libmpdec/%.wasm: src/libmpdec/%.c $(CC) $(CFLAGS) -c -o $@ $< $(LIB_CPP_OBJS): $(WASM_OBJ_DIR)/src/libc++/%.wasm: src/libc++/%.cc $(CXX) $(CPPFLAGS) -c -o $@ $< $(RE2_RE2_OBJS): $(WASM_OBJ_DIR)/src/re2/re2/%.wasm: src/re2/re2/%.cc $(CXX) $(CPPFLAGS) -c -o $@ $< $(RE2_UTIL_OBJS): $(WASM_OBJ_DIR)/src/re2/util/%.wasm: src/re2/util/%.cc $(CXX) $(CPPFLAGS) -c -o $@ $< $(TEST_OBJS): $(WASM_OBJ_DIR)/tests/%.wasm: tests/%.c $(CC) $(CFLAGS) -I src -c -o $@ $< $(TEST_CPP_OBJS): $(WASM_OBJ_DIR)/tests/%.wasm: tests/%.cc $(CXX) $(CPPFLAGS) -I src -c -o $@ $< $(WASM_OBJ_DIR)/opa.wasm: $(OBJS) $(CPP_OBJS) $(LIB_OBJS) $(LIB_MPDEC_OBJS) $(LIB_CPP_OBJS) $(RE2_RE2_OBJS) $(RE2_UTIL_OBJS) wasm-ld \ --allow-undefined-file=src/undefined.symbols \ --no-entry \ --export=__heap_base \ --stack-first \ -o $@ $^ @wasm2wat $(WASM_OBJ_DIR)/opa.wasm > $(WASM_OBJ_DIR)/opa.wast $(WASM_OBJ_DIR)/opa-test.wasm: $(OBJS) $(CPP_OBJS) $(LIB_OBJS) $(LIB_MPDEC_OBJS) $(LIB_CPP_OBJS) $(RE2_RE2_OBJS) $(RE2_UTIL_OBJS) $(TEST_OBJS) $(TEST_CPP_OBJS) @cat src/undefined.symbols tests/undefined.symbols > _obj/undefined.symbols @wasm-ld \ --allow-undefined-file=_obj/undefined.symbols \ --no-entry \ --stack-first \ -o $@ $^ $(WASM_OBJ_DIR)/callgraph.csv: $(WASM_OBJ_DIR)/opa.wasm # NOTE: wasm-opt will output "warning: no output file specified", # because we're not actually optimizing the wasm, but only extract # information. build/gen-wasm-callgraph.sh $< > $@ # These are for canceling the implicit rules of GNU Make, see # https://www.gnu.org/software/make/manual/html_node/Canceling-Rules.html#Canceling-Rules src/libc++/mutex: src/libc++/mutex.cc