#- modmake
# this is the master makefile that controls the building of each
# libk module. it is included from each k*/makefile.
# vim: ft=make

include ../makerule

mod = $(notdir $(PWD))
src = $(wildcard *.c) $(wildcard *.s) $(filter-out %.h,$(patsubst %.m,%,$(wildcard *.m)))
bare = $(mod:k%=%)
headers = $(wildcard *.h) $(gen-headers) $(patsubst %.m,%,$(wildcard *.h.m))

tools    = $(filter     %.exe.c,   $(src))
nontools = $(filter-out %.exe.c,   $(src))
cobjects = $(filter     %.c,       $(nontools))
sobjects = $(filter %.${TARGET}.s, $(nontools))

obj: $(cobjects:%.c=${OUT}/$(mod).%.o) \
	 $(sobjects:%.s=${OUT}/$(mod).%.o)
tool: $(tools:%.exe.c=${OUT}/$(mod).%) \
	  ${OUT}/libk.a

def: $(headers:%=${OUT}/k/%)

dbg:
	@echo src = $(src)
	@echo tools = $(tools)
	@echo TARGET = ${TARGET}
	@echo cobjects = $(cobjects)
	@echo sobjects = $(sobjects)
	@echo headers = $(headers)
	@echo m-comp = $(m-comp)
	@echo m-env = $(m-env) "$(m-env:%=-D%)"
	@echo mod = $(mod)

${OUT}/k/%.h: %.h.m
	$(m-comp) $< > $@

.PRECIOUS: ${TMP}/$(mod).%
${TMP}/$(mod).%: %.m ${TMP}
	$(m-comp) $< > $@

${OUT}/$(mod).%.o: ${TMP}/$(mod).%.c
	$(CC) $(cflags) -c $< -o $@

${OUT}/$(mod).%.o: %.c $(bare).h
	$(CC) $(cflags) -c $< -o $@

${OUT}/k/%.h: %.h
	cp $< $@

${OUT}/$(mod).%: %.exe.c
	$(CC) $(cflags) $< ${OUT}/libk.a -o $@

${TMP}:
	mkdir -p ${TMP}

#- assembly
# compiling  the assembly  code will  be  faster but  a lot  more
# complex, given the  nature of assembly and the  large number of
# platforms  targeted.  we need  to  add  build rules  for  every
# arch.OS[.bits] tuple;  since this  is a fairly  repetetive task
# that  requires ugly  make  rules,  we're just  going  to use  a
# function to generate these.

# ${OUT} = ultimate build directory
# $(mod) = module name
#      % = function name
#   $(1) = arch tuple
arch = ${OUT}/$(mod).%.$(1).o: $2%.$(1).s
# invoke with $(call arch,tuple). do not
# put spaces between either term though!

ifeq ($(debug),yes)
yasm-flags = -gdwarf2
endif

yasm = yasm $(yasm-flags) -f$1 -i${TMP} $< -o $@

#-- linux
# linux uses the ELF{32,64} binary format,  and generating these
# from yasm is trivial.  linux only supports one ABI per format,
# at least with ELF, so that's all we need to do.


$(call arch,x86.lin.32,)
	$(call yasm,elf32)

$(call arch,x86.lin.64,)
	$(call yasm,elf64)

$(call arch,x86.lin.32,${TMP}/$(mod).)
	$(call yasm,elf32)

$(call arch,x86.lin.64,${TMP}/$(mod).)
	$(call yasm,elf64)

#-- freebsd
# the freebsd ABI is different, so it will require different code
# (though there might be ways to minimize that). freebsd uses the
# same binary format as Linux  (though it also supports a.out and
# COFF) but because freebsd can interpret multiple different ABIs
# the  object files  need to  be "branded"  with the  correct one
# using the tool brandelf (`brandelf -t [ABI]`)

$(call arch,x86.fbsd.32,)
	$(call yasm,elf32)
	brandelf -t FreeBSD $@

$(call arch,x86.fbsd.64,)
	$(call yasm,elf64)
	brandelf -t FreeBSD $@

$(call arch,x86.fbsd.32,${TMP}/$(mod).)
	$(call yasm,elf32)
	brandelf -t FreeBSD $@

$(call arch,x86.fbsd.64,${TMP}/$(mod).)
	$(call yasm,elf64)
	brandelf -t FreeBSD $@
