#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
#
# SYNOPSIS
#
#   Freestanding Hermetically-Sealed Monolithic Repository
#
# REQUIREMENTS
#
#   You can run your programs on any operating system, but you have
#   to build them on Linux 2.6+ (or WSL) using GNU Make. A modern C
#   compiler that's statically-linked comes included as a courtesy.
#
# EXAMPLES
#
#   # build and run everything
#   make -j8 -O
#   make -j8 -O MODE=dbg
#   make -j8 -O MODE=opt
#   make -j8 -O MODE=rel
#   make -j8 -O MODE=tiny
#
#   # build individual target
#   make -j8 -O o//examples/hello.com
#   o//examples/hello.com
#
#   # view source
#   less examples/hello.c
#
#   # view binary
#   o//tool/viz/bing.com o//examples/hello.com |
#     o//tool/viz/fold.com
#
#   # view transitive closure of legalese
#   o//tool/viz/bing.com -n o//examples/hello.com |
#     o//tool/viz/fold.com
#
#   # basic debugging
#   make -j8 -O MODE=dbg o/dbg/examples/crashreport.com
#   o/dbg/examples/crashreport.com
#   less examples/crashreport.c
#
#   # extremely tiny binaries (scout's honor escape hatch)
#   # please pay the $1k for commercial license if you can
#   make -j8 -O MODE=tiny				\
#               LDFLAGS+=-s				\
#               CPPFLAGS+=-DIM_FEELING_NAUGHTY	        \
#               CPPFLAGS+=-DSUPPORT_VECTOR=0b00000001	\
#               o/tiny/examples/hello4.elf
#   ls -hal o/tiny/examples/hello4.elf
#   o/tiny/examples/hello4.elf
#
# TROUBLESHOOTING
#
#   make -j8 -O SILENT=0 o//examples/hello.com
#   make o//examples/life.elf -pn |& less
#   etc.
#
# SEE ALSO
#
#   build/config.mk

SHELL = dash
HOSTS ?= freebsd openbsd alpine

.SUFFIXES:
.DELETE_ON_ERROR:
.FEATURES: output-sync
.PHONY: all o bins check test depend tags

all:	o
o:	o/libc					\
	o/$(MODE)/ape				\
	o/$(MODE)/dsp				\
	o/$(MODE)/net				\
	o/$(MODE)/libc				\
	o/$(MODE)/test				\
	o/$(MODE)/tool				\
	o/$(MODE)/examples			\
	o/$(MODE)/third_party

PKGS =

include build/functions.mk			#─┐
include build/definitions.mk			# ├──meta
include build/config.mk				# │
include build/rules.mk				# │
include build/online.mk				# │
include libc/stubs/stubs.mk			#─┘
include libc/nexgen32e/nexgen32e.mk		#─┐
include libc/intrin/intrin.mk			# │
include libc/math/math.mk			# ├──metal
include libc/tinymath/tinymath.mk		# │
include third_party/compiler_rt/compiler_rt.mk	# │
include libc/bits/bits.mk			# │
include libc/str/str.mk				# │
include third_party/xed/xed.mk			# │
include third_party/zlib/zlib.mk		# │
include libc/elf/elf.mk				# │
include ape/lib/apelib.mk			# │
include ape/ape.mk				#─┘
include libc/sysv/sysv.mk			#─┐
include libc/nt/nt.mk				# ├──system
include libc/conv/conv.mk			# │
include libc/fmt/fmt.mk				# │
include libc/rand/rand.mk			#─┘
include libc/calls/calls.mk			#─┐
include libc/runtime/runtime.mk			# ├──systems
include libc/unicode/unicode.mk			# │
include third_party/dlmalloc/dlmalloc.mk	# │
include libc/mem/mem.mk				# │
include libc/zipos/zipos.mk			# │
include third_party/dtoa/dtoa.mk		# │
include libc/time/time.mk			# │
include libc/escape/escape.mk			# │
include libc/alg/alg.mk				# │
include libc/calls/hefty/hefty.mk		# │
include libc/stdio/stdio.mk			# │
include third_party/f2c/f2c.mk			# │
include third_party/blas/blas.mk		# │
include net/net.mk				# │
include libc/log/log.mk				# │
include dsp/core/core.mk			# │
include libc/x/x.mk				# │
include third_party/stb/stb.mk			# │
include dsp/scale/scale.mk			# │
include dsp/mpeg/mpeg.mk			# │
include dsp/dsp.mk				# │
include third_party/musl/musl.mk		# │
include third_party/getopt/getopt.mk		# │
include libc/libc.mk				#─┘
include libc/sock/sock.mk			#─┐
include dsp/tty/tty.mk				# ├──online
include libc/dns/dns.mk				# │
include libc/crypto/crypto.mk			# │
include net/http/http.mk			#─┘
include third_party/linenoise/linenoise.mk
include third_party/editline/editline.mk
include third_party/duktape/duktape.mk
include third_party/regex/regex.mk
include third_party/avir/avir.mk
include third_party/third_party.mk
include libc/testlib/testlib.mk
include libc/crt/crt.mk
include tool/viz/lib/vizlib.mk
include examples/examples.mk
include third_party/lex/lex.mk
include third_party/m4/m4.mk
include third_party/lz4cli/lz4cli.mk
include third_party/bzip2/bzip2.mk
include tool/build/lib/buildlib.mk
include tool/build/build.mk
include tool/debug/debug.mk
include tool/decode/lib/decodelib.mk
include tool/decode/decode.mk
include tool/hash/hash.mk
include tool/net/net.mk
include tool/viz/viz.mk
include tool/cc/cc.mk
include tool/tool.mk
include test/libc/alg/test.mk
include test/libc/tinymath/test.mk
include test/libc/math/test.mk
include test/libc/intrin/test.mk
include test/libc/mem/test.mk
include test/libc/nexgen32e/test.mk
include test/libc/runtime/test.mk
include test/libc/sock/test.mk
include test/libc/bits/test.mk
include test/libc/crypto/test.mk
include test/libc/str/test.mk
include test/libc/unicode/test.mk
include test/libc/calls/test.mk
include test/libc/x/test.mk
include test/libc/xed/test.mk
include test/libc/fmt/test.mk
include test/libc/dns/test.mk
include test/libc/rand/test.mk
include test/libc/time/test.mk
include test/libc/stdio/test.mk
include test/libc/conv/test.mk
include test/libc/test.mk
include test/ape/lib/test.mk
include test/ape/test.mk
include test/net/http/test.mk
include test/net/test.mk
include test/tool/build/lib/test.mk
include test/tool/build/test.mk
include test/tool/viz/lib/test.mk
include test/tool/viz/test.mk
include test/tool/test.mk
include test/dsp/core/test.mk
include test/dsp/scale/test.mk
include test/dsp/tty/test.mk
include test/dsp/test.mk
include third_party/make/build.mk
#-φ-examples/package/new.sh
include test/test.mk

