2026-04-12 14:32:14 -05:00
|
|
|
# pxl8 - Makefile
|
|
|
|
|
#
|
|
|
|
|
# Usage:
|
|
|
|
|
# make Build everything (debug)
|
|
|
|
|
# make release Build everything (release)
|
|
|
|
|
# make run Build and run (CART=script.fnl)
|
|
|
|
|
# make server Build pxl8d only
|
|
|
|
|
# make client Build pxl8 only
|
|
|
|
|
# make install Install to ~/.local/bin (release)
|
|
|
|
|
# make profile Profile with perf + flamegraph (Linux)
|
|
|
|
|
# make ase Aseprite tools (ASE_CMD=package|clean)
|
|
|
|
|
# make clean Remove build artifacts
|
|
|
|
|
# make clean-all Remove build artifacts and dependencies
|
|
|
|
|
# make clean-deps Remove only dependencies
|
|
|
|
|
# make clean-cache Clear ccache
|
|
|
|
|
# make update Fetch/update all dependencies
|
|
|
|
|
# make vendor-sdl Vendor SDL3 from source
|
|
|
|
|
# make help Show available targets
|
|
|
|
|
#
|
|
|
|
|
# Variables:
|
|
|
|
|
# MODE=release Build in release mode (default: debug)
|
|
|
|
|
# CART=demo Cart/script to run (default: demo)
|
|
|
|
|
# PROFILE_DURATION=30 Perf recording seconds (default: 30)
|
|
|
|
|
# ASE_CMD= Aseprite subcommand (package, clean, ...)
|
|
|
|
|
|
|
|
|
|
export PATH := $(PATH):/usr/bin:/bin
|
|
|
|
|
|
2026-04-12 14:46:29 -05:00
|
|
|
# -- Colors -------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
GREEN := \033[1;38;2;184;187;38m
|
|
|
|
|
YELLOW := \033[1;38;2;250;189;47m
|
|
|
|
|
RED := \033[1;38;2;251;73;52m
|
|
|
|
|
CYAN := \033[1;38;2;131;165;152m
|
|
|
|
|
NC := \033[0m
|
|
|
|
|
|
|
|
|
|
INFO = @printf '$(GREEN)[%s INFO]$(NC) %s\n' "$$(date +%H:%M:%S)"
|
|
|
|
|
WARN = @printf '$(YELLOW)[%s WARN]$(NC) %s\n' "$$(date +%H:%M:%S)"
|
|
|
|
|
ERROR = @printf '$(RED)[%s ERROR]$(NC) %s\n' "$$(date +%H:%M:%S)"
|
|
|
|
|
CC_ = @printf '$(CYAN)[%s CC]$(NC) %s\n' "$$(date +%H:%M:%S)"
|
|
|
|
|
SHD_ = @printf '$(CYAN)[%s SHADER]$(NC) %s\n' "$$(date +%H:%M:%S)"
|
|
|
|
|
|
2026-04-12 14:32:14 -05:00
|
|
|
# -- Platform detection -------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
UNAME := $(shell uname)
|
|
|
|
|
PLATFORM := posix
|
|
|
|
|
|
|
|
|
|
ifneq (,$(findstring MINGW,$(UNAME)))
|
|
|
|
|
PLATFORM := windows
|
|
|
|
|
endif
|
|
|
|
|
ifneq (,$(findstring MSYS,$(UNAME)))
|
|
|
|
|
PLATFORM := windows
|
|
|
|
|
endif
|
|
|
|
|
ifneq (,$(findstring CYGWIN,$(UNAME)))
|
|
|
|
|
PLATFORM := windows
|
|
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
# -- Toolchain ----------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
CC := clang
|
|
|
|
|
CCACHE := $(shell command -v ccache 2>/dev/null)
|
|
|
|
|
ifdef CCACHE
|
|
|
|
|
CC := ccache $(CC)
|
|
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
NPROC := $(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
|
|
|
|
|
|
|
|
|
|
# -- Directories --------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
BUILDDIR = .build/$(MODE)
|
|
|
|
|
OBJDIR = $(BUILDDIR)/obj
|
|
|
|
|
BINDIR = bin/$(MODE)
|
|
|
|
|
SHADERDIR = $(BUILDDIR)/shaders/cpu
|
|
|
|
|
|
|
|
|
|
# -- Mode (debug/release) ----------------------------------------------------
|
|
|
|
|
|
|
|
|
|
MODE ?= debug
|
|
|
|
|
|
|
|
|
|
ifeq ($(MODE),release)
|
|
|
|
|
CFLAGS = -std=c23 -Wall -Wextra -Wno-missing-braces \
|
|
|
|
|
-O3 -flto -ffast-math -funroll-loops \
|
|
|
|
|
-fno-unwind-tables -fno-asynchronous-unwind-tables
|
|
|
|
|
LDFLAGS = -flto
|
2026-04-12 17:43:43 -05:00
|
|
|
STRIP = true
|
2026-04-12 14:32:14 -05:00
|
|
|
else
|
|
|
|
|
CFLAGS = -std=c23 -Wall -Wextra -Wno-missing-braces -g -O1 -DDEBUG
|
|
|
|
|
LDFLAGS =
|
2026-04-12 17:43:43 -05:00
|
|
|
STRIP = false
|
2026-04-12 14:32:14 -05:00
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
DEP_CFLAGS = -O3 -funroll-loops -MMD -MP
|
|
|
|
|
CFLAGS += -MMD -MP
|
|
|
|
|
|
|
|
|
|
# -- Linker -------------------------------------------------------------------
|
|
|
|
|
|
2026-04-12 17:43:43 -05:00
|
|
|
ifeq ($(PLATFORM),windows)
|
|
|
|
|
LDFLAGS += -fuse-ld=lld
|
|
|
|
|
else
|
|
|
|
|
MOLD := $(shell command -v mold 2>/dev/null)
|
|
|
|
|
ifdef MOLD
|
|
|
|
|
LDFLAGS += -fuse-ld=mold
|
|
|
|
|
endif
|
2026-04-12 14:32:14 -05:00
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
ifeq ($(PLATFORM),windows)
|
|
|
|
|
LIBS = -lws2_32
|
2026-04-12 14:46:29 -05:00
|
|
|
LDFLAGS += -Wl,/SUBSYSTEM:CONSOLE
|
2026-04-12 14:32:14 -05:00
|
|
|
PXL8_DEF = $(BUILDDIR)/pxl8.def
|
|
|
|
|
EXE_EXT = .exe
|
|
|
|
|
else ifeq ($(UNAME),Darwin)
|
|
|
|
|
LIBS = -lm
|
|
|
|
|
export MACOSX_DEPLOYMENT_TARGET := $(shell sw_vers -productVersion | cut -d '.' -f 1)
|
|
|
|
|
else
|
|
|
|
|
LIBS = -lm
|
|
|
|
|
LDFLAGS += -rdynamic
|
|
|
|
|
LIBS += -ldl
|
|
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
EXE_EXT ?=
|
|
|
|
|
|
|
|
|
|
# -- SDL3 detection -----------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
ifeq ($(PLATFORM),windows)
|
|
|
|
|
# Windows: always vendor SDL3, ship SDL3.dll alongside the .exe
|
|
|
|
|
SDL3_BUILD_DIR := $(firstword $(wildcard lib/SDL/build/Release lib/SDL/build/Debug))
|
|
|
|
|
ifneq ($(SDL3_BUILD_DIR),)
|
|
|
|
|
SDL3_CFLAGS = -Ilib/SDL/include
|
|
|
|
|
SDL3_LIBS = -L$(SDL3_BUILD_DIR) -lSDL3
|
|
|
|
|
HAS_SDL3 = 1
|
|
|
|
|
endif
|
|
|
|
|
else
|
|
|
|
|
# Unix: check vendored build, then system
|
|
|
|
|
ifneq (,$(wildcard lib/SDL/build/libSDL3.*))
|
|
|
|
|
SDL3_CFLAGS = -Ilib/SDL/include
|
|
|
|
|
SDL3_LIBS = -Llib/SDL/build -lSDL3 -Wl,-rpath,$(CURDIR)/lib/SDL/build
|
|
|
|
|
HAS_SDL3 = 1
|
|
|
|
|
else
|
|
|
|
|
SDL3_CFLAGS := $(shell pkg-config --cflags sdl3 2>/dev/null)
|
|
|
|
|
SDL3_LIBS := $(shell pkg-config --libs sdl3 2>/dev/null)
|
|
|
|
|
ifneq ($(SDL3_LIBS),)
|
|
|
|
|
HAS_SDL3 = 1
|
|
|
|
|
endif
|
|
|
|
|
endif
|
|
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
CFLAGS += $(SDL3_CFLAGS)
|
|
|
|
|
LIBS += $(SDL3_LIBS)
|
|
|
|
|
|
|
|
|
|
# -- Linenoise ----------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
ifeq ($(PLATFORM),windows)
|
|
|
|
|
LINENOISE_DIR = lib/linenoise-win32
|
|
|
|
|
LINENOISE_SRCS = $(LINENOISE_DIR)/linenoise.c $(LINENOISE_DIR)/stringbuf.c $(LINENOISE_DIR)/utf8.c
|
|
|
|
|
CFLAGS += -DPXL8_WIN32_LINENOISE -D_CRT_SECURE_NO_WARNINGS
|
|
|
|
|
else
|
|
|
|
|
LINENOISE_DIR = lib/linenoise
|
|
|
|
|
LINENOISE_SRCS = $(LINENOISE_DIR)/linenoise.c
|
|
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
# -- LuaJIT ------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
LUAJIT_LIB = lib/luajit/src/libluajit.a
|
|
|
|
|
|
|
|
|
|
ifeq ($(PLATFORM),windows)
|
|
|
|
|
LUAJIT_BUILD = $(MAKE) -C lib/luajit -j$(NPROC) \
|
|
|
|
|
CC="$(firstword $(CC))" HOST_CC="$(firstword $(CC))" \
|
|
|
|
|
TARGET_SYS=Windows BUILDMODE=static \
|
|
|
|
|
MINILUA_LIBS= TARGET_XLIBS= Q=
|
|
|
|
|
else
|
|
|
|
|
LUAJIT_BUILD = $(MAKE) -C lib/luajit -j$(NPROC) \
|
|
|
|
|
CC="$(firstword $(CC))" HOST_CC="$(firstword $(CC))" Q= > /dev/null 2>&1
|
|
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
# -- Include paths ------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
INCLUDES = \
|
|
|
|
|
-Isrc/asset -Isrc/bsp -Isrc/core -Isrc/gfx -Isrc/gui -Isrc/hal \
|
|
|
|
|
-Isrc/math -Isrc/net -Isrc/procgen -Isrc/script -Isrc/shader \
|
|
|
|
|
-Isrc/sfx -Isrc/sim -Isrc/world \
|
|
|
|
|
-I$(LINENOISE_DIR) -Ilib/luajit/src -Ilib/miniz -I.build/shaders/c
|
|
|
|
|
|
|
|
|
|
# -- Source files -------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
LIB_SRCS = $(LINENOISE_SRCS) lib/miniz/miniz.c
|
|
|
|
|
|
|
|
|
|
PXL8_SRCS = \
|
|
|
|
|
src/asset/pxl8_ase.c \
|
|
|
|
|
src/asset/pxl8_cart.c \
|
|
|
|
|
src/asset/pxl8_save.c \
|
|
|
|
|
src/bsp/pxl8_bsp.c \
|
|
|
|
|
src/bsp/pxl8_bsp_render.c \
|
|
|
|
|
src/core/pxl8.c \
|
|
|
|
|
src/core/pxl8_bytes.c \
|
|
|
|
|
src/core/pxl8_io.c \
|
|
|
|
|
src/core/pxl8_log.c \
|
|
|
|
|
src/core/pxl8_replay.c \
|
|
|
|
|
src/core/pxl8_rng.c \
|
|
|
|
|
src/gfx/pxl8_3d_camera.c \
|
|
|
|
|
src/gfx/pxl8_anim.c \
|
|
|
|
|
src/gfx/pxl8_atlas.c \
|
|
|
|
|
src/gfx/pxl8_blit.c \
|
|
|
|
|
src/gfx/pxl8_colormap.c \
|
|
|
|
|
src/gfx/pxl8_dither.c \
|
|
|
|
|
src/gfx/pxl8_render.c \
|
|
|
|
|
src/gfx/pxl8_shader_registry.c \
|
|
|
|
|
src/gfx/pxl8_shader_runtime.c \
|
|
|
|
|
src/gfx/pxl8_font.c \
|
|
|
|
|
src/gfx/pxl8_gfx.c \
|
|
|
|
|
src/gfx/pxl8_glows.c \
|
|
|
|
|
src/gfx/pxl8_lightmap.c \
|
|
|
|
|
src/gfx/pxl8_lights.c \
|
|
|
|
|
src/gfx/pxl8_mesh.c \
|
|
|
|
|
src/gfx/pxl8_palette.c \
|
|
|
|
|
src/gfx/pxl8_particles.c \
|
|
|
|
|
src/gfx/pxl8_tilemap.c \
|
|
|
|
|
src/gfx/pxl8_tilesheet.c \
|
|
|
|
|
src/gfx/pxl8_transition.c \
|
|
|
|
|
src/gui/pxl8_gui.c \
|
|
|
|
|
src/hal/pxl8_hal_sdl3.c \
|
|
|
|
|
src/hal/pxl8_thread_sdl3.c \
|
|
|
|
|
src/math/pxl8_math.c \
|
|
|
|
|
src/math/pxl8_noise.c \
|
|
|
|
|
src/net/pxl8_net.c \
|
|
|
|
|
src/net/pxl8_protocol.c \
|
|
|
|
|
src/procgen/pxl8_graph.c \
|
|
|
|
|
src/script/pxl8_repl.c \
|
|
|
|
|
src/script/pxl8_script.c \
|
|
|
|
|
src/sfx/pxl8_sfx.c \
|
|
|
|
|
src/sim/pxl8_sim.c \
|
|
|
|
|
src/world/pxl8_entity.c \
|
|
|
|
|
src/world/pxl8_world.c \
|
|
|
|
|
src/world/pxl8_world_chunk.c \
|
|
|
|
|
src/world/pxl8_world_chunk_cache.c
|
|
|
|
|
|
|
|
|
|
ifeq ($(HAS_SDL3),1)
|
|
|
|
|
PXL8_SRCS += src/hal/pxl8_io_sdl3.c src/hal/pxl8_mem_sdl3.c
|
|
|
|
|
else
|
|
|
|
|
PXL8_SRCS += src/hal/pxl8_mem.c
|
|
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
# -- Object files -------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
LIB_OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(LIB_SRCS)))
|
|
|
|
|
PXL8_OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(PXL8_SRCS)))
|
|
|
|
|
ALL_OBJS = $(LIB_OBJS) $(PXL8_OBJS)
|
|
|
|
|
|
|
|
|
|
# -- Shader objects -----------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
SHADER_SRCS = $(wildcard src/gfx/shaders/cpu/*.c)
|
|
|
|
|
SHADER_OBJS = $(patsubst src/gfx/shaders/cpu/%.c,$(SHADERDIR)/obj/%.o,$(SHADER_SRCS))
|
|
|
|
|
SHADER_INCLUDES = -Isrc/core -Isrc/gfx -Isrc/math
|
|
|
|
|
|
|
|
|
|
# -- Targets ------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
CLIENT = $(BINDIR)/pxl8$(EXE_EXT)
|
|
|
|
|
SERVER = $(BINDIR)/pxl8d$(EXE_EXT)
|
|
|
|
|
|
|
|
|
|
CART ?= demo
|
|
|
|
|
PROFILE_DURATION ?= 30
|
|
|
|
|
ASE_CMD ?=
|
|
|
|
|
|
|
|
|
|
.PHONY: all release client server run clean clean-all clean-deps clean-cache \
|
|
|
|
|
update vendor-sdl deps luajit install ase profile help
|
|
|
|
|
|
|
|
|
|
all: client server
|
|
|
|
|
|
|
|
|
|
release:
|
|
|
|
|
$(MAKE) MODE=release all
|
|
|
|
|
|
|
|
|
|
# -- Dependencies -------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
DEPS_OK = lib/luajit/src/luajit.c lib/miniz/miniz.c lib/fennel/fennel.lua $(LINENOISE_DIR)/linenoise.c
|
|
|
|
|
|
|
|
|
|
deps: $(DEPS_OK)
|
|
|
|
|
|
|
|
|
|
lib/luajit/src/luajit.c:
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Fetching LuaJIT"
|
2026-04-12 14:32:14 -05:00
|
|
|
@rm -rf lib/luajit
|
|
|
|
|
@git clone --quiet --branch v2.1 https://github.com/LuaJIT/LuaJIT.git lib/luajit
|
|
|
|
|
|
|
|
|
|
lib/linenoise/linenoise.c:
|
|
|
|
|
@mkdir -p lib/linenoise
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Fetching linenoise"
|
2026-04-12 14:32:14 -05:00
|
|
|
@curl -sL -o lib/linenoise/linenoise.c https://raw.githubusercontent.com/antirez/linenoise/master/linenoise.c
|
|
|
|
|
@curl -sL -o lib/linenoise/linenoise.h https://raw.githubusercontent.com/antirez/linenoise/master/linenoise.h
|
|
|
|
|
|
|
|
|
|
lib/linenoise-win32/linenoise.c:
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Fetching linenoise-win32"
|
2026-04-12 14:32:14 -05:00
|
|
|
@rm -rf lib/linenoise-win32
|
|
|
|
|
@git clone --quiet --depth 1 https://github.com/msteveb/linenoise.git lib/linenoise-win32
|
|
|
|
|
|
|
|
|
|
lib/miniz/miniz.c:
|
|
|
|
|
@mkdir -p lib/miniz
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Fetching miniz"
|
2026-04-12 14:32:14 -05:00
|
|
|
@curl -sL -o /tmp/miniz.zip "https://github.com/richgel999/miniz/releases/download/3.1.0/miniz-3.1.0.zip"
|
|
|
|
|
@unzip -qjo /tmp/miniz.zip miniz.c miniz.h -d lib/miniz/
|
|
|
|
|
@rm -f /tmp/miniz.zip
|
|
|
|
|
|
|
|
|
|
lib/fennel/fennel.lua:
|
|
|
|
|
@mkdir -p lib/fennel
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Fetching Fennel"
|
2026-04-12 14:32:14 -05:00
|
|
|
@curl -sL -o lib/fennel/fennel.lua "https://fennel-lang.org/downloads/fennel-1.6.1.lua"
|
|
|
|
|
|
|
|
|
|
update:
|
|
|
|
|
@rm -f lib/linenoise/linenoise.c lib/miniz/miniz.c lib/fennel/fennel.lua
|
|
|
|
|
@rm -rf lib/luajit lib/linenoise-win32
|
|
|
|
|
$(MAKE) deps
|
|
|
|
|
|
|
|
|
|
vendor-sdl:
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Fetching SDL3"
|
2026-04-12 14:32:14 -05:00
|
|
|
@if [ -d lib/SDL/.git ]; then cd lib/SDL && git pull --quiet origin main; \
|
|
|
|
|
else rm -rf lib/SDL && git clone --quiet https://github.com/libsdl-org/SDL.git lib/SDL; fi
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Building SDL3"
|
2026-04-12 14:32:14 -05:00
|
|
|
@mkdir -p lib/SDL/build && cd lib/SDL/build && \
|
|
|
|
|
cmake .. -DCMAKE_BUILD_TYPE=Release && \
|
|
|
|
|
cmake --build . --config Release --parallel $(NPROC)
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Built SDL3"
|
2026-04-12 14:32:14 -05:00
|
|
|
|
|
|
|
|
# -- LuaJIT build ------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
luajit: $(LUAJIT_LIB)
|
|
|
|
|
|
|
|
|
|
$(LUAJIT_LIB): lib/luajit/src/luajit.c
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Building LuaJIT"
|
2026-04-12 14:32:14 -05:00
|
|
|
@$(LUAJIT_BUILD)
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Built LuaJIT"
|
2026-04-12 14:32:14 -05:00
|
|
|
|
|
|
|
|
# -- Server (Rust) ------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
server: $(SERVER)
|
|
|
|
|
|
|
|
|
|
$(SERVER): $(wildcard pxl8d/src/*.rs pxl8d/Cargo.toml)
|
|
|
|
|
@mkdir -p $(BINDIR)
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Building pxl8d ($(MODE) mode)"
|
2026-04-12 14:32:14 -05:00
|
|
|
ifeq ($(MODE),release)
|
|
|
|
|
@cd pxl8d && PATH="$$(echo $$PATH | tr ':' '\n' | grep -v '/usr/bin' | tr '\n' ':')" cargo build --release --quiet
|
|
|
|
|
@cp pxl8d/target/release/pxl8d$(EXE_EXT) $(SERVER)
|
|
|
|
|
else
|
|
|
|
|
@cd pxl8d && PATH="$$(echo $$PATH | tr ':' '\n' | grep -v '/usr/bin' | tr '\n' ':')" cargo build --quiet
|
|
|
|
|
@cp pxl8d/target/debug/pxl8d$(EXE_EXT) $(SERVER)
|
|
|
|
|
endif
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Built pxl8d"
|
2026-04-12 14:32:14 -05:00
|
|
|
|
|
|
|
|
# -- Client (C23) -------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
client: deps $(CLIENT)
|
|
|
|
|
|
|
|
|
|
$(CLIENT): $(ALL_OBJS) $(SHADER_OBJS) $(LUAJIT_LIB)
|
|
|
|
|
@mkdir -p $(BINDIR)
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Linking pxl8"
|
2026-04-12 14:32:14 -05:00
|
|
|
ifeq ($(PLATFORM),windows)
|
|
|
|
|
@(echo EXPORTS && llvm-nm --defined-only $(ALL_OBJS) $(SHADER_OBJS) | grep ' T pxl8_\| T SDL' | awk '{print $$3}') > $(PXL8_DEF)
|
|
|
|
|
@MSYS_NO_PATHCONV=1 $(CC) $(LDFLAGS) $(ALL_OBJS) $(SHADER_OBJS) $(LUAJIT_LIB) $(LIBS) -Wl,/DEF:$(PXL8_DEF) -o $@
|
|
|
|
|
@cp -u $(SDL3_BUILD_DIR)/SDL3.dll $(BINDIR)/
|
|
|
|
|
else
|
|
|
|
|
@$(CC) $(LDFLAGS) $(ALL_OBJS) $(SHADER_OBJS) $(LUAJIT_LIB) $(LIBS) -o $@
|
2026-04-12 17:43:43 -05:00
|
|
|
endif
|
|
|
|
|
ifeq ($(STRIP),true)
|
|
|
|
|
@llvm-strip $@
|
2026-04-12 14:32:14 -05:00
|
|
|
endif
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Built pxl8 -> $@"
|
2026-04-12 14:32:14 -05:00
|
|
|
|
|
|
|
|
# -- Compile rules ------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
# Lib sources (dep flags, no warnings)
|
|
|
|
|
$(OBJDIR)/linenoise.o: $(LINENOISE_DIR)/linenoise.c | $(OBJDIR)
|
2026-04-12 14:46:29 -05:00
|
|
|
$(CC_) "$<"
|
2026-04-12 14:32:14 -05:00
|
|
|
@$(CC) -c $(DEP_CFLAGS) $(INCLUDES) $< -o $@
|
|
|
|
|
|
|
|
|
|
$(OBJDIR)/stringbuf.o: $(LINENOISE_DIR)/stringbuf.c | $(OBJDIR)
|
2026-04-12 14:46:29 -05:00
|
|
|
$(CC_) "$<"
|
2026-04-12 14:32:14 -05:00
|
|
|
@$(CC) -c $(DEP_CFLAGS) $(INCLUDES) $< -o $@
|
|
|
|
|
|
|
|
|
|
$(OBJDIR)/utf8.o: $(LINENOISE_DIR)/utf8.c | $(OBJDIR)
|
2026-04-12 14:46:29 -05:00
|
|
|
$(CC_) "$<"
|
2026-04-12 14:32:14 -05:00
|
|
|
@$(CC) -c $(DEP_CFLAGS) $(INCLUDES) $< -o $@
|
|
|
|
|
|
|
|
|
|
$(OBJDIR)/miniz.o: lib/miniz/miniz.c | $(OBJDIR)
|
2026-04-12 14:46:29 -05:00
|
|
|
$(CC_) "$<"
|
2026-04-12 14:32:14 -05:00
|
|
|
@$(CC) -c $(DEP_CFLAGS) $(INCLUDES) $< -o $@
|
|
|
|
|
|
|
|
|
|
# Pattern rules for pxl8 sources by directory
|
|
|
|
|
define PXL8_COMPILE_RULE
|
|
|
|
|
$(OBJDIR)/%.o: $(1)/%.c | $(OBJDIR)
|
2026-04-12 14:46:29 -05:00
|
|
|
@printf '$(CYAN)[%s CC]$(NC) %s\n' "$$$$(date +%H:%M:%S)" "$$<"
|
2026-04-12 14:32:14 -05:00
|
|
|
@$$(CC) -c $$(CFLAGS) $$(INCLUDES) $$< -o $$@
|
|
|
|
|
endef
|
|
|
|
|
|
|
|
|
|
$(foreach dir,src/asset src/bsp src/core src/gfx src/gui src/hal src/math src/net src/procgen src/script src/shader src/sfx src/sim src/world,$(eval $(call PXL8_COMPILE_RULE,$(dir))))
|
|
|
|
|
|
|
|
|
|
# pxl8_script.o depends on embedded Lua/Fennel sources
|
|
|
|
|
LUA_SRCS = $(wildcard src/lua/*.lua src/lua/pxl8/*.lua) lib/fennel/fennel.lua
|
|
|
|
|
$(OBJDIR)/pxl8_script.o: $(LUA_SRCS)
|
|
|
|
|
|
|
|
|
|
# Shader objects
|
|
|
|
|
$(SHADERDIR)/obj/%.o: src/gfx/shaders/cpu/%.c | $(SHADERDIR)/obj
|
2026-04-12 14:46:29 -05:00
|
|
|
$(SHD_) "$<"
|
2026-04-12 14:32:14 -05:00
|
|
|
@$(CC) -c -O2 $(SHADER_INCLUDES) $< -o $@
|
|
|
|
|
|
|
|
|
|
# -- Directory creation -------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
$(OBJDIR) $(SHADERDIR)/obj:
|
|
|
|
|
@mkdir -p $@
|
|
|
|
|
|
|
|
|
|
# -- Gitignore bookkeeping ---------------------------------------------------
|
|
|
|
|
|
|
|
|
|
$(shell mkdir -p bin .build lib 2>/dev/null)
|
|
|
|
|
$(shell [ -f bin/.gitignore ] || echo '*' > bin/.gitignore)
|
|
|
|
|
$(shell [ -f .build/.gitignore ] || echo '*' > .build/.gitignore)
|
|
|
|
|
$(shell [ -f lib/.gitignore ] || echo '*' > lib/.gitignore)
|
|
|
|
|
|
|
|
|
|
# -- Run ----------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
run: all
|
|
|
|
|
@$(BINDIR)/pxl8d$(EXE_EXT) & SERVER_PID=$$!; \
|
|
|
|
|
sleep 0.5; \
|
|
|
|
|
$(BINDIR)/pxl8$(EXE_EXT) $(CART) || true; \
|
|
|
|
|
kill $$SERVER_PID 2>/dev/null; wait $$SERVER_PID 2>/dev/null || true
|
|
|
|
|
|
|
|
|
|
# -- Clean --------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
clean:
|
|
|
|
|
rm -rf .build/debug .build/release bin/debug bin/release .build/shaders
|
|
|
|
|
@if [ -d pxl8d ]; then cd pxl8d && cargo clean 2>/dev/null; fi || true
|
|
|
|
|
|
|
|
|
|
clean-all: clean
|
|
|
|
|
rm -rf lib
|
|
|
|
|
|
|
|
|
|
clean-deps:
|
|
|
|
|
rm -rf lib
|
|
|
|
|
|
|
|
|
|
clean-cache:
|
|
|
|
|
@if command -v ccache >/dev/null 2>&1; then ccache -C; else echo "ccache not found"; fi
|
|
|
|
|
|
|
|
|
|
# -- Install ------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
install:
|
|
|
|
|
$(MAKE) MODE=release client
|
|
|
|
|
@mkdir -p $(HOME)/.local/bin
|
|
|
|
|
@cp bin/release/pxl8$(EXE_EXT) $(HOME)/.local/bin/pxl8$(EXE_EXT)
|
|
|
|
|
@chmod +x $(HOME)/.local/bin/pxl8$(EXE_EXT)
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Installed pxl8 to $(HOME)/.local/bin/pxl8$(EXE_EXT)"
|
2026-04-12 14:32:14 -05:00
|
|
|
|
|
|
|
|
# -- Aseprite tools -----------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
ase:
|
|
|
|
|
@bash tools/aseprite/pxl8-ase.sh $(ASE_CMD)
|
|
|
|
|
|
|
|
|
|
# -- Profile (Linux) ----------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
profile: client
|
2026-04-12 14:46:29 -05:00
|
|
|
@if [ "$$(uname)" != "Linux" ]; then printf '$(RED)[ERROR]$(NC) %s\n' "Profiling requires Linux + perf"; exit 1; fi
|
|
|
|
|
@if ! command -v perf >/dev/null 2>&1; then printf '$(RED)[ERROR]$(NC) %s\n' "perf not found"; exit 1; fi
|
2026-04-12 14:32:14 -05:00
|
|
|
@if [ ! -d lib/FlameGraph ]; then \
|
|
|
|
|
echo "[INFO] Fetching FlameGraph"; \
|
|
|
|
|
git clone --quiet https://github.com/brendangregg/FlameGraph.git lib/FlameGraph; \
|
|
|
|
|
fi
|
|
|
|
|
@mkdir -p .build/$(MODE)/profile; \
|
|
|
|
|
TIMESTAMP=$$(date +%Y%m%d_%H%M%S); \
|
|
|
|
|
PDIR=.build/$(MODE)/profile; \
|
|
|
|
|
echo "[INFO] Starting server..."; \
|
|
|
|
|
$(BINDIR)/pxl8d$(EXE_EXT) & SERVER_PID=$$!; \
|
|
|
|
|
sleep 0.5; \
|
|
|
|
|
echo "[INFO] Profiling for $(PROFILE_DURATION)s (Ctrl+C to stop early)..."; \
|
|
|
|
|
perf record -F 99 -g --call-graph dwarf -o $$PDIR/perf_$$TIMESTAMP.data -- \
|
|
|
|
|
timeout $(PROFILE_DURATION)s $(BINDIR)/pxl8$(EXE_EXT) $(CART) 2>/dev/null || true; \
|
|
|
|
|
kill $$SERVER_PID 2>/dev/null; wait $$SERVER_PID 2>/dev/null || true; \
|
|
|
|
|
echo "[INFO] Generating flamegraph..."; \
|
|
|
|
|
perf script -i $$PDIR/perf_$$TIMESTAMP.data > $$PDIR/perf_$$TIMESTAMP.perf; \
|
|
|
|
|
lib/FlameGraph/stackcollapse-perf.pl $$PDIR/perf_$$TIMESTAMP.perf > $$PDIR/perf_$$TIMESTAMP.folded; \
|
|
|
|
|
lib/FlameGraph/flamegraph.pl --cp --colors orange --title "pxl8 profile" \
|
|
|
|
|
$$PDIR/perf_$$TIMESTAMP.folded > $$PDIR/flamegraph_$$TIMESTAMP.svg; \
|
|
|
|
|
rm -f $$PDIR/perf_$$TIMESTAMP.data $$PDIR/perf_$$TIMESTAMP.perf $$PDIR/perf_$$TIMESTAMP.folded; \
|
|
|
|
|
echo "[INFO] Flamegraph: $$PDIR/flamegraph_$$TIMESTAMP.svg"; \
|
|
|
|
|
command -v xdg-open >/dev/null 2>&1 && xdg-open $$PDIR/flamegraph_$$TIMESTAMP.svg 2>/dev/null &
|
|
|
|
|
|
|
|
|
|
# -- Help ---------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
help:
|
|
|
|
|
@echo "pxl8 - framework build system"
|
|
|
|
|
@echo ""
|
|
|
|
|
@echo "TARGETS:"
|
|
|
|
|
@echo " make Build everything (debug)"
|
|
|
|
|
@echo " make release Build everything (release)"
|
|
|
|
|
@echo " make run Build and run (CART=\"demo --repl\")"
|
|
|
|
|
@echo " make client Build pxl8 only"
|
|
|
|
|
@echo " make server Build pxl8d only"
|
|
|
|
|
@echo " make install Install to ~/.local/bin (release)"
|
|
|
|
|
@echo " make profile Profile with perf (PROFILE_DURATION=30, Linux only)"
|
|
|
|
|
@echo " make ase Aseprite tools (ASE_CMD=package|clean)"
|
|
|
|
|
@echo " make clean Remove build artifacts"
|
|
|
|
|
@echo " make clean-all Remove artifacts + dependencies"
|
|
|
|
|
@echo " make clean-deps Remove only dependencies"
|
|
|
|
|
@echo " make clean-cache Clear ccache"
|
|
|
|
|
@echo " make update Fetch/update all dependencies"
|
|
|
|
|
@echo " make vendor-sdl Vendor SDL3 from source"
|
|
|
|
|
@echo ""
|
|
|
|
|
@echo "VARIABLES:"
|
|
|
|
|
@echo " MODE=release Build mode (default: debug)"
|
|
|
|
|
@echo " CART=demo Cart or script to run"
|
|
|
|
|
|
|
|
|
|
# -- Auto-generated header dependencies --------------------------------------
|
|
|
|
|
|
|
|
|
|
-include $(ALL_OBJS:.o=.d)
|
|
|
|
|
-include $(SHADER_OBJS:.o=.d)
|
|
|
|
|
|
|
|
|
|
# -- compile_commands.json ----------------------------------------------------
|
|
|
|
|
|
|
|
|
|
compile_commands.json: $(LIB_SRCS) $(PXL8_SRCS)
|
2026-04-12 14:46:29 -05:00
|
|
|
$(INFO) "Generating compile_commands.json"
|
2026-04-12 14:32:14 -05:00
|
|
|
@echo '[' > $@.tmp
|
|
|
|
|
@first=true; \
|
|
|
|
|
for f in $(LIB_SRCS); do \
|
|
|
|
|
if $$first; then first=false; else printf ',\n' >> $@.tmp; fi; \
|
|
|
|
|
printf ' {"directory":"%s","command":"clang -c %s %s","file":"%s"}' \
|
|
|
|
|
"$(CURDIR)" "$(DEP_CFLAGS) $(INCLUDES)" "$$f" "$$f" >> $@.tmp; \
|
|
|
|
|
done; \
|
|
|
|
|
for f in $(PXL8_SRCS); do \
|
|
|
|
|
if $$first; then first=false; else printf ',\n' >> $@.tmp; fi; \
|
|
|
|
|
printf ' {"directory":"%s","command":"clang -c %s %s","file":"%s"}' \
|
|
|
|
|
"$(CURDIR)" "$(CFLAGS) $(INCLUDES)" "$$f" "$$f" >> $@.tmp; \
|
|
|
|
|
done
|
|
|
|
|
@printf '\n]\n' >> $@.tmp
|
|
|
|
|
@mv $@.tmp $@
|