1# SPDX-License-Identifier: BSD-2-Clause
2#
3# $Id: jobs.mk,v 1.17 2024/02/17 17:26:57 sjg Exp $
4#
5#	@(#) Copyright (c) 2012-2023, Simon J. Gerraty
6#
7#	This file is provided in the hope that it will
8#	be of use.  There is absolutely NO WARRANTY.
9#	Permission to copy, redistribute or otherwise
10#	use this file is hereby granted provided that
11#	the above copyright notice and this notice are
12#	left intact.
13#
14#	Please send copies of changes and bug-fixes to:
15#	sjg@crufty.net
16#
17
18# This makefile is used by top-level makefile.
19# With the following:
20#
21#	.if make(*-jobs)
22#	.include <jobs.mk>
23#	.endif
24#
25# 
26# Then if you do:
27#
28#	mk target-jobs
29#
30# We will run:
31#
32#	${MAKE} -j${JOB_MAX} target > ${JOB_LOGDIR}/target.log 2>&1
33#
34# JOB_MAX should be something like 1.2 - 1.5 times the number of
35# available CPUs.
36# If bmake sets .MAKE.JOBS.C=yes we can use -jC and
37# JOB_MAX defaults to JOB_MAX_C (default 1.33C).
38# Otherwise we use 8.
39#
40
41now_utc ?= ${%s:L:localtime}
42.if !defined(start_utc)
43start_utc := ${now_utc}
44.endif
45
46.if make(*-jobs)
47.info ${.newline}${TIME_STAMP} Start ${.TARGETS}
48
49JOB_LOGDIR ?= ${SRCTOP:H}
50JOB_LOG = ${JOB_LOGDIR}/${.TARGET:S,-jobs,,:S,/,_,g}.log
51JOB_LOG_GENS ?= 4
52# we like to rotate logs
53.if empty(NEWLOG_SH)
54.for d in ${.SYSPATH:U${.PARSEDIR}:@x@$x $x/scripts@}
55.if exists($d/newlog.sh)
56NEWLOG_SH := $d/newlog.sh
57.if ${MAKE_VERSION} > 20220924
58.break
59.endif
60.endif
61.endfor
62.if empty(NEWLOG_SH)
63.ifdef M_whence
64NEWLOG_SH := ${newlog.sh:L:${M_whence}}
65.else
66NEWLOG_SH := ${(type newlog.sh) 2> /dev/null:L:sh:M/*}
67.endif
68.endif
69.endif
70.if !empty(NEWLOG_SH) && exists(${NEWLOG_SH})
71NEWLOG := sh ${NEWLOG_SH}
72JOB_NEWLOG_ARGS ?= -S -n ${JOB_LOG_GENS}
73.else
74NEWLOG = :
75.endif
76
77.if ${.MAKE.JOBS:U0} > 0
78JOB_MAX = ${.MAKE.JOBS}
79.else
80# This should be derrived from number of cpu's
81.if ${.MAKE.JOBS.C:Uno} == "yes"
82# 1.2 - 1.5 times nCPU works well on most machines that support -jC
83# if the factor is floating point, the C suffix isn't needed
84JOB_MAX_C ?= 1.33
85JOB_MAX ?= ${JOB_MAX_C}
86.endif
87JOB_MAX ?= 8
88JOB_ARGS += -j${JOB_MAX}
89.endif
90
91# we need to reset .MAKE.LEVEL to 0 so that
92# build orchestration works as expected (DIRDEPS_BUILD)
93${.TARGETS:M*-jobs}:
94	@${NEWLOG} ${JOB_NEWLOG_ARGS} ${JOB_LOG}
95	@echo "${TIME_STAMP} Start ${.TARGET:S,-jobs,,} ${JOB_ARGS} ${JOB_LOG_START} log=${JOB_LOG}" | tee ${JOB_LOG}
96	@cd ${.CURDIR} && env MAKELEVEL=0 \
97	${.MAKE} ${JOB_ARGS} _TARGETS=${.TARGET:S,-jobs,,} ${.TARGET:S,-jobs,,} >> ${JOB_LOG} 2>&1
98
99.endif
100
101.END: _build_finish
102.ERROR: _build_failed
103
104_build_finish:  .NOMETA
105	@echo "${TIME_STAMP} Finished ${.TARGETS} seconds=`expr ${now_utc} - ${start_utc}`"
106
107_build_failed: .NOMETA
108	@echo "${TIME_STAMP} Failed ${.TARGETS} seconds=`expr ${now_utc} - ${start_utc}`"
109