# Makefile fragment for C and C++ modules

INCLUDED_CMODULE = YES

#
# This makefile provides the following phony targets:
#
#    all 
#    export  export_hdrs  export_libs
#    resources
#    rom  rom_link 
#    standalone  install
#    debug  gpa_debug
#    prepro
#    clean
#
#
# This fragment uses the following macros set by the master makefile.
#
#
# COMPONENT          (the name of the component)
# TARGET       (opt) (the leafname of the module - otherwise ${COMPONENT})
# ROM_TARGET   (opt) (partially linked module leafname - otherwise ${TARGET}.aof)
# LNK_TARGET   (opt) (fixed-position module leafname - otherwise ${TARGET}.linked)
# SA_TARGET    (opt) (standalone module leafname - otherwise ${TARGET})
# DBG_TARGET   (opt) (debug module leafname - otherwise ${TARGET}D)
# AIF_TARGET   (opt) (GPA-intermediate leafname - otherwise ${TARGET}.aif)
# GPA_TARGET   (opt) (GPA debug leafname - otherwise ${TARGET}.gpa)
# INSTDIR      (opt) (the target directory - otherwise ${INSTALLDIR})
# C_EXP_HDR    (opt) (C header target directory - otherwise ${CEXPORTDIR}/Interface)
# EXP_HDR      (opt) (assembly header target directory - otherwise ${EXPORTDIR}
# DIRS         (opt) (stamp object for directory creation - otherwise _dirs)
# HDRS         (opt) (C header files to export, no .h suffix - otherwise ${TARGET})
# ASMHDRS      (opt) (assembly header files to export, no .hdr suffix - otherwise none)
# ASMCHDRS     (opt) (C-from-assembly auto-generated header files to export, no .hdr suffix - otherwise none)
# INSTRES_FILES   (opt) (extra resource files in addition to Messages - use InstRes specification rules)
# INSTRAM_FILES   (opt) (RAM build specific resources - otherwise ${INSTRES_FILES})
# INSTROM_FILES   (opt) (ROM build specific resources - otherwise ${INSTRES_FILES})
# INSTR??_DEPENDS (opt) (any extra dependency to assert on INSTRES/INSTRAM/INSTROM_FILES)
# MERGEDRDIR      (r/o) (directory for generating exported resources, for information only)
# MERGEDMSGS      (r/o) (leafname of generated Messages file, for compatibility with AAsmModule)
# RESFSDIR        (opt) (actual directory to export resources to - otherwise ${RESDIR}/${TARGET})
# RES_AREA        (opt) (area name to use for embedded messages in standalone build - otherwise Resources)
# RES_OBJ         (opt) (object file for embedded messages in standalone build, no .o suffix - otherwise ${TARGET}Msgs)
# RES_PATH        (opt) (path relative to ResourceFS root to be suffixed by ${TARGET} - otherwise Resources)
# CMHGFILE     (opt) (name of CMHG source file, no .cmhg suffix - otherwise ${TARGET}Hdr)
# CMHGAUTOHDR  (opt) (header file, if any, from HDRS or ASMCHDRS, to which to append the SWI defines from CMHG)
# CMHGFILE_SWIPREFIX (opt) (name of SWI prefix used in CMHG file - otherwise ${TARGET})
# OBJS         (opt) (object files, no .o suffixes - otherwise ${TARGET} ${CMHGFILE})
# ROM_OBJS     (opt) (ROM build objects - otherwise ${OBJS})
# SA_OBJS      (opt) (standalone build objects - otherwise ${OBJS})
# DBG_OBJS     (opt) (debug build object files, no prefixes - otherwise ${OBJS})
# LIBS         (opt) (extra libraries; ${CLIB} is always used)
# ROM_LIBS     (opt) (libraries to link for ROM targets - otherwise ${LIBS})
# SA_LIBS      (opt) (libraries to link for standalone targets - otherwise ${LIBS})
# DBG_LIBS     (opt) (extra debug libraries in addition to SA_LIBS and DEBUGLIBS)
# ROM_DEPEND   (opt) (any extra dependency to assert on ROM_TARGET)
# SA_DEPEND    (opt) (any extra dependency to assert on SA_TARGET and DBG_TARGET)
# TOKHELPDEPENDS (opt) (set to any source files which need to include any autogenerated tokenised help file - otherwise ${OBJS})
# TOKHELPSRC   (opt) (set equal to ${TOKENSOURCE} to indicate that the binary depends on autogenerated tokenised help source file of that name)
# HELPSRC      (opt) (set to filename containing untokenised help messages if ${TOKHELPSRC} = ${TOKENSOURCE})
# TOKENS       (opt) (set to filename containing help message tokens - otherwise ${HDRDIR}/Global/Tokens)
# CUSTOMEXP    (opt) (set to "custom" to override the export rules)
# CUSTOMRES    (opt) (set to "custom" to override the resources rules, or "no" for no resources)
# CUSTOMROM    (opt) (set to "custom" to override the rom rules)
# CUSTOMSA     (opt) (set to "custom" to override the standalone rules)
# CUSTOMDBG    (opt) (set to "custom" to override the debug rules)
# CUSTOMGPA    (opt) (set to "custom" to override the GPA rules)
# RAMCDEFINES  (opt) (additions to CDEFINES for RAM builds - requires ModStdRule to be included later)
# ROMCDEFINES  (opt) (additions to CDEFINES for ROM builds - requires ModStdRule to be included later)
# RAMASMDEFINES (opt) (additions to ASMDEFINES for RAM builds - requires ModStdRule to be included later)
# ROMASMDEFINES (opt) (additions to ASMDEFINES for ROM builds - requires ModStdRule to be included later)
# CMHGDEPENDS  (opt) (source files which need to include the .h file autogenerated from the CMHG file)
# ASM2TXT      (opt) (source file to be autogenerated using objasm as a text generator; second word if present is "extension" subdirectory to place output into)
# ASM2TXT_SUBDIR (opt) (non-"extension" subdirectory to place ASM2TXT file into)
# MODULEWRAP   (opt) (set to "yes" to build and link with the modulewrap veneer from RISC_OSLib)
#
#
# It relies on the following from the build system:
#
#
# PHASE            (export phase discriminator)
# CMDHELP          (whether star command help/syntax strings are included)
# RESDIR           (installation directory for resources - cf. RESFSDIR)
# FORCEROMLINK     (set to force a relink of the ROM target, used in BBE)
# LINKDIR          (installation directory for LNK_TARGET)
# ADDRESS          (base address for LNK_TARGET)
# INSERTVERSION    (awk script to substitute from VersionNum)
#
#
# It relies on the following generic tool macros from the StdTools makefile
#
#
# C + CFLAGS       (C compiler; CDFLAGS also used in debug builds; -g implicit)
# CP + CPFLAGS     (copy, cp etc.)
# WIPE + WFLAGS    (recursive delete)
# RM               (non-recursive delete)
# AS + ASFLAGS     (assembler)
# LD + LDFLAGS     (linker; LDDFLAGS also used in debug builds; -d implicit)
# LDRAMFLAGS       (more linker flags)
# LDROMFLAGS       (more linker flags)
# LDLINKFLAGS      (flags for the rom_link phase)
# MODSQZ + MODSQZFLAGS (module binary compressor)
# CHMOD
# MKDIR            (cdir/mkdir -p)
# ECHO
# TOUCH            (create/touch)
# RESGEN
# TOGPA
#
#
# It relies on the following from the StdRules makefile
#
#
# .c.o  .c++.o  .cpp.o  .s.o
#
#
# It relies on the following from the ModStdRule makefile
#
#
# .cmhg.h  .cmhg.o
#
#
# It relies on the following from the DbgRules makefile
#
#
# CDFLAGS  C++DFLAGS  ASDFLAGS  LDDFLAGS
# .c.od  .c++.od  .cpp.od  .s.od
#
#

TARGET       ?= ${COMPONENT}
ROM_TARGET   ?= ${TARGET}
LNK_TARGET   ?= ${TARGET}
SA_TARGET    ?= ${TARGET}
DBG_TARGET   ?= ${TARGET}D
AIF_TARGET   ?= ${TARGET}
GPA_TARGET   ?= ${TARGET}
INSTDIR      ?= ${INSTALLDIR}
C_EXP_HDR    ?= ${CEXPORTDIR}/Interface
EXP_HDR      ?= ${EXPORTDIR}
DIRS         ?= _dirs
HDRS         ?= ${TARGET}
ASMHDRS      ?= 
ASMCHDRS     ?= 
INSTRAM_FILES   ?= ${INSTRES_FILES}
INSTRAM_DEPENDS ?= ${INSTRES_DEPENDS}
INSTROM_FILES   ?= ${INSTRES_FILES}
INSTROM_DEPENDS ?= ${INSTRES_DEPENDS}
MERGEDRDIR   ?= _ResData_
MERGEDMSGS   ?= ${MERGEDRDIR}/${TARGET}/MergedMessages
RES_AREA     ?= Resources
RES_OBJ      ?= ${TARGET}Msgs
RES_PATH     ?= Resources
RESFSDIR     ?= ${RESDIR}/${TARGET}
CMHGFILE     ?= ${TARGET}Hdr
CMHGFILE_SWIPREFIX ?= ${TARGET}
OBJS         ?= ${TARGET}
ifeq ("${MODULEWRAP}","yes")
OBJS         += modulewrap
endif
ROM_OBJS     ?= ${OBJS}
SA_OBJS      ?= ${OBJS}
DBG_OBJS     ?= ${OBJS}
ROM_OBJS     += ${CMHGFILE}
SA_OBJS      += ${CMHGFILE}
DBG_OBJS     += ${CMHGFILE}
ifeq ($(filter no custom,${CUSTOMRES}),)
RESDIR       ?= ${MERGEDRDIR}
SA_OBJS      += ${RES_OBJ}
DBG_OBJS     += ${RES_OBJ}
endif
TOKHELPDEPENDS ?= ${OBJS}
ROM_LIBS     ?= ${LIBS}
SA_LIBS      ?= ${LIBS}
ROM_LIBS     += ${ROMCSTUBS}
ROM_SYMS      = ${C_ABSSYM}
SA_LIBS      += ${CLIB}
DBG_LIBS     += ${DEBUGLIBS}

ROM_OBJS_     = $(addsuffix .o,${ROM_OBJS})
SA_OBJS_      = $(addsuffix .o,${SA_OBJS})
DBG_OBJS_     = $(addsuffix .od,${DBG_OBJS})
PP_OBJS_      = $(addsuffix .i,$(filter-out ${CMHGFILE} ${RES_OBJ},${DBG_OBJS}))
EXPORTING_HDRS     = $(addsuffix .exphdr,${HDRS})
EXPORTING_ASMHDRS  = $(addsuffix .expasm,${ASMHDRS})
EXPORTING_ASMCHDRS = $(addsuffix .expasmc,${ASMCHDRS})

ifeq ($(filter rom%,${MAKECMDGOALS}),)
CDEFINES     += ${RAMCDEFINES}
ASMDEFINES   += ${RAMASMDEFINES}
RES_FILES_    = ${INSTRAM_FILES}
RES_DEPENDS_  = ${INSTRAM_DEPENDS}
else
CDEFINES     += ${ROMCDEFINES}
ASMDEFINES   += ${ROMASMDEFINES}
RES_FILES_    = ${INSTROM_FILES}
RES_DEPENDS_  = ${INSTROM_DEPENDS}
endif

ifneq ($(filter debug%,${MAKECMDGOALS}),)
CMHGFLAGS    += ${CMHGDFLAGS}  # Affects both object and header generation 
endif

TOKENS       ?= ${HDRDIR}/Global/Tokens
# Unlike with AAsmModule, we enforce this filename, to prevent any cross-compilation issues being introduced
TOKENSOURCE  := TokHelpSrc.s

SOURCES_TO_SYMLINK += $(wildcard c/*) $(wildcard c++/*) $(wildcard cmhg/*) $(wildcard h/*) $(wildcard hdr/*) $(wildcard s/*) VersionNum VersionASM

ifeq ("${INCLUDED_STDTOOLS}","")
include StdTools
endif

ifneq (objs,$(notdir ${CURDIR}))

# Makefile invoked from same directory
# Create link farm, then execute the makefile from within it

ifeq (clean,${MAKECMDGOALS})
# With a double-colon rule which can have additional actions assigned from the
# master makefile, we'd normally need the master makefile to include the
# ${CURDIR} check to ensure that it's performed on the same invocation as us.
# However, there's no real benefit to performing clean from within the objs
# directory, and it adds an ordering problem between the different double-colon
# rules (the one that deletes the objs directory has to be last otherwise the
# cwd is invalid for the others) so to simplify things, we only ever do cleans
# from the same directory as the Makefile.
clean::
	@echo Cleaning...
	@rm -rf objs
	@echo ${COMPONENT}: cleaned
else
all export export_hdrs export_libs resources rom rom_link standalone install debug gpa_debug prepro links: ${SYMLINK_DEPEND}
	$(foreach linksource,${SOURCES_TO_SYMLINK}, \
		$(shell \
			linkdest=`echo ${linksource} | sed -e 's,\([^/]*\)/\([^/]*\)$$,\2.\1,' -e 's,^,objs/,'`; \
			linkdestdir=`echo $$linkdest | sed -e 's,/[^/]*$$,,'`; \
			linkbackpath=`echo $$linkdestdir | sed -e 's,[^/]*,..,g'`; \
			[ -d ${linksource} ] || [ -L $$linkdest ] || mkdir -p $$linkdestdir; \
			[ -d ${linksource} ] || [ -L $$linkdest ] || ln -s $$linkbackpath/${linksource} $$linkdest; \
		 ) \
	)
	@[ -L objs/Resources ] || ln -s ../Resources objs/Resources
	@mkdir -p objs
ifneq (links,${MAKECMDGOALS})
	@${MAKE} -C objs -f ../$(firstword ${MAKEFILE_LIST}) ${MAKECMDGOALS}
endif
endif

else

# Makefile invoked from objs subdirectory

ASM2TXT_BASE := $(word 1,${ASM2TXT})
ASM2TXT_EXT  := $(word 2,${ASM2TXT})
ifneq ("${ASM2TXT_EXT}","")
ASM2TXT_EXT  := .${ASM2TXT_EXT}
endif

ifeq ("${INCLUDED_MODULELIBS}","")
include ModuleLibs
endif

CFLAGS       := ${C_MODULE} ${C_NO_STKCHK} ${CFLAGS}

ifeq ("${INCLUDED_MODSTDRULE}","")
include ModStdRule
endif
ifeq ("${INCLUDED_DBGRULES}","")
include DbgRules
endif

ifneq ("${ASM2TXT}","")
${ASM2TXT_SUBDIR}${ASM2TXT_BASE}${ASM2TXT_EXT}: ${ASM2TXT_BASE}.o
	${LDBIN} $@ $^
endif

#
# General rules
#
all: ${DBG_TARGET}${SUFFIX_MODULE} ${SA_TARGET}${SUFFIX_MODULE} ${ROM_TARGET}.aof
	@${ECHO} ${COMPONENT}: all built

# GNU make seems to treat any double-colon rule with no dependencies as
# always out-of-date, therefore always rebuilds it and anything which in turn
# depends on the target of the double-colon rule. So use a single-colon rule
# instead. If any cross builds need to create extra directories on a
# per-component basis, we'll cross that bridge when we get to it.
${DIRS}:
	${TOUCH} $@

#
# Export phases
#
export${CUSTOMEXP}: export_${PHASE}
	@${NOP}

export_: export_hdrs export_libs
	@${NOP}

create_exp_hdr_dirs:
	${MKDIR} ${C_EXP_HDR}
	${MKDIR} ${EXP_HDR}

ifneq (${CMHGFILE},)
${CMHGAUTOHDR}_h_: ${DIRS} ${CMHGFILE}.h
	${AWK} -- "/.ifndef ${CMHGFILE_SWIPREFIX}/,/endif/" ${CMHGFILE}.h > ${CMHGAUTOHDR}_h_
endif

ifneq ($(findstring ${CMHGAUTOHDR},${HDRS}),)
${CMHGAUTOHDR}.exphdr: ${CMHGAUTOHDR}_h_ ${CMHGAUTOHDR}.h
	${FAPPEND} ${C_EXP_HDR}/${CMHGAUTOHDR}.h ${CMHGAUTOHDR}.h ${CMHGAUTOHDR}_h_
endif

ifneq ($(findstring ${CMHGAUTOHDR},${ASMCHDRS}),)
${CMHGAUTOHDR}.expasmc: ${CMHGAUTOHDR}_h_ ${CMHGAUTOHDR}.hdr
	${HDR2H} ${CMHGAUTOHDR}.hdr ${C_EXP_HDR}/${CMHGAUTOHDR}.h
	${FAPPEND} ${C_EXP_HDR}/${CMHGAUTOHDR}.h ${C_EXP_HDR}/${CMHGAUTOHDR}.h ${CMHGAUTOHDR}_h_
endif

ifneq (${CMHGDEPENDS},)
CMHGDEPENDS_ = $(addsuffix .o,${CMHGDEPENDS}) $(addsuffix .od,${CMHGDEPENDS}) $(addsuffix .i,${CMHGDEPENDS})
${CMHGDEPENDS_}: ${CMHGFILE}.h
endif

ifeq (${TOKHELPSRC},${TOKENSOURCE})
TOKHELPDEPENDS_ = $(addsuffix .o,${TOKHELPDEPENDS}) $(addsuffix .od,${TOKHELPDEPENDS})
${TOKHELPDEPENDS_}: ${TOKHELPSRC}
endif

${TOKENSOURCE}: ${HELPSRC} ${TOKENS}
	${TOKENISE} ${TOKENS} ${HELPSRC} $@

ifeq ("${MODULEWRAP}","yes")
modulewrap.s: ${LIBDIR}/RISC_OSLib/modulewrap.s
	${CP} $^ $@
endif

.SUFFIXES: .exphdr .expasm .expasmc .h .hdr
.h.exphdr:;    ${CP} $< ${C_EXP_HDR}/$<
.hdr.expasm:;  ${CP} $< ${EXP_HDR}/$*
.hdr.expasmc:; ${HDR2H} $< ${C_EXP_HDR}/$*.h

export_hdrs${CUSTOMEXP}: create_exp_hdr_dirs ${DIRS} ${EXPORTING_HDRS} ${EXPORTING_ASMHDRS} ${EXPORTING_ASMCHDRS}
	@${ECHO} ${COMPONENT}: header export complete

export_libs${CUSTOMEXP}:
	@${ECHO} ${COMPONENT}: no exported libraries

#
# Resources rules
#
resources${CUSTOMRES}:: resources-${CMDHELP}
	@${ECHO} ${COMPONENT}: resources copied to Messages module

ifeq (${CUSTOMRES},no)
resources:
	@${ECHO} ${COMPONENT}: no resources to export
endif        

resources_extra: ${RES_DEPENDS_}
ifneq (${RES_FILES_},)
	${INSTRES} -I Resources.${USERIF}.${LOCALE},Resources.${USERIF}.UK,Resources.${LOCALE},Resources.UK,Resources ${RESFSDIR} ${RES_FILES_}
endif
ifneq (,$(filter Messages,${INSTRES_VERSION}))
	${INSERTVERSION} ${RESFSDIR}/Messages > ${RESFSDIR}/_Awk_
	${CP} ${RESFSDIR}/_Awk_ ${RESFSDIR}/Messages ${CPFLAGS}
	${RM} ${RESFSDIR}/_Awk_
	for path in ${USERIF}/${LOCALE} ${USERIF}/UK ${LOCALE} UK ""; do if [ -f Resources/$$path/Messages ]; then touch -r Resources/$$path/Messages ${RESFSDIR}/Messages; break; fi; done
endif
	@${NOP}

resources_common:
	${MKDIR} ${RESFSDIR}
	${INSTRES} -I Resources.${USERIF}.${LOCALE},Resources.${USERIF}.UK,Resources.${LOCALE},Resources.UK,Resources ${RESFSDIR} [Messages]

resources_cmdhelp: ${MERGEDMSGS}
	mv ${MERGEDMSGS} ${RESFSDIR}/Messages

resources-None: resources_common resources_extra
	@${NOP}

resources-: resources_common resources_cmdhelp resources_extra
	@${NOP}

${RES_OBJ}.o: ${DIRS} resources-${CMDHELP}
	${INSTVIARG} ${MERGEDRDIR} ${RES_PATH} _ResGen_
	${RESGEN} ${RES_AREA} $@ -via _ResGen_

${RES_OBJ}.od: ${RES_OBJ}.o
	${CP} $< $@

ifeq ($(filter no custom,${CUSTOMRES}),)
${MERGEDMSGS}:
	${MKDIR} ${MERGEDRDIR}/tmp
	${MKDIR} ${MERGEDRDIR}/${TARGET}
	${TOUCH} ${MERGEDRDIR}/tmp/Messages
	${TOUCH} ${MERGEDRDIR}/tmp/CmdHelp
	${INSTRES} -I Resources.${USERIF}.${LOCALE},Resources.${USERIF}.UK,Resources.${LOCALE},Resources.UK,Resources ${MERGEDRDIR}/tmp [Messages] [CmdHelp]
	${CAT} ${MERGEDRDIR}/tmp/Messages ${MERGEDRDIR}/tmp/CmdHelp > $@
	${WIPE} ${MERGEDRDIR}/tmp
else
${MERGEDMSGS}::
	@${NOP}
endif

#
# ROM build rules
#
rom${CUSTOMROM}: ${ROM_TARGET}.aof
	@${ECHO} ${COMPONENT}: rom module built

rom_link${CUSTOMROM}: ${LNK_TARGET}.linked
	${CP} ${LNK_TARGET}.linked ${LINKDIR}/${TARGET}
	${CP} ${LNK_TARGET}_sym.linked ${LINKDIR}/${TARGET}_sym
	@${ECHO} ${COMPONENT}: rom_link complete

${ROM_TARGET}.aof: ${ROM_DEPEND} ${DIRS} ${ROM_OBJS_} ${ROM_LIBS}
	${LD} -o $@ -aof ${ROM_OBJS_} ${ROM_LIBS}

${LNK_TARGET}.linked: ${FORCEROMLINK} ${ROM_SYMS} ${ROM_TARGET}.aof
	${LD} ${LDFLAGS} ${LDLINKFLAGS} -o $@ -rmf -base ${ADDRESS} ${ROM_TARGET}.aof ${ROM_SYMS} -Symbols ${LNK_TARGET}_sym.linked

#
# Standalone rules
#
install${CUSTOMSA}: ${SA_TARGET}${SUFFIX_MODULE}
	${MKDIR} ${INSTDIR}
	${CP} ${SA_TARGET}${SUFFIX_MODULE} ${INSTDIR}/${TARGET}${SUFFIX_MODULE}
	@${ECHO} ${COMPONENT}: ram module installed

standalone${CUSTOMSA}: ${SA_TARGET}${SUFFIX_MODULE}
	@${ECHO} ${COMPONENT}: ram module built

debug${CUSTOMDBG}: ${DBG_TARGET}${SUFFIX_MODULE}
	@${ECHO} ${COMPONENT}: debug module built

gpa_debug${CUSTOMGPA}: ${GPA_TARGET}.gpa
	@${ECHO} ${COMPONENT}: GPA debug built

prepro: ${DIRS} ${PP_OBJS_}
	@${ECHO} ${COMPONENT}: sources preprocessed

${SA_TARGET}${SUFFIX_MODULE}: ${SA_DEPEND} ${DIRS} ${SA_OBJS_} ${SA_LIBS}
	${LD} ${LDFLAGS} ${LDRAMFLAGS} -o $@ -rmf ${SA_OBJS_} ${SA_LIBS}
	${MODSQZ} ${MODSQZFLAGS} $@

${DBG_TARGET}${SUFFIX_MODULE}: ${SA_DEPEND} ${DIRS} ${DBG_OBJS_} ${SA_LIBS} ${DBG_LIBS}
	${LD} ${LDFLAGS} ${LDRAMFLAGS} -o $@ -rmf ${DBG_OBJS_} ${DBG_LIBS} ${SA_LIBS}

${GPA_TARGET}.gpa: ${AIF_TARGET}.aif
	${TOGPA} -s aif.${AIF_TARGET} $@

${AIF_TARGET}.aif: ${DBG_TARGET}${SUFFIX_MODULE}
	${LD} -aif -bin -d -o ${AIF_TARGET}.aif ${DBG_OBJS_} ${DBG_LIBS} ${SA_LIBS}

include $(wildcard *.d)
include $(wildcard *.dd)

endif

# EOF