.POSIX:

PREFIX = /usr/local
DESTDIR =
BINDIR = $(PREFIX)/bin
MANDIR = $(PREFIX)/share/man
DOCDIR = $(PREFIX)/share/doc/vipirc
CC = cc
CPPFLAGS = -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED=1
CFLAGS = -O2 -std=c11 -Wall -Wextra -Wpedantic
LDFLAGS = 
CURSES_LIBS = -lncursesw
TLS_LIBS = -lssl -lcrypto
PYTHON = python3
SANFLAGS = -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer

SRC = src/main.c src/client.c src/ui.c src/settings.c src/transfers.c src/dcc.c src/app.c src/sim.c src/net.c src/config.c src/protocol.c src/editor.c src/manual.c
OBJ = src/main.o src/client.o src/ui.o src/settings.o src/transfers.o src/dcc.o src/app.o src/sim.o src/net.o src/config.o src/protocol.o src/editor.o src/manual.o
HEADERS = src/client.h src/dcc.h src/transfers.h src/app.h src/sim.h src/net.h src/config.h src/protocol.h src/editor.h src/ui.h src/settings.h src/manual.h

all: vipirc

vipirc: $(OBJ)
	$(CC) $(LDFLAGS) -o $@ $(OBJ) $(CURSES_LIBS) $(TLS_LIBS)

$(OBJ): $(HEADERS)

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

build:
	mkdir -p build

build/test_protocol: tests/test_protocol.c src/protocol.c src/protocol.h build
	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Isrc -o $@ tests/test_protocol.c src/protocol.c

build/test_editor: tests/test_editor.c src/editor.c src/editor.h build
	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Isrc -o $@ tests/test_editor.c src/editor.c

build/test_config: tests/test_config.c src/config.c src/protocol.c src/config.h src/protocol.h build
	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Isrc -o $@ tests/test_config.c src/config.c src/protocol.c

build/test_app: tests/test_app.c src/app.c src/sim.c src/protocol.c $(HEADERS) build
	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Isrc -o $@ tests/test_app.c src/app.c src/sim.c src/protocol.c

build/test_client: tests/test_client.c src/client.c src/config.c src/protocol.c $(HEADERS) build
	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Isrc -o $@ tests/test_client.c src/client.c src/config.c src/protocol.c

build/test_dcc: tests/test_dcc.c src/dcc.c src/protocol.c $(HEADERS) build
	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Isrc -o $@ tests/test_dcc.c src/dcc.c src/protocol.c

check-unit: build/test_protocol build/test_editor build/test_config build/test_app build/test_client build/test_dcc
	./build/test_protocol
	./build/test_editor
	./build/test_config
	./build/test_app
	./build/test_client
	./build/test_dcc

check-offline: vipirc
	$(PYTHON) tests/test_welcome.py
	$(PYTHON) tests/test_controls.py
	$(PYTHON) tests/test_offline.py
	$(PYTHON) tests/test_input_limits.py
	$(PYTHON) tests/test_settings.py --offline-only
	$(PYTHON) tests/test_chat_basics.py --offline-only
	$(PYTHON) tests/test_servers.py --offline-only
	$(PYTHON) tests/test_transfers.py --offline-only

check: vipirc check-unit check-offline
	$(PYTHON) tests/test_net.py
	$(PYTHON) tests/test_integration.py
	$(PYTHON) tests/test_settings.py --live-only
	$(PYTHON) tests/test_chat_basics.py --live-only
	$(PYTHON) tests/test_servers.py --live-only
	$(PYTHON) tests/test_transfers.py --live-only

sanitize: build
	mkdir -p build/sanitize
	$(CC) $(CPPFLAGS) $(SANFLAGS) -Isrc -o build/sanitize/test_protocol tests/test_protocol.c src/protocol.c
	$(CC) $(CPPFLAGS) $(SANFLAGS) -Isrc -o build/sanitize/test_editor tests/test_editor.c src/editor.c
	$(CC) $(CPPFLAGS) $(SANFLAGS) -Isrc -o build/sanitize/test_config tests/test_config.c src/config.c src/protocol.c
	$(CC) $(CPPFLAGS) $(SANFLAGS) -Isrc -o build/sanitize/test_app tests/test_app.c src/app.c src/sim.c src/protocol.c
	$(CC) $(CPPFLAGS) $(SANFLAGS) -Isrc -o build/sanitize/test_client tests/test_client.c src/client.c src/config.c src/protocol.c
	$(CC) $(CPPFLAGS) $(SANFLAGS) -Isrc -o build/sanitize/test_dcc tests/test_dcc.c src/dcc.c src/protocol.c
	$(CC) $(CPPFLAGS) $(SANFLAGS) -o build/sanitize/vipirc $(SRC) $(CURSES_LIBS) $(TLS_LIBS)
	./build/sanitize/test_protocol
	./build/sanitize/test_editor
	./build/sanitize/test_config
	./build/sanitize/test_app
	./build/sanitize/test_client
	./build/sanitize/test_dcc
	VIPIRC_BINARY="`pwd`/build/sanitize/vipirc" $(PYTHON) tests/test_welcome.py
	VIPIRC_BINARY="`pwd`/build/sanitize/vipirc" $(PYTHON) tests/test_controls.py
	VIPIRC_BINARY="`pwd`/build/sanitize/vipirc" $(PYTHON) tests/test_offline.py
	VIPIRC_BINARY="`pwd`/build/sanitize/vipirc" $(PYTHON) tests/test_input_limits.py
	VIPIRC_BINARY="`pwd`/build/sanitize/vipirc" $(PYTHON) tests/test_settings.py
	VIPIRC_BINARY="`pwd`/build/sanitize/vipirc" $(PYTHON) tests/test_chat_basics.py
	VIPIRC_BINARY="`pwd`/build/sanitize/vipirc" $(PYTHON) tests/test_servers.py
	VIPIRC_BINARY="`pwd`/build/sanitize/vipirc" $(PYTHON) tests/test_transfers.py
	VIPIRC_BINARY="`pwd`/build/sanitize/vipirc" $(PYTHON) tests/test_integration.py

