# GNU Make automatic variables
# $@ current target
# $< First dependency
# $? All newer dependencies
# $^ All dependencies
# $* The stem (ie. target is dir/a.foo.b and the pattern is
#    a.%.b, then the stem is dir/foo)

# Create one directory without any output
%define mkdir_q dir=.
	@if [ ! -d %(dir) ]; then $(MKDIR) %(dir) ; else true ; fi
%end

# Create several directories without any output
%define mkdirs_q dirs=/M
	@for dir in %(dirs) ; do \
	    if [ ! -d $$dir ]; then $(MKDIR) $$dir ; else true ; fi ; \
	done
%end

# Assemble the file %(from) to %(to) with %(cmd). Write any errors to %(err)
# and use the options in %(opt).
%define assemble_q cmd=$(AS) opt=$(AFLAGS) from=$< to=$@ err=$*.err
	@$(ECHO) "Assembling $(CURDIR)/%(from)..."
	@%(cmd) %(opt) -c %(from) -o %(to) 2>&1|tee %(err)
	@if test -s %(err); then $(TOUCH) $(TOP)/errors ; else $(RM) %(err) ; fi
%end

# Compile the file %(from) to %(to) with %(cmd). Write any errors to %(err)
# and use the options in %(opt).
%define compile_q cmd=$(CC) opt=$(CFLAGS) from=$< to=$@ err=$*.err
	@$(ECHO) "Compiling $(CURDIR)/%(from)..."
	@%(cmd) %(opt) -c %(from) -o %(to) 2>&1|tee %(err)
	@if test -s %(err); then $(TOUCH) $(TOP)/errors ; else $(RM) %(err) ; fi
%end

%define link_q cmd=$(CC) opt=$(ILDFLAGS) startup=$(STARTUP) from=$< to=$@ err=$(@F)-x.err libs=$(LIBS) us=undefdsyms.list
	@$(ECHO) "Linking %(to)..."
	@%(cmd) %(opt) %(startup) %(from) -o %(to) %(libs) 2>&1|tee %(err)
	@$(CHECKUDS) %(to) > %(us)
	@if test -s %(us); then \
	    cat %(us) >> %(err); \
	    echo "There are undefined symbols in %(to):"; \
	    cat %(us); \
	else true ; fi
	@$(RM) %(us)
	@if test -s %(err); then $(TOUCH) $(TOP)/errors ; else $(RM) %(err) ; fi
%end

%define checkuds us=undefdsyms.list err=$(@F)-x.err to=$@
	@$(CHECKUDS) %(to) > %(us)
	@if test -s %(us); then \
	    cat %(us) >> %(err); \
	    echo "There are undefined symbols in %(to):"; \
	    cat %(us); \
	else true ; fi
	@$(RM) %(us)
%end

# Create the library
%define mklib_q ar=$(AR) ranlib=$(RANLIB) to=$@ from=$(OBJS)
	@$(ECHO) "Creating library %(to)..."
	@%(ar) %(to) %(from)
	@%(ranlib) %(to)
%end

# Same but more noisy
%define mklib ar=$(AR) ranlib=$(RANLIB) to=$@ from=$(OBJS)
	@$(ECHO) "Creating library %(to)..."
	%(ar) %(to) %(from)
	%(ranlib) %(to)
%end

# Create the dependency file %(to) for %(from) in the directory %(dir)
%define mkdepend_q flags=$(CFLAGS) from=$< to=$@ dir=$(@D) opt=
	@if [ ! -d %(dir) ]; then $(MKDIR) %(dir) ; else true ; fi
	@$(ECHO) "Makedepend $(CURDIR)/%(from)..."
	@$(MKDEPEND) -f- -p%(dir)/ %(opt) -- %(flags) -- %(from) > %(to)
%end

# Same but more noisy
%define mkdepend flags=$(CFLAGS) from=$< to=$@ dir=$(@D) opt=
	@if [ ! -d %(dir) ]; then $(MKDIR) %(dir) ; else true ; fi
	@$(ECHO) "Makedepend $(CURDIR)/%(from)..."
	$(MKDEPEND) -f- -p%(dir)/ %(opt) -- %(flags) -- %(from) > %(to)
%end

# Add section with all necessary libs and dependencies for linking
%define define_libs prelibs= postlibs= deplibs=
STARTUP = $(LIBDIR)/startup.o
LIBS = -L$(LIBDIR) %(prelibs) -larossupport -lamiga -larosc %(postlibs)
DEPLIBS = $(LIBDIR)/libamiga.a $(LIBDIR)/libarossupport.a $(STARTUP) \
	$(LIBDIR)/libarosc.a %(deplibs)
%end

# Do something in all subdirs
# This macro uses a trick: %(target) is evaluated *after* %(text), so one
# can use %(target) in %(text).
%define subdirs_q text="Making %(target)" target=$(TARGET) dirs=$(SUBDIRS) curdir=$(CURDIR) mflags=$(MFLAGS) submf=makefile top=$(TOP)
	@for dir in %(dirs) ; do \
	    echo "%(text) in %(curdir)/$$dir..." ; \
	    if test -e $$dir/%(submf).src && \
		{ test ! -e $$dir/%(submf) \
		-o $$dir/%(submf).src -nt $$dir/%(submf) \
		-o %(top)/config/make.tmpl -nt $$dir/%(submf) ; } ; then \
		echo "Generating %(submf)..." ; \
		$(AWK) -f $(TOP)/scripts/genmf.gawk \
		--assign TOP="$(TOP)" \
		$$dir/%(submf).src > $$dir/%(submf) || exit 1 ; \
	    fi ; \
	    if ( cd $$dir ; \
		$(MAKE) %(mflags) -f %(submf) \
		    TOP="%(top)/.." CURDIR="%(curdir)/$$dir" \
		    TARGET=%(target) %(target) ) ; \
	    then true ; else exit 1 ; fi ; \
	done
%end

# Prepare creation of a shared lib
%define prepare_shlib lib=dummy shflag=$(SHARED_DUMMY)
OBJDIR=$(OSGENDIR)/%(lib)
ifeq ("%(shflag)","yes")
LIB=$(LIBDIR)/lib%(lib).so
RMLIB=$(LIBDIR)/lib%(lib).a
AR=$(SHARED_AR)
RANLIB=true
else
LIB=$(LIBDIR)/lib%(lib).a
RMLIB=$(LIBDIR)/lib%(lib).so
endif
%end

# Generate function table
%define mkfunctable_q lib=dummy from=$^ to=$@
	@$(ECHO) "Regenerating %(to)..."
	@$(AWK) -f $(TOP)/scripts/makefunctable.awk \
	    --assign lib="%(lib)" %(from)
%end

# Generate endskip variable
%define mkendtag_q lib=dummy from=$^ to=$@
	@$(ECHO) "Regenerating %(to)..."
	@$(AWK) -f $(TOP)/scripts/makeendtag.awk \
	    --assign lib="%(lib)" %(from)
%end

# Common rules for all makefiles
%define common
# Check if the makefile itself must be remade
clean ::
	$(RM) makefile makefile.bak

all : makefile

# Remake makefile
makefile : makefile.src $(TOP)/scripts/genmf.gawk \
	    $(TOP)/config/make.tmpl
	@$(ECHO) "Regenerating makefile..."
	@$(MV) $@ $@.bak
	@$(AWK) -f $(TOP)/scripts/genmf.gawk --assign TOP="$(TOP)" \
	    $< > $@

%end

# Include the dependency files and add some internal rules
%define include_deps deps=$(DEPS)/M
# Include these files but only if the current target is neither
# setup nor clean.
ifneq ("$(TARGET)","clean")
ifneq ("$(TARGET)","setup")
include %(deps)
endif
endif
%end

# rule to generate libdefs.h
%define libdefs_rule
libdefs.h : lib.conf $(TOP)/scripts/genlibdefs.gawk
	@echo "Generating $@..."
	@$(AWK) -f $(TOP)/scripts/genlibdefs.gawk lib.conf > libdefs.h
%end

# rule to generate asm files from c files (for debugging purposes)
%define asm_rule
.PHONY : asm
asm : $(foreach f,$(FUNCTIONS) $(INIT_FILE) $(END_FILE) $(FILES),$(f).s) all
%end

# generate asm files from c files (for debugging purposes)
%define ctoasm_q
%.s : %.c
	@echo "Generating $(CURDIR)/$@..."
	@$(CC) -S $(CFLAGS) $< -c -o $@
%end

# Used to help with the function replacement mechanism. Use like
#
#	%prepare_replace module=os/exec
#
# This will include the file contain information written out by the
# $(TOP)/config makefiles which is used to filter out files that are
# being replaced by machine dependant versions in the $(TOP)/config
# subtree.
#
# You can also determine which group of files you wish to filter against
# with the filter command. You pass it the variable to modify as var
#
# Eg:
#	%prepare_replace module=os/foobar
#	%filter_replace $(FUNCTIONS)
#
# The variable $(ADDITIONAL_OBJS) will be available for you to link in
# extra files.
#
# You should save the values of the variables which you filter in case
# you need them at a later date.
#
%define prepare_replace module=
-include $(GENDIR)/%(module)/mf.inc
%end

%define filter_replace var=FILES filter=$(SUPPRESS_FILES)
%(var) := $(filter-out %(filter),$(%(var)))
%end

# You can use this to prevent objects which weren't compiled correctly by
# config/$(...) directories to not be compiled by the local makefile.
%define additional_objs_rule
$(foreach f,$(ADDITIONAL_OBJS),$(OBJDIR)/$(f).o) :
	@echo Error: One of the precompiled object files did not exist.
	@exit 1
%end

%define add_objects files=/M
	$(foreach f,%(files),$(shell echo >> $(GENDIR)/config.files add $(f)))
%end

%define exclude_files files=/M
	$(foreach f,%(files),$(shell echo >> $(GENDIR)/config.files not $(f)))
%end
