#       $NetBSD: Makefile.image,v 1.44 2024/05/17 21:31:10 christos Exp $
#
# Makefile snippet to build a tree from the provided lists,
# and make an ffs file system image from that tree
#
# Required variables:
#       NETBSDSRCDIR    top level of src tree (set by <bsd.own.mk>)
#       LISTS           list file(s) to use
#       IMAGEDEPENDS    depends for ${IMAGE}
#       IMAGEENDIAN     endianness of ${IMAGE}
#       IMAGESIZE       size of ${IMAGE}
#       MTREECONF       mtree specfiles to use to build a master specfile
#
# Optional variables:
#       IMAGE           name of target image
#       IMAGEPREBUILD   additional operations to run pre image creation
#       IMAGEPOSTBUILD  operation to run on ${IMAGE} ${.TARGET} after its built
#                       (if this returns non zero, ${.TARGET} is removed)
#       IMAGERUNTIME    files/directories to copy from $DESTDIR onto the image
#       IMAGESPECEXTRA  files/directories to add to the spec
#       CRUNCHBIN       name of crunchgen(1)ed binary
#       DESTDIR         destination directory
#       MAKEFS_FLAGS    extra options to ${TOOL_MAKEFS}
#       PARSELISTENV    environment variables to set for parselist.awk
#       WORKDIR         directory to build image in to
#       IMAGETAR        tar.gz file to create containing ${IMAGE}'s contents
#
#       IMAGE_RELEASEDIR        where to install ${IMAGE}.gz
#       IMAGETAR_RELEASEDIR     where to install ${IMAGETAR}
#

if !defined(_MAKEFILE_IMAGE_)
_MAKEFILE_IMAGE_=1


WORKDIR?=       work
WORKSPEC?=      work.spec
WORKBUILT?=     work.built
CUROBJDIR!=     cd ${.CURDIR} && ${PRINTOBJDIR}

include "${DISTRIBDIR}/common/Makefile.parselist"

PARSELISTENV+=  TARGETDIR=${.OBJDIR}/${WORKDIR:Q}

if ${MKREPRO_TIMESTAMP:Uno} != "no"
MAKEFS_TIMESTAMP=-T "${MKREPRO_TIMESTAMP}"
PAX_TIMESTAMP=--timestamp "${MKREPRO_TIMESTAMP}"
GZIP_N_FLAG=-n
endif
MAKESPEC=       ${HOST_SH} ${NETBSDSRCDIR}/etc/makespec

if ${MAKEVERBOSE} >= 2
PAX_v?= -v
else
PAX_v?=
endif


GZIP_FLAGS= -9 ${GZIP_N_FLAG}

if !target(${WORKBUILT})                                        # {
${WORKBUILT}: ${IMAGEDEPENDS} ${WORKSPEC} ${PARSELISTDEP} ${LISTS}
#       There is a .PHONY ${CRUNCHBIN}, so check if out of date by hand
#       Default to `.' if ${CRUNCHBIN} isn't set, to always force a rebuild.
       [ "${.OODATE}" = ${CRUNCHBIN:U.} -a -f ${WORKBUILT} -a ${WORKBUILT} -nt ${CRUNCHBIN:U.} ]  || { \
       ${_MKSHMSG} "  build " ${.CURDIR:T}/${WORKDIR}; \
       rm -rf ${WORKDIR} ${WORKBUILT}; \
       mkdir -m 755 ${WORKDIR} &&  \
       ${TOOL_MTREE} -def ${WORKSPEC} -p ${WORKDIR}/ -UW && \
       ${PARSELIST} -v mode=populate ${LISTS} | \
       ${HOST_SH} -e ${POPULATE_DEBUG} \
       && touch ${WORKBUILT} ; \
       }

CLEANFILES+=    ${WORKBUILT}

clean cleandir distclean: cleanfsimage

PHONY: cleanfsimage

cleanfsimage:
       -rm -rf ${WORKDIR} ${WORKBUILT}

endif   # ! target (${WORKBUILT})                               # }

if !target(${WORKSPEC})                                 # {
${WORKSPEC}: ${MTREECONF} ${LISTS} ${PARSELISTDEP}
       ${_MKTARGET_CREATE}
       -rm -f ${.TARGET} ${.TARGET}.tmp
       ( for i in ${MTREECONF}; do     \
               echo "# --" ; \
               echo "# entries from: $$i" ; \
               echo "#" ; \
               cat $$i ;               \
               echo "/unset all" ;     \
       done ) >> ${.TARGET}.tmp
       ${PARSELIST} -v mode=mtree ${LISTS} >> ${.TARGET}.tmp \
       && mv ${.TARGET}.tmp ${.TARGET}

CLEANFILES+=    ${WORKSPEC} ${WORKSPEC}.tmp
endif   # ! target (${WORKSPEC})                                # }

if defined(IMAGE)                                               # {
IMGMAKEFSOPTIONS?= -o bsize=4096,fsize=512
${IMAGE}: ${WORKBUILT}
if defined(IMAGEPREBUILD)
       ${IMAGEPREBUILD}
endif
       if [ "X${IMAGERUNTIME}" != "X" ]; then                          \
               release_destdir=${CUROBJDIR}/${WORKDIR};                \
               cd ${DESTDIR};                                          \
               for imge in ${IMAGERUNTIME};                            \
               do                                                      \
                       ${TOOL_PAX} ${PAX_TIMESTAMP} -rw -pp ${PAX_v}   \
                               $${imge} $$release_destdir;             \
               done;                                                   \
               cd "${CUROBJDIR}";                                      \
       fi
       for i in ${IMAGESPECEXTRA}; do                                  \
               if [ -n "$$i" ] && [ -e ${WORKDIR}/$$i ]; then          \
                   ${MAKESPEC} -d ${WORKDIR} $$i >> ${WORKSPEC};       \
               fi;                                                     \
       done
       [ "${.OODATE}" = ${WORKBUILT} -a -f ${IMAGE} -a ! ${IMAGE} -ot ${WORKBUILT} ]  || { \
       ${_MKSHMSG_CREATE} ${.CURDIR:T}/${.TARGET}; \
       rm -f ${.TARGET} ${.TARGET}.tmp; \
       ${TOOL_MAKEFS} -t ffs -B ${IMAGEENDIAN} -s ${IMAGESIZE} -F ${WORKSPEC} \
           -xx ${MAKEFS_TIMESTAMP} -N ${NETBSDSRCDIR}/etc ${IMGMAKEFSOPTIONS} \
           -o optimization=space,minfree=0 \
           ${MAKEFS_FLAGS} ${.TARGET}.tmp ${WORKDIR} \
       && mv -f ${.TARGET}.tmp ${.TARGET}; \
       }
if defined(IMAGEPOSTBUILD)
       ${IMAGEPOSTBUILD} || { rm -f ${.TARGET} ; false; }
endif

PHONY: fsimage
fsimage: ${IMAGE}

${IMAGE}.gz: ${IMAGE}
       ${_MKTARGET_CREATE}
       -rm -f ${.TARGET}
       ${TOOL_GZIP} ${GZIP_FLAGS} -c ${.ALLSRC} > ${.TARGET}

realall: ${IMAGE}

if defined(IMAGE_RELEASEDIR)
release:: check_RELEASEDIR .WAIT ${IMAGE}.gz
       ${RELEASE_INSTALL} ${IMAGE}.gz \
           ${RELEASEDIR}/${RELEASEMACHINEDIR}/${IMAGE_RELEASEDIR}
endif

CLEANFILES+=    ${IMAGE} ${IMAGE}.gz ${IMAGE}.tmp
endif   # ! defined(IMAGE)                                      # }


if defined(IMAGETAR)                                            # {
${IMAGETAR}: ${WORKBUILT} ${WORKSPEC} ${IMAGEDEPENDS}
       ${_MKTARGET_CREATE}
       ( cd ${WORKDIR}; \
         GZIP=${GZIP_FLAGS:Q} \
         ${TOOL_PAX} ${PAX_TIMESTAMP} --use-compress-program=${TOOL_GZIP:Q} \
             -ON ${NETBSDSRCDIR}/etc -wdM <${.OBJDIR}/${WORKSPEC} \
       ) > ${.TARGET}.tmp \
       && mv ${.TARGET}.tmp ${.TARGET}

realall: ${IMAGETAR}

CLEANFILES+=    ${IMAGETAR} ${IMAGETAR}.tmp

if defined(IMAGETAR_RELEASEDIR)
release:: check_RELEASEDIR .WAIT ${IMAGETAR}
       ${RELEASE_INSTALL} ${IMAGETAR} \
           ${RELEASEDIR}/${RELEASEMACHINEDIR}/${IMAGETAR_RELEASEDIR}
endif

endif   # ! defined(IMAGETAR)                                   # }


endif   # _MAKEFILE_IMAGE_