OBJS	= $(foreach x,$(PKGS),$($(x)_OBJS))
SRCS	= $(foreach x,$(PKGS),$($(x)_SRCS))
HDRS	= $(foreach x,$(PKGS),$($(x)_HDRS))
BINS	= $(foreach x,$(PKGS),$($(x)_BINS))
TESTS	= $(foreach x,$(PKGS),$($(x)_TESTS))
CHECKS	= $(foreach x,$(PKGS),$($(x)_CHECKS))

bins:	$(BINS)
check:	$(CHECKS)
test:	$(TESTS)
depend:	o/$(MODE)/depend
tags:	TAGS HTAGS

o/$(MODE)/.x:
	@mkdir -p $(dir $@) && touch $@

o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
	$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))

o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS),$(dir $(x))))
	$(file >$@) $(foreach x,$(HDRS),$(file >>$@,$(x)))

o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt $(SRCS) $(HDRS)
	@build/mkdeps -o $@ -r o/$(MODE)/ o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt

TAGS:	o/$(MODE)/srcs.txt $(SRCS)
	@rm -f $@
	@ACTION=TAGS TARGET=$@ build/do $(TAGS) $(TAGSFLAGS) -L $< -o $@

HTAGS:	o/$(MODE)/hdrs.txt $(HDRS)
	@rm -f $@
	@ACTION=TAGS TARGET=$@ build/do build/htags -L $< -o $@

loc:;	find -name \*.h -or -name \*.c -or -name \*.S | \
	$(XARGS) wc -l | grep total | awk '{print $$1}' | summy

# UNSPECIFIED PREREQUISITES TUTORIAL
#
# A build rule must exist for all files that make needs to consider in
# order to build the requested goal. That includes input source files,
# even if the rule is empty and does nothing. Otherwise, the .DEFAULT
# rule gets triggered.
#
# This is a normal and neecssary behavior when source files get deleted.
# The build reacts automatically to this happening, by simply deleting
# and regenerating the dependency graph; so we can safely use wildcard.
#
# This is abnormal if it needs to keep doing that repeatedly. That can
# only mean the build config is broken.
#
# Also note that a suboptimal in-between state may exist, where running
# `make -pn` reveals rules being generated with the .DEFAULT target, but
# never get executed since they're not members of the transitive closure
# of `make all`. In that case the build config could be improved.
%.mk:
$(SRCS):
$(HDRS):
.DEFAULT:
	@echo >&2
	@echo NOTE: deleting o/$(MODE)/depend due to unspecified prerequisite: $@ >&2
	@echo >&2
	rm -f o/$(MODE)/depend

-include o/$(MODE)/depend