#--*- Makefile -*--

# Compile and run C# libraries and programs using 'mono'.

#------------------------------------------------------------------------------

PRG_DIR ?= programs
EXE_DIR ?= exe

CS_SOURCES ?= $(wildcard ${PRG_DIR}/*.cs)

CS_EXE ?= $(sort ${CS_SOURCES:${PRG_DIR}/%.cs=${EXE_DIR}/%.exe})

#------------------------------------------------------------------------------

LIB_DIR ?= lib

SRC_DIR ?= src
LIB_SRC_DIRS  ?= $(wildcard ${SRC_DIR}/*)
LIB_SRC_FILES ?= $(wildcard ${SRC_DIR}/*/*.cs)

LIBS ?= ${LIB_SRC_DIRS:${SRC_DIR}/%=${LIB_DIR}/%.dll}

#------------------------------------------------------------------------------

.PHONY: all clean distclean cleanAll

all: ${CS_EXE} ${LIBS}

DEPENDENCIES = .depend

include ${DEPENDENCIES}

${DEPENDENCIES}: ${LIB_SRC_FILES}
	find $(sort $(dir $^)) -name '*.cs' \
	| sed 's/^${SRC_DIR}\///' \
	| awk '{ \
		dir = $$0; gsub("/[^/]*$$","",dir); \
		print "${LIB_DIR}/"dir".dll: ${SRC_DIR}/"$$0 \
	}' \
	> ${DEPENDENCIES}

#------------------------------------------------------------------------------

${EXE_DIR}/%.exe: ${PRG_DIR}/%.cs | ${LIBS}
	mono-csc -out:$@ $(addprefix -reference:,${LIBS}) $<

${LIB_DIR}/%.dll:
	mono-csc -out:$@ -target:library $^

# use 'make run ARGS="a b c"' to pass args to programs
ARGS ?=

.PHONY: run

MONO_PATH := $(shell cd ${LIB_DIR}; pwd)${MONO_PATH:%=:%}

export MONO_PATH

run: ${CS_EXE}
	for PROG in $^; do ( \
		set -x; \
		./$${PROG} ${ARGS}; \
	) done

#------------------------------------------------------------------------------

.PHONY: cs-mono-clean  cs-mono-distclean

cs-mono-clean:

cs-mono-distclean:
	rm -f ${CS_EXE}
	rm -f ${LIBS}

clean: cs-mono-clean

cleanAll distclean: cs-mono-distclean