bench: vipirc
	$(PYTHON) tests/bench.py

STRESS_SECONDS = 60
SOAK_SECONDS = 1200

build/app-faults.o: src/app.c $(HEADERS) build
	$(CC) $(CPPFLAGS) $(CFLAGS) -Dmalloc=app_test_malloc -Dcalloc=app_test_calloc -Drealloc=app_test_realloc -Dfree=app_test_free -c src/app.c -o $@

build/test_app_faults: tests/test_app_faults.c tests/test_app.c build/app-faults.o src/protocol.c src/sim.c $(HEADERS) build
	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Isrc -o $@ tests/test_app_faults.c build/app-faults.o src/protocol.c src/sim.c

build/test_dcc_stress: tests/test_dcc_stress.c src/dcc.c src/protocol.c $(HEADERS) build
	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Isrc -o $@ tests/test_dcc_stress.c src/dcc.c src/protocol.c

check-stress: vipirc build/test_app_faults build/test_dcc_stress
	./build/test_app_faults
	./build/test_dcc_stress --seconds $(STRESS_SECONDS)
	$(PYTHON) tests/test_lifecycle_stress.py
	$(PYTHON) tests/test_ui_stress.py
	$(PYTHON) tests/test_fd_pressure.py

soak: vipirc
	$(PYTHON) tests/test_soak.py --seconds $(SOAK_SECONDS) --servers 8 --tls


install: vipirc
	mkdir -p "$(DESTDIR)$(BINDIR)" "$(DESTDIR)$(MANDIR)/man1" "$(DESTDIR)$(DOCDIR)"
	cp vipirc "$(DESTDIR)$(BINDIR)/vipirc"
	chmod 755 "$(DESTDIR)$(BINDIR)/vipirc"
	cp doc/vipirc.1 "$(DESTDIR)$(MANDIR)/man1/vipirc.1"
	chmod 644 "$(DESTDIR)$(MANDIR)/man1/vipirc.1"
	cp README.md INSTALL DESIGN.md SECURITY.md NOTICE LICENSE.md doc/manual.txt examples/config.ini "$(DESTDIR)$(DOCDIR)/"
	chmod 644 "$(DESTDIR)$(DOCDIR)/README.md" "$(DESTDIR)$(DOCDIR)/INSTALL" "$(DESTDIR)$(DOCDIR)/DESIGN.md" "$(DESTDIR)$(DOCDIR)/SECURITY.md" "$(DESTDIR)$(DOCDIR)/NOTICE" "$(DESTDIR)$(DOCDIR)/LICENSE.md" "$(DESTDIR)$(DOCDIR)/manual.txt" "$(DESTDIR)$(DOCDIR)/config.ini"

uninstall:
	rm -f "$(DESTDIR)$(BINDIR)/vipirc" "$(DESTDIR)$(MANDIR)/man1/vipirc.1"
	rm -f "$(DESTDIR)$(DOCDIR)/README.md" "$(DESTDIR)$(DOCDIR)/INSTALL" "$(DESTDIR)$(DOCDIR)/DESIGN.md" "$(DESTDIR)$(DOCDIR)/SECURITY.md" "$(DESTDIR)$(DOCDIR)/NOTICE" "$(DESTDIR)$(DOCDIR)/LICENSE.md" "$(DESTDIR)$(DOCDIR)/manual.txt" "$(DESTDIR)$(DOCDIR)/config.ini"
	-rmdir "$(DESTDIR)$(DOCDIR)"

clean:
	rm -f vipirc $(OBJ) build/test_protocol build/test_editor build/test_config build/test_app build/test_client build/test_dcc
	rm -f build/app-faults.o build/test_app_faults build/test_dcc_stress
	rm -f build/sanitize/vipirc build/sanitize/test_protocol build/sanitize/test_editor build/sanitize/test_config build/sanitize/test_app build/sanitize/test_client build/sanitize/test_dcc

distclean: clean
	rm -f config.log

