Monorepo for Aesthetic.Computer aesthetic.computer
at main 198 lines 7.6 kB view raw
1# ac-native Makefile 2# Builds the native AC piece runner, optionally with QuickJS-ng 3 4SRCDIR := src 5BUILDDIR := build 6QJSDIR := $(BUILDDIR)/quickjs 7 8# Use musl for static linking if available, else gcc 9CC ?= gcc 10GIT_HASH := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown") 11BUILD_TS ?= $(shell date -u '+%Y-%m-%dT%H:%M') 12BUILD_NAME := $(shell scripts/build-name.sh --bump 2>/dev/null || echo "local-build") 13QUIRCDIR := lib/quirc/lib 14QRGENDIR := lib/qrcodegen 15CFLAGS := -O2 -Wall -Wextra -std=gnu11 -I$(QJSDIR) -I$(QUIRCDIR) -I$(QRGENDIR) -DAC_GIT_HASH=\"$(GIT_HASH)\" -DAC_BUILD_TS=\"$(BUILD_TS)\" -DAC_BUILD_NAME=\"$(BUILD_NAME)\" 16LDFLAGS := -Wl,--as-needed -lm -lpthread -lasound -lutil -ldl 17 18# Static build: only when musl-gcc is available (musl has bundled static libc) 19# On Fedora/standard gcc, dynamic linking is used and .so files are bundled in initramfs 20ifdef STATIC 21 ifeq ($(shell command -v musl-gcc 2>/dev/null),) 22 # musl-gcc not available — skip -static (dynamic linking, bundle .so in initramfs) 23 STATIC := 24 else 25 LDFLAGS += -static 26 endif 27endif 28 29# DRM headers — use pkg-config if available 30DRM_CFLAGS := $(shell pkg-config --cflags libdrm 2>/dev/null || echo "-I/usr/include/libdrm -I/usr/include/drm") 31DRM_LIBS := $(shell pkg-config --libs libdrm 2>/dev/null || echo "-ldrm") 32ALSA_CFLAGS := $(shell pkg-config --cflags alsa 2>/dev/null) 33ALSA_LIBS := $(shell pkg-config --libs alsa 2>/dev/null || echo "-lasound") 34FLITE_LIBS := -lflite -lflite_cmulex -lflite_usenglish -lflite_cmu_us_slt -lflite_cmu_us_kal 35 36# ffmpeg libraries for video recording (optional: disabled if not found) 37HAVE_AVCODEC := $(shell pkg-config --exists libavcodec libavformat libavutil libswscale libswresample 2>/dev/null && echo 1) 38ifeq ($(HAVE_AVCODEC),1) 39 AV_CFLAGS := $(shell pkg-config --cflags libavcodec libavformat libavutil libswscale libswresample 2>/dev/null) 40 AV_LIBS := $(shell pkg-config --libs libavcodec libavformat libavutil libswscale libswresample 2>/dev/null) 41endif 42 43CFLAGS += $(DRM_CFLAGS) $(ALSA_CFLAGS) 44LDFLAGS += $(DRM_LIBS) $(ALSA_LIBS) $(FLITE_LIBS) 45ifeq ($(HAVE_AVCODEC),1) 46 CFLAGS += -DHAVE_AVCODEC $(AV_CFLAGS) 47 LDFLAGS += $(AV_LIBS) 48endif 49 50# SDL3 GPU-accelerated display: always compiled, loaded via dlopen at runtime. 51# Binary runs without SDL3 libs and falls back to DRM/fbdev. 52# No compile-time or link-time SDL dependency. 53 54# Wayland display backend (for running under cage compositor: make USE_WAYLAND=1) 55XDG_SHELL_XML := /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml 56ifdef USE_WAYLAND 57 WL_CFLAGS := $(shell pkg-config --cflags wayland-client 2>/dev/null) 58 WL_LIBS := $(shell pkg-config --libs wayland-client 2>/dev/null || echo "-lwayland-client") 59 CFLAGS += -DUSE_WAYLAND $(WL_CFLAGS) 60 LDFLAGS += $(WL_LIBS) 61endif 62 63# Source files 64SSL_LIBS := $(shell pkg-config --libs openssl 2>/dev/null || echo "-lssl -lcrypto") 65LDFLAGS += $(SSL_LIBS) 66 67SRCS := $(SRCDIR)/ac-native.c \ 68 $(SRCDIR)/drm-display.c \ 69 $(SRCDIR)/framebuffer.c \ 70 $(SRCDIR)/graph.c \ 71 $(SRCDIR)/graph3d.c \ 72 $(SRCDIR)/font.c \ 73 $(SRCDIR)/color.c \ 74 $(SRCDIR)/input.c \ 75 $(SRCDIR)/audio.c \ 76 $(SRCDIR)/usb-midi.c \ 77 $(SRCDIR)/wifi.c \ 78 $(SRCDIR)/tts.c \ 79 $(SRCDIR)/ws-client.c \ 80 $(SRCDIR)/udp-client.c \ 81 $(SRCDIR)/camera.c \ 82 $(SRCDIR)/pty.c \ 83 $(SRCDIR)/machines.c \ 84 $(SRCDIR)/swank-bridge.c \ 85 $(SRCDIR)/js-bindings.c \ 86 $(SRCDIR)/audio-decode.c \ 87 $(SRCDIR)/recorder.c 88 89# Wayland display backend (conditional) 90ifdef USE_WAYLAND 91 SRCS += $(SRCDIR)/wayland-display.c 92endif 93 94OBJS := $(patsubst $(SRCDIR)/%.c,$(BUILDDIR)/%.o,$(SRCS)) 95 96# Wayland protocol generated objects (separate from SRCS pattern) 97ifdef USE_WAYLAND 98 WL_PROTO_OBJS := $(BUILDDIR)/xdg-shell-protocol.o 99else 100 WL_PROTO_OBJS := 101endif 102 103# QuickJS-ng object files (compiled from source) 104QJS_SRCS := $(QJSDIR)/quickjs.c $(QJSDIR)/libunicode.c $(QJSDIR)/libregexp.c $(QJSDIR)/cutils.c $(QJSDIR)/libbf.c 105QJS_OBJS := $(patsubst $(QJSDIR)/%.c,$(BUILDDIR)/qjs-%.o,$(QJS_SRCS)) 106 107# Quirc QR decoder (compiled from vendored source) 108QUIRC_SRCS := $(QUIRCDIR)/quirc.c $(QUIRCDIR)/decode.c $(QUIRCDIR)/identify.c $(QUIRCDIR)/version_db.c 109QUIRC_OBJS := $(patsubst $(QUIRCDIR)/%.c,$(BUILDDIR)/quirc-%.o,$(QUIRC_SRCS)) 110 111# QR code generator (vendored from nayuki/QR-Code-generator, MIT licensed) 112QRGEN_SRCS := $(QRGENDIR)/qrcodegen.c 113QRGEN_OBJS := $(patsubst $(QRGENDIR)/%.c,$(BUILDDIR)/qrgen-%.o,$(QRGEN_SRCS)) 114 115TARGET := $(BUILDDIR)/ac-native 116 117.PHONY: all clean quickjs test bpf 118 119all: quickjs $(TARGET) 120 121# BPF trace tools (ftrace fallback by default; full BPF: make bpf HAS_LIBBPF=1) 122bpf: 123 $(MAKE) -C bpf CC=$(CC) 124 125$(TARGET): $(OBJS) $(QJS_OBJS) $(QUIRC_OBJS) $(QRGEN_OBJS) $(WL_PROTO_OBJS) 126 $(CC) -o $@ $^ $(LDFLAGS) 127 @echo "Built: $@ ($(shell wc -c < $@ | tr -d ' ') bytes)" 128 129# All .c files depend on all project headers (simple but correct) 130HEADERS := $(wildcard $(SRCDIR)/*.h) 131 132# Track CFLAGS changes — force full rebuild when git hash, build name, or any flag changes. 133# Make only watches source timestamps, not compiler flags, so without this the binary 134# retains stale AC_BUILD_NAME / AC_GIT_HASH after new commits with no C source changes. 135CFLAGS_FILE := $(BUILDDIR)/.cflags 136CFLAGS_SIG := $(shell echo '$(CFLAGS)' | md5sum | cut -d' ' -f1) 137CFLAGS_PREV := $(shell cat $(CFLAGS_FILE) 2>/dev/null) 138ifneq ($(CFLAGS_SIG),$(CFLAGS_PREV)) 139 $(shell mkdir -p $(BUILDDIR) && echo '$(CFLAGS_SIG)' > $(CFLAGS_FILE)) 140 $(shell rm -f $(BUILDDIR)/*.o) 141endif 142 143$(BUILDDIR)/%.o: $(SRCDIR)/%.c $(HEADERS) | $(BUILDDIR) 144 $(CC) $(CFLAGS) -c -o $@ $< 145 146$(BUILDDIR)/qjs-%.o: $(QJSDIR)/%.c | $(BUILDDIR) 147 $(CC) $(CFLAGS) -DCONFIG_VERSION=\"0.8.0\" -c -o $@ $< 148 149$(BUILDDIR)/qrgen-%.o: $(QRGENDIR)/%.c | $(BUILDDIR) 150 $(CC) -O2 -Wall -std=c99 -I$(QRGENDIR) -c -o $@ $< 151 152$(BUILDDIR)/quirc-%.o: $(QUIRCDIR)/%.c | $(BUILDDIR) 153 $(CC) -O2 -Wall -std=gnu11 -I$(QUIRCDIR) -c -o $@ $< 154 155$(BUILDDIR): 156 mkdir -p $(BUILDDIR) 157 158# Wayland protocol code generation (xdg-shell) 159ifdef USE_WAYLAND 160$(BUILDDIR)/xdg-shell-client-protocol.h: $(XDG_SHELL_XML) | $(BUILDDIR) 161 wayland-scanner client-header $< $@ 162 163$(BUILDDIR)/xdg-shell-protocol.c: $(XDG_SHELL_XML) | $(BUILDDIR) 164 wayland-scanner private-code $< $@ 165 166$(BUILDDIR)/xdg-shell-protocol.o: $(BUILDDIR)/xdg-shell-protocol.c $(BUILDDIR)/xdg-shell-client-protocol.h | $(BUILDDIR) 167 $(CC) -O2 -Wall -I$(BUILDDIR) -c -o $@ $< 168 169# wayland-display.c depends on generated protocol header 170$(BUILDDIR)/wayland-display.o: $(SRCDIR)/wayland-display.c $(BUILDDIR)/xdg-shell-client-protocol.h $(HEADERS) | $(BUILDDIR) 171 $(CC) $(CFLAGS) -I$(BUILDDIR) -c -o $@ $< 172endif 173 174# Download and prepare QuickJS-ng 175quickjs: $(QJSDIR)/quickjs.h 176 177QJS_VERSION := 0.8.0 178QJS_URL := https://github.com/nicoffee/nicoffee-nicoffee/archive/refs/tags/v$(QJS_VERSION).tar.gz 179 180$(QJSDIR)/quickjs.h: 181 @echo "Fetching QuickJS..." 182 mkdir -p $(QJSDIR) 183 curl -sL "https://bellard.org/quickjs/quickjs-2024-01-13.tar.xz" -o $(BUILDDIR)/qjs.tar.xz && \ 184 cd $(BUILDDIR) && tar xf qjs.tar.xz && \ 185 cp quickjs-2024-01-13/*.c quickjs-2024-01-13/*.h quickjs/ || { \ 186 echo "ERROR: Cannot fetch QuickJS." ; \ 187 echo " curl -L https://bellard.org/quickjs/quickjs-2024-01-13.tar.xz | tar xJ" ; \ 188 exit 1 ; \ 189 } 190 191clean: 192 rm -f $(BUILDDIR)/*.o $(BUILDDIR)/qjs-*.o $(TARGET) $(BUILDDIR)/qjs.tar.xz 193 rm -rf $(BUILDDIR)/quickjs $(BUILDDIR)/quickjs-* 194 195# Run test piece locally (needs DRM access or QEMU) 196test: $(TARGET) 197 @echo "Running hello.mjs test piece..." 198 $(TARGET) test-pieces/hello.mjs