Files
releases/wasm/Makefile
Stephan Renatus 7c48e417ea wasm: updates (LLVM+tools) (#8295)
* wasm: update wabt and binaryen in builder image
* wasm: bump ubuntu and llvm
* wasm: bump LLVM 13 -> 21, adjust headers
* wasm: make docker optional

We depend on it in our builds, but if you happen to bring

clang (LLVM 21)
clang++ (LLVM 21)
wasm-ld (LLVM 21)
wasm2wat (wabt)
wasm-opt (binaryen)
node

you should be able to build the opa.wasm blob without the docker image.


Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
2026-02-05 15:31:23 +01:00

210 lines
6.5 KiB
Makefile

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