#- modmake
# this is the master makefile that controls the building of each
# libk module. it is included from each k*/makefile.
# vim: ft=make
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))
cflags = -std=c11 -isystem ${OUT} -fPIC -nostdlib ${COMPLIB} -L${OUT}
m-env = atom_target_arch=${ARCH}
m-env += atom_target_os=${OS}
ifneq (${BITS},) #!!! ifdef does NOT work with environment variables
m-env += atom_target_bits=${BITS}
endif
m-env += target_posix=${POSIX}
m-env += target_unix=${UNIX}
m-comp = ${m4} $(m-env:%=-D%)
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 $@