sources = $(shell find . -name '*.go' \
	| grep -v cmd/treerack/docreflect.gen.go \
	| grep -v head.go \
	| grep -v .build/head.go \
	| grep -v headexported.go \
	| grep -v .build/headexported.go \
	| grep -v internal/self/self.go \
	| grep -v .build/self.go)
parsers = $(shell find . -name '*.treerack')
release_date = $(shell git show -s --format=%cs HEAD)
version = $(release_date)-$(shell git rev-parse --short HEAD)
PREFIX ?= /usr/local
prefix ?= $(PREFIX)

default: build

.build:
	mkdir -p .build

.build/head.go: $(sources) .build
	go fmt ./...
	go run scripts/createhead.go -- \
		char.go \
		sequence.go \
		choice.go \
		idset.go \
		results.go \
		context.go \
		nodehead.go \
		syntaxhead.go \
	> .build/head.go
	go fmt .build/head.go

head.go: .build/head.go
	cp .build/head.go .

.build/headexported.go:  $(sources) .build
	go fmt ./...
	go run scripts/createhead.go --exported -- \
		char.go \
		sequence.go \
		choice.go \
		idset.go \
		results.go \
		context.go \
		nodehead.go \
		syntaxhead.go \
	> .build/headexported.go
	go fmt .build/headexported.go

headexported.go: .build/headexported.go
	cp .build/headexported.go .

.build/self.go: $(sources) $(parsers) head.go headexported.go .build
	# since the generator code depends on the syntax itself, and such influences its own output, we need two
	# passes:
	go build -o .build/treerack.current ./cmd/treerack
	.build/treerack.current generate --export --package-name self < syntax.treerack > .build/self.go
	go fmt .build/self.go
	# we backup the original and apply the new:
	cp internal/self/self.go .build/self.go.backup
	cp .build/self.go internal/self
	# second pass:
	go build -o .build/treerack.interim ./cmd/treerack || mv .build/self.go.backup internal/self/self.go
	.build/treerack.interim generate --export --package-name self < syntax.treerack > .build/self.go \
		|| mv .build/self.go.backup internal/self/self.go
	go fmt .build/self.go || mv .build/self.go.backup internal/self/self.go
	mv .build/self.go.backup internal/self/self.go

internal/self/self.go: .build/self.go
	cp .build/self.go internal/self

lib: $(sources) head.go headexported.go internal/self/self.go
	go build
	go build ./internal/self

cmd/treerack/docreflect.gen.go: $(sources) .build
	go run scripts/docreflect.go > .build/docreflect.gen.go
	go fmt .build/docreflect.gen.go
	mv .build/docreflect.gen.go cmd/treerack

cmd/treerack/readme.md: $(sources) cmd/treerack/docreflect.gen.go
	go run scripts/cmdreadme.go ./cmd/treerack > cmd/treerack/readme.md || \
		rm cmd/treerack/readme.md

.build/treerack: $(sources) lib cmd/treerack/docreflect.gen.go .build
	go build -o .build/treerack -ldflags "-X main.version=$(version)" ./cmd/treerack
		

.build/treerack.1: $(sources) cmd/treerack/docreflect.gen.go .build
	go run scripts/man.go $(version) $(release_date) > .build/treerack.1 || \
		rm .build/treerack.1

build: lib cmd/treerack/readme.md .build/treerack .build/treerack.1

check-generate: .build/head.go .build/headexported.go .build/self.go
	@if ! diff head.go .build/head.go > /dev/null; then \
		echo head.go does not match; \
		false; \
	fi
	@if ! diff headexported.go .build/headexported.go > /dev/null; then \
		echo headexported.go does not match; \
		false; \
	fi
	@if ! diff internal/self/self.go .build/self.go > /dev/null; then \
		echo self.go does not match; \
		false; \
	fi

check: $(sources) $(parsers) build check-generate
	go test
	go test ./cmd/treerack

.coverprofile: $(sources)
	go test -coverprofile .coverprofile

cover: .coverprofile
	go tool cover -func .coverprofile

showcover: .coverprofile
	go tool cover -html .coverprofile

.coverprofile-cmd: $(sources)
	go test ./cmd/treerack -coverprofile .coverprofile-cmd

cover-cmd: .coverprofile-cmd
	go tool cover -func .coverprofile-cmd

showcover-cmd: .coverprofile-cmd
	go tool cover -html .coverprofile-cmd

.PHONY: cpu.out
cpu.out:
	go test -v -run TestMMLFile -cpuprofile cpu.out

cpu: cpu.out
	go tool pprof -top cpu.out

fmt: $(sources) head.go headexported.go internal/self/self.go cmd/treerack/docreflect.gen.go
	go fmt ./...

$(prefix)/bin/treerack: .build/treerack
	mkdir -p $(prefix)/bin
	cp .build/treerack $(prefix)/bin

$(prefix)/share/man/man1/treerack.1: .build/treerack.1
	mkdir -p $(prefix)/share/man/man1
	cp .build/treerack.1 $(prefix)/share/man/man1

install: $(prefix)/bin/treerack $(prefix)/share/man/man1/treerack.1

clean:
	rm -f cpu.out
	rm -f .coverprofile
	rm -rf .build
	go clean ./...
