1# zbanks/alttp, the C bot, built from its own sources. `zbanks-alttp/` is 2# upstream's tree byte for byte; everything a host needs is outside it 3# (../../packages/zbanks). The few changes to the bot itself are the carried 4# patches in `patches/`, applied at build time by `:patched` below, so a 5# patch that stops applying after a refresh fails the build instead of 6# silently going missing. The flags are upstream's Makefile CFLAGS, less 7# three things a different compiler forces - see README.md. 8 9_SRCS = [ 10 "alttp.c", 11 "ap_map.c", 12 "ap_snes.c", 13 "ap_plan.c", 14 "ap_req.c", 15 "ap_item.c", 16 "pm.c", 17 "pq.c", 18 "lb.c", 19] 20 21_HEADERS = [ 22 "alttp_public.h", 23 "ap_item.h", 24 "ap_macro.h", 25 "ap_map.h", 26 "ap_math.h", 27 "ap_plan.h", 28 "ap_req.h", 29 "ap_snes.h", 30 "bm.h", 31 "lb.h", 32 "pm.h", 33 "pq.h", 34] 35 36_PATCHES = glob(["patches/*.patch"]) 37 38# Upstream's sources with `patches/*.patch` applied in name order. `patch` 39# refuses a hunk that does not match, and the genrule fails with it. 40genrule( 41 name = "patched", 42 srcs = ["zbanks-alttp/" + f for f in _SRCS + _HEADERS] + _PATCHES, 43 outs = {f: [f] for f in _SRCS + _HEADERS}, 44 cmd = " && ".join([ 45 "cp " + " ".join(["$SRCDIR/zbanks-alttp/" + f for f in _SRCS + _HEADERS]) + " $OUT/", 46 "chmod u+w $OUT/*", 47 "for p in $SRCDIR/patches/*.patch; do patch --batch --forward -p4 -d $OUT < $p || exit 1; done", 48 ]), 49) 50 51cxx_library( 52 name = "zbanks-alttp", 53 srcs = [ 54 # ap_map.c creates every goal (ap_goal_add, as it adds each node). 55 # Renaming the calls there sends them through the host 56 # (../../packages/zbanks/shim/host.c, zb_goal_add), which declines a 57 # goal the save says is already done - uncle, on a start from a 58 # mid-game state with an imported map - and otherwise calls the real 59 # ap_goal_add in ap_plan.c, which is compiled without the rename. 60 (":patched[{}]".format(s), ["-Dap_goal_add=zb_goal_add"]) if s == "ap_map.c" else ":patched[{}]".format(s) 61 for s in _SRCS 62 ], 63 # Upstream compiles with `-I.` and includes its own headers both as 64 # "ap_macro.h" and <ap_macro.h>; bare names reproduce that. 65 exported_headers = {h: ":patched[{}]".format(h) for h in _HEADERS}, 66 header_namespace = "", 67 compiler_flags = [ 68 # Upstream's Makefile, verbatim, minus -Werror (below). 69 "-O3", 70 "-ggdb3", 71 "-Wall", 72 "-Wextra", 73 "-Wno-unused-parameter", 74 "-Wno-unused", 75 "-Wwrite-strings", 76 "-Wshadow", 77 "-std=c11", 78 "-D_DEFAULT_SOURCE", 79 # ap_snes.h DEFINES `bool ap_manual_mode;` and every .c includes it. 80 # gcc before 10 (upstream's era) merged such tentative definitions; 81 # clang 11+ and gcc 10+ default to -fno-common and fail the link with 82 # "multiple definition". -fcommon is the old default, restored. 83 "-fcommon", 84 # Upstream writes its debug files (goals.txt, map, map.pbm, 85 # full_map.dot, ...) with bare relative names, i.e. into whatever the 86 # process's working directory is - the repo root, for our apps. These 87 # two renames send every such fopen/rename through 88 # ../../packages/zbanks/shim/host.c, which puts them in the directory 89 # the host chose (run/zbanks-c/..., run/zbanks-window/). The call 90 # sites are untouched; only the symbol they bind to changes. 91 "-Dfopen=zb_fopen", 92 "-Drename=zb_rename", 93 # -Werror is dropped: upstream's code was warning-clean on ITS 94 # compiler; this one (clang 21) warns about things gcc of 2020 did 95 # not, and a warning is not a behaviour change. 96 ], 97 visibility = ["PUBLIC"], 98)