aboutsummaryrefslogtreecommitdiff
.POSIX:
DATE         = 1970-01-01
VERSION      = 0.1.0
NAME         = grovel
NAME_UC      = $(NAME)
MAILING_LIST = public-inbox
LANGUAGES    =
## Installation prefix.  Defaults to "/usr".
PREFIX       = /usr
BINDIR       = $(PREFIX)/bin
LIBDIR       = $(PREFIX)/lib
INCLUDEDIR   = $(PREFIX)/include
SRCDIR       = $(PREFIX)/src/$(NAME)
SHAREDIR     = $(PREFIX)/share
LOCALEDIR    = $(SHAREDIR)/locale
MANDIR       = $(SHAREDIR)/man
EXEC         = ./
## Where to store the installation.  Empty by default.
DESTDIR      =
LDLIBS       =



.SUFFIXES:
.SUFFIXES: .in .c .o .to .xa .bin .msg .cat
.SUFFIXES: .s

.in:
	sed \
		-e 's:@VERSION@:$(VERSION):g' \
		-e 's:@DATE@:$(DATE):g'       \
		-e 's:@NAME@:$(NAME):g'       \
		< $< > $@
	if [ -x $< ]; then chmod +x $@; fi

.s.o:
	$(CC) $(CFLAGS)        -o $@ -c $<

.c.o:
	$(CC) $(CFLAGS)        -o $@ -c $<

.c.to:
	$(CC) $(CFLAGS) -DTEST -o $@ -c $<

.xa.bin:
	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS)



all:
include deps.mk

manpages     = $(manpages.in:.in=)
catalogs.cat = $(catalogs.msg:.msg=.cat)

sources.o   = $(sources.c:.c=.o) $(sources.s:.s=.o)
sources.to  = $(sources.c:.c=.to)
sources.xa  = $(sources.c:.c=.xa)
sources.bin = $(sources.c:.c=.bin)
fuzz.o      = $(fuzz.c:.c=.o)
fuzz.xa     = $(fuzz.c:.c=.xa)
fuzz.bin    = $(fuzz.c:.c=.bin)

sources = \
	$(sources.c)       \
	$(sources.c:.c=.h) \
	src/config.h.in    \
	src/config.h       \
	src/main.c         \
	src/$(NAME).h      \
	$(catalogs.msg)    \

empty-libs.a = \
	libm.a             \
	librt.a            \
	libpthread.a       \
	libcrypt.a         \
	libutil.a          \
	libxnet.a          \
	libresolv.a        \
	libdl.a            \


derived-assets = \
	lib$(NAME).a       \
	$(empty-libs.a)    \
	libc.a             \
	src/config.h       \
	$(manpages)        \
	$(catalogs.cat)    \
	$(sources.o)       \
	$(sources.to)      \
	$(sources.xa)      \
	$(sources.bin)     \
	src/main.o         \
	src/main.xa        \
	src/main.bin       \

side-assets = \
	$(fuzz.o)          \
	$(fuzz.xa)         \
	$(fuzz.bin)        \



## Default target.  Builds all artifacts required for testing
## and installation.
all: $(derived-assets)


lib$(NAME).a: $(libc.c:.c=.o) $(libc.s:.s=.o)
src/main.xa:  $(sources.o) src/main.o
$(fuzz.bin): lib$(NAME).a
$(manpages) src/config.h:   Makefile deps.mk
$(sources.o) $(sources.to): Makefile deps.mk src/config.h
$(sources.xa): crt/crt1.o crt/x86_64/crti.o crt/x86_64/crtn.o
$(sources.xa): $(libc.c:.c=.o) $(libc.s:.s=.o)

crt/crt1.bin:
	touch $@
	chmod +x $@


lib$(NAME).a $(sources.xa) src/main.xa $(fuzz.xa) $(empty-libs.a):
	$(AR) $(ARFLAGS) $@ $?

src/$(NAME).en.cat: src/i18n.bin
	env DUMP_TRANSLATABLE_STRINGS=1 $(EXEC)src/i18n.bin > $*.msg.new
	cmp -s $*.msg.new $*.msg || mv $*.msg.new $*.msg
	rm -f $*.msg.new
	gencat $@ $*.msg
	touch $@

libc.a: lib$(NAME).a
	ln -fs lib$(NAME).a $@



.SUFFIXES: .bin-check
sources.bin-check = $(sources.c:.c=.bin-check)
$(sources.bin-check):
	$(EXEC)$*.bin

check-unit: $(sources.bin-check)


## Run all tests.  Each test suite is isolated, so that a parallel
## build can run tests at the same time.  The required artifacts
## are created if missing.
check: check-unit



fuzz.bin-check = $(fuzz.c:.c=.bin-check)
$(fuzz.bin-check):
	$(EXEC)$*.bin tests/fuzz/corpus/ $(FUZZFLAGS)

## Run fuzzing targets indefinitely.
fuzz: $(fuzz.bin-check)



## Remove *all* derived artifacts produced during the build.
## A dedicated test asserts that this is always true.
clean:
	rm -rf $(derived-assets) $(side-assets)


## Installs into $(DESTDIR)$(PREFIX).  Its dependency target
## ensures that all installable artifacts are crafted beforehand.
install: all
	mkdir -p \
		'$(DESTDIR)$(BINDIR)' \
		'$(DESTDIR)$(LIBDIR)' \
		'$(DESTDIR)$(INCLUDEDIR)'
	cp src/main.bin  '$(DESTDIR)$(BINDIR)'/$(NAME)
	# FIXME headers in '$(DESTDIR)$(INCLUDEDIR)'
	cp -P lib$(NAME).a $(empty-libs.a) libc.a '$(DESTDIR)$(LIBDIR)'
	for f in $(FIXME_sources); do \
		dir='$(DESTDIR)$(SRCDIR)'/"`dirname "$${f#src/}"`"; \
		mkdir -p "$$dir"; \
		cp -P "$$f" "$$dir"; \
	done
	for l in $(LANGUAGES); do \
		dir='$(DESTDIR)$(LOCALEDIR)'/"$$l"/LC_MESSAGES; \
		mkdir -p "$$dir"; \
		cp src/$(NAME)."$$l".cat "$$dir"/$(NAME).cat; \
	done
	sh tools/manpages.sh -ip '$(DESTDIR)$(MANDIR)' $(manpages)

## Uninstalls from $(DESTDIR)$(PREFIX).  This is a perfect mirror
## of the "install" target, and removes *all* that was installed.
## A dedicated test asserts that this is always true.
uninstall:
	rm -rf \
		'$(DESTDIR)$(BINDIR)'/$(NAME)       \
		'$(DESTDIR)$(LIBDIR)'/lib$(NAME).a  \
		'$(DESTDIR)$(INCLUDEDIR)'/$(NAME).h \
		'$(DESTDIR)$(SRCDIR)'
	for l in $(empty-libs.a) libc.a; do \
		rm -f '$(DESTDIR)$(LIBDIR)'/"$$l"; \
	done
	for l in $(LANGUAGES); do \
		rm -f '$(DESTDIR)$(LOCALEDIR)'/"$$l"/LC_MESSAGES/$(NAME).cat; \
	done
	sh tools/manpages.sh -up '$(DESTDIR)$(MANDIR)' $(manpages)


MAKEFILE = Makefile
## Show this help.
help:
	cat $(MAKEFILE) | sh tools/makehelp.sh


ALWAYS: