#!/usr/local/bin/cbsd
#v11.1.16
CBSDMODULE="sys"
MYARG=""
MYOPTARG="arch basename ccache clean distcc maxjobs nice notify stable target_arch target_cputype ver"
MYDESC="Build FreeBSD world from sources (basejail)"
ADDHELP="

${H3_COLOR}Description${N0_COLOR}:

Compiling the FreeBSD base after obtaining the source code via 'cbsd srcup',
( located in the ~cbsd/src/src_\$ver directory ). As a result, you get the
FreeBSD base tree in ~cbsd/basejail/ ( after 'cbsd installworld' ) directory.
These directories are used to create containers (baserw = 1) or mount 
the jail RO (baserw = 0) via the 'nullfs' overlay.

There are alternative and faster ways to get basejail files:

 - via network: 'cbsd repo action=get sources=base';
 - from local: from archive or current base;

Which 'cbsd buildworld' you can customize build/base and use it via alternative name
via 'basename' args.

${H3_COLOR}Options${N0_COLOR}:

 ${N2_COLOR}arch=${N0_COLOR}        - <name>, build non-native architectures.
 ${N2_COLOR}basename=${N0_COLOR}    - Prefix for directory name, can be used for jail
                as alternative base.
 ${N2_COLOR}ccache=${N0_COLOR}      - 1 - enable ccache (must be installed on the system).
 ${N2_COLOR}distcc=${N0_COLOR}      - 1 - enable distcc (must be installed on the system).
 ${N2_COLOR}nice=${N0_COLOR}        - num: overwrite default nice: '19'.
 ${N2_COLOR}maxjobs=${N0_COLOR}     - num: limit number of parallel job (-j for make),
                by default: use all host CPUs cores.
 ${N2_COLOR}stable=${N0_COLOR}      - 1 for RELENG_X.
 ${N2_COLOR}target_arch=${N0_COLOR} - <name>, build non-native target arch.
 ${N2_COLOR}ver=${N0_COLOR}         - set version: '13.0', '13.1';
                when version without minor version: e.g: 
               '13' or '12' - you will receive RELENG (stable=1), not release.

${H3_COLOR}Examples${N0_COLOR}:

 # cbsd buildworld\n\
 # cbsd buildworld ver=13.0 arch=arm64 target_arch=aarch64
 # cbsd buildworld ver=13.0 arch=riscv target_arch=riscv64

${H3_COLOR}See also${N0_COLOR}:

 cbsd installworld --help
 cbsd bases --help
 cbsd jcreate --help
 cbsd srcup --help
 cbsd world --help
 cbsd install-pkg-world --help

"

. ${subrdir}/nc.subr
nice=
idprio=
. ${cbsdinit}
. ${system}

# MAIN
over="${ver}"
oarch="${arch}"
[ -z "${nice}" ] && nice=19
[ -z "${idprio}" ] && idprio=31		# dead/lock? see man BUGS


. ${subrdir}/build.subr
. ${subrdir}/distccache.subr
. ${subrdir}/mailtools.subr
readconf buildworld.conf
. ${subrdir}/universe.subr

# for checkout_method
readconf srcup.conf

init_distcc
init_notify
init_target_arch
init_srcdir
init_supported_arch
init_make_flags
init_basedir

if [ "${ccache}" = "1"  ]; then
	init_ccache_dir
	if ! ccache_check; then
		${ECHO} "${N1_COLOR}*** ${N2_COLOR}Ccache disabled: no binaries at /usr/local/bin/ccache${N1_COLOR} ***${N0_COLOR}"
		ccache=0
	fi

	${ECHO} "${N1_COLOR}*** ${N2_COLOR}Ccache enabled${N1_COLOR} ***${N0_COLOR}"
	export PATH=/usr/local/libexec/ccache:${PATH}
	export CCACHE_PATH=/usr/bin:/usr/local/bin
	export CCACHE_DIR=${ccache_dir_source}
	CCACHE_SIZE="8"
	/usr/local/bin/ccache -M ${CCACHE_SIZE}
else
	ccache=0
fi

${TRUNCATE_CMD} -s0 ${ftmpdir}/make.$$.conf

export __MAKE_CONF=${ftmpdir}/make.$$.conf
prepare_make_conf ${origmakeconf} ${__MAKE_CONF}

init_make_flags

LOCKFILE=${ftmpdir}/$( ${miscdir}/cbsd_md5 ${MAKEOBJDIRPREFIX} ).lock
[ ${notify} -eq 1 ] && BLDLOG="${tmpdir}/build.$$.log"
makelock ${LOCKFILE} "${RM_CMD} -f ${__MAKE_CONF} ${BLDLOG}; cleanup_bases"

[ ${distcc} -eq 1 ] && export DISTCC_HOSTS="${CBSD_DISTCCHOST}"

register_base arch=${arch} ver=${ver} source="buildworld" auto_baseupdate=0

# CBSD QUEUE
if [ "${mod_cbsd_queue_enabled}" = "YES" -a -z "${MOD_CBSD_QUEUE_DISABLED}" ]; then
	readconf cbsd_queue.conf
	[ -z "${cbsd_queue_backend}" ] && MOD_CBSD_QUEUE_DISABLED="1"
fi

if [ "${mod_cbsd_queue_enabled}" = "YES" -a -z "${MOD_CBSD_QUEUE_DISABLED}" ]; then
	[ -n "${cbsd_bases_queue_name}" ] && ${cbsd_queue_backend} cbsd_bases_queue_name=${cbsd_bases_queue_name} cmd=world id=base${ver}-${arch}-${stable} platform=${platform} arch=${arch} targetarch=${targetarch} ver=${ver} stable="${stable}" date="-" elf="-" status=1
fi

if [ -x "${BASE_DIR}/bin/sh" ]; then
	baseelf=$( ${miscdir}/elf_tables --ver ${BASE_DIR}/bin/sh 2>/dev/null )
	[ -z "${baseelf}" ] && baseelf="0"
	register_base arch=${arch} ver=${ver} source="installworld" auto_baseupdate=0	# again: update elf
	base_status_is_maintenance_soft
else
	base_status_is_maintenance_hard
fi

${ECHO} "${N1_COLOR}buildworld for TARGET:${N2_COLOR}${arch} ${N1_COLOR}TARGET_ARCH:${N2_COLOR}${target_arch}${N0_COLOR}"

build_arch="${arch}"
build_target_arch="${target_arch}"

# map amd64 -> x86_64 for DFLY
if [ "${platform}" = "DragonFly" ]; then
	case "${arch}" in
		amd64)
			build_arch="x86_64"
			build_target_arch="x86_64"
			;;
	esac
fi

st_time=$( ${DATE_CMD} +%s )
if [ ${notify} -eq 1 ]; then
	[ -z "${TAILSTRING}" ] && TAILSTRING=50
	# idprio deadlock? idprio overwrite nice?
	# without idprio
	cbsdlogger NOTICE ${CBSD_APP}: buildworld started: ${NICE_CMD} -n ${nice} ${MAKE_CMD} ${NUMJOBS} -C ${SRC_DIR} buildworld ${NOCLEANUP} TARGET=${build_arch} TARGET_ARCH="${build_target_arch}"
	script ${BLDLOG} ${NICE_CMD} -n ${nice} ${MAKE_CMD} ${NUMJOBS} -C ${SRC_DIR} buildworld ${NOCLEANUP} TARGET=${build_arch} TARGET_ARCH="${build_target_arch}"
	res=$?
else
	# idprio deadlock? idprio overwrite nice?
	# without idprio
	cbsdlogger NOTICE ${CBSD_APP}: buildworld started: ${NICE_CMD} -n ${nice} ${MAKE_CMD} ${NUMJOBS} -C ${SRC_DIR} buildworld ${NOCLEANUP} TARGET=${build_arch} TARGET_ARCH="${build_target_arch}"
	${NICE_CMD} -n ${nice} ${MAKE_CMD} ${NUMJOBS} -C ${SRC_DIR} buildworld ${NOCLEANUP} TARGET=${build_arch} TARGET_ARCH="${build_target_arch}"
	res=$?
fi

. ${subrdir}/time.subr
end_time=$( ${DATE_CMD} +%s )
diff_time=$(( end_time - st_time ))
run_time=$( displaytime ${diff_time} )

if [ ${notify} -eq 1 ]; then

	${CAT_CMD} >> ${BLDLOG} << EOF
Start build date: ${st_time}
End build date: ${end_time}
Runtime: ${run_time}
EOF

fi

${CAT_CMD} <<EOF
Start build date: ${st_time}
End build date: ${end_time}
Runtime: ${run_time}
EOF

cbsdlogger NOTICE ${CBSD_APP}: buildworld ended: runtime: ${run_time}, retcode: ${_ret}

cleanup_bases

DT_END=$( ${DATE_CMD} +%s )

init_scm_and_version

if [ ${res} -ne 0 ]; then
	[ ${notify} -eq 1 ] && send_notification -s "[CBSD ${nodename}] buildworld ${basename} ${ver} ${arch} ${target_arch} r${svnrev} failed." -b "`tail -n${TAILSTRING} ${BLDLOG}`"

	# CBSD QUEUE
	if [ "${mod_cbsd_queue_enabled}" = "YES" -a -z "${MOD_CBSD_QUEUE_DISABLED}" ]; then
		[ -n "${cbsd_bases_queue_name}" ] && ${cbsd_queue_backend} cbsd_bases_queue_name=${cbsd_bases_queue_name} cmd=world id=base${ver}-${arch}-${stable} status=2
	fi

	exit ${res}
fi

if [ ${res} -eq 0 -a ${notify} -eq 1 ]; then
	send_notification -s "[CBSD ${nodename}] buildworld ${basename} ${ver} ${arch} ${target_arch} r${svnrev} complete in ${run_time}" -f ${BLDLOG}
fi

# CBSD QUEUE
if [ "${mod_cbsd_queue_enabled}" = "YES" -a -z "${MOD_CBSD_QUEUE_DISABLED}" ]; then
	baseelf=
	baseelf=$( ${miscdir}/elf_tables --ver ${BASE_DIR}/bin/sh 2>/dev/null )
	[ -n "${cbsd_bases_queue_name}" ] && ${cbsd_queue_backend} cbsd_bases_queue_name=${cbsd_bases_queue_name} cmd=update id=base${ver}-${arch}-${stable} platform=${platform} arch=${arch} targetarch=${targetarch} ver=${ver} stable="${stable}" date="${DT_END}" elf="${baseelf}" status=1
	sleep 2
	[ -n "${cbsd_bases_queue_name}" ] && ${cbsd_queue_backend} cbsd_bases_queue_name=${cbsd_bases_queue_name} cmd=world id=base${ver}-${arch}-${stable} status=2
fi

exit 0
