xref: /freebsd/contrib/bmake/unit-tests/varname-makeflags.mk (revision 148ee84570001f46b7b667c86573d378101c3801)
1*148ee845SSimon J. Gerraty# $NetBSD: varname-makeflags.mk,v 1.8 2023/06/01 07:27:30 rillig Exp $
22c3632d1SSimon J. Gerraty#
38c973ee2SSimon J. Gerraty# Tests for the environment variable 'MAKEFLAGS', from which additional
48c973ee2SSimon J. Gerraty# command line arguments are read before the actual command line arguments.
58c973ee2SSimon J. Gerraty#
68c973ee2SSimon J. Gerraty# After reading the makefiles and before making the targets, the arguments
78c973ee2SSimon J. Gerraty# that were collected in '.MAKEFLAGS' and '.MAKEOVERRIDES' are written back to
88c973ee2SSimon J. Gerraty# the environment variable 'MAKEFLAGS'.
92c3632d1SSimon J. Gerraty
108c973ee2SSimon J. Gerratyall: spaces_stage_0 dollars_stage_0 append_stage_0 override_stage_0
112c3632d1SSimon J. Gerraty
128c973ee2SSimon J. Gerraty
138c973ee2SSimon J. Gerraty.if !make(*stage*)
1406b9b3e0SSimon J. Gerraty
1506b9b3e0SSimon J. Gerraty# The unit tests are run with an almost empty environment.  In particular,
168c973ee2SSimon J. Gerraty# the variable MAKEFLAGS is not set.
1706b9b3e0SSimon J. Gerraty.  if ${MAKEFLAGS:Uundefined} != "undefined"
1806b9b3e0SSimon J. Gerraty.    error
1906b9b3e0SSimon J. Gerraty.  endif
2006b9b3e0SSimon J. Gerraty
2106b9b3e0SSimon J. Gerraty# The special variable .MAKEFLAGS is influenced though.
2206b9b3e0SSimon J. Gerraty# See varname-dot-makeflags.mk for more details.
238c973ee2SSimon J. Gerraty.  if ${.MAKEFLAGS} != " -r -k"
2406b9b3e0SSimon J. Gerraty.    error
2506b9b3e0SSimon J. Gerraty.  endif
2606b9b3e0SSimon J. Gerraty
279f45a3c8SSimon J. Gerraty
289f45a3c8SSimon J. Gerraty# In POSIX mode, the environment variable MAKEFLAGS can contain letters only,
299f45a3c8SSimon J. Gerraty# for compatibility.  These letters are exploded to form regular options.
309f45a3c8SSimon J. GerratyOUTPUT!=	env MAKEFLAGS=ikrs ${MAKE} -f /dev/null -v .MAKEFLAGS
319f45a3c8SSimon J. Gerraty.  if ${OUTPUT} != " -i -k -r -s -V .MAKEFLAGS"
329f45a3c8SSimon J. Gerraty.    error
339f45a3c8SSimon J. Gerraty.  endif
349f45a3c8SSimon J. Gerraty
359f45a3c8SSimon J. Gerraty# As soon as there is a single non-alphabetic character in the environment
369f45a3c8SSimon J. Gerraty# variable MAKEFLAGS, it is no longer split.  In this example, the word
379f45a3c8SSimon J. Gerraty# "d0ikrs" is treated as a target, but the option '-v' prevents any targets
389f45a3c8SSimon J. Gerraty# from being built.
399f45a3c8SSimon J. GerratyOUTPUT!=	env MAKEFLAGS=d0ikrs ${MAKE} -r -f /dev/null -v .MAKEFLAGS
409f45a3c8SSimon J. Gerraty.  if ${OUTPUT} != " -r -V .MAKEFLAGS"
419f45a3c8SSimon J. Gerraty.    error ${OUTPUT}
429f45a3c8SSimon J. Gerraty.  endif
439f45a3c8SSimon J. Gerraty
448c973ee2SSimon J. Gerraty.endif
459f45a3c8SSimon J. Gerraty
468c973ee2SSimon J. Gerraty
478c973ee2SSimon J. Gerraty# When options are parsed, the option and its argument are appended as
488c973ee2SSimon J. Gerraty# separate words to the MAKEFLAGS for the child processes.  Special characters
498c973ee2SSimon J. Gerraty# in the option arguments are not quoted though.
508c973ee2SSimon J. Gerratyspaces_stage_0:
518c973ee2SSimon J. Gerraty	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
528c973ee2SSimon J. Gerraty	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
538c973ee2SSimon J. Gerraty	@${MAKE} -f ${MAKEFILE} spaces_stage_1 -d00000 -D"VARNAME WITH SPACES"
548c973ee2SSimon J. Gerraty
558c973ee2SSimon J. Gerraty# At this point, the 'VARNAME WITH SPACES' is no longer recognizable as a
568c973ee2SSimon J. Gerraty# single command line argument.  In practice, variable names don't contain
578c973ee2SSimon J. Gerraty# spaces.
588c973ee2SSimon J. Gerratyspaces_stage_1:
598c973ee2SSimon J. Gerraty	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
608c973ee2SSimon J. Gerraty	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
618c973ee2SSimon J. Gerraty
628c973ee2SSimon J. Gerraty
638c973ee2SSimon J. Gerraty# Demonstrate that '$' characters are altered when they are passed on to child
648c973ee2SSimon J. Gerraty# make processes via MAKEFLAGS.
658c973ee2SSimon J. Gerratydollars_stage_0:
668c973ee2SSimon J. Gerraty	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
678c973ee2SSimon J. Gerraty
688c973ee2SSimon J. Gerraty	# The '$$$$' becomes a literal '$$' when building the '${MAKE}'
698c973ee2SSimon J. Gerraty	# command line, making the actual argument 'DOLLARS=$${varname}'.
708c973ee2SSimon J. Gerraty	# At this stage, MAKEFLAGS is not yet involved.
718c973ee2SSimon J. Gerraty	@${MAKE} -f ${MAKEFILE} dollars_stage_1 DOLLARS='$$$${varname}'
728c973ee2SSimon J. Gerraty
738c973ee2SSimon J. Gerraty.if make(dollars_stage_1)
748c973ee2SSimon J. Gerraty# At this point, the variable 'DOLLARS' contains '$${varname}', which
758c973ee2SSimon J. Gerraty# evaluates to a literal '$' followed by '{varname}'.
768c973ee2SSimon J. Gerraty.  if ${DOLLARS} != "\${varname}"
778c973ee2SSimon J. Gerraty.    error
788c973ee2SSimon J. Gerraty.  endif
798c973ee2SSimon J. Gerraty.endif
808c973ee2SSimon J. Gerratydollars_stage_1:
818c973ee2SSimon J. Gerraty	# At this point, the stage 1 make provides the environment variable
828c973ee2SSimon J. Gerraty	# 'MAKEFLAGS' to its child processes, even if the child process is not
838c973ee2SSimon J. Gerraty	# another make.
848c973ee2SSimon J. Gerraty	#
858c973ee2SSimon J. Gerraty	# expect: dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}>
868c973ee2SSimon J. Gerraty	#
878c973ee2SSimon J. Gerraty	# The 'DOLLARS=\$\{varname\}' assignment is escaped so that the stage
888c973ee2SSimon J. Gerraty	# 2 make will see it as a single word.
898c973ee2SSimon J. Gerraty	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
908c973ee2SSimon J. Gerraty
918c973ee2SSimon J. Gerraty	# At this point, evaluating the environment variable 'MAKEFLAGS' leads
928c973ee2SSimon J. Gerraty	# to strange side effects as the string '\$\{varname\}' is interpreted
938c973ee2SSimon J. Gerraty	# as:
948c973ee2SSimon J. Gerraty	#
958c973ee2SSimon J. Gerraty	#	\		a literal string of a single backslash
968c973ee2SSimon J. Gerraty	#	$\		the value of the variable named '\'
978c973ee2SSimon J. Gerraty	#	{varname\}	a literal string
988c973ee2SSimon J. Gerraty	#
99*148ee845SSimon J. Gerraty	# Since the variable named '\' is not defined, the resulting value is
1008c973ee2SSimon J. Gerraty	# '\{varname\}'.  Make doesn't handle isolated '$' characters in
1018c973ee2SSimon J. Gerraty	# strings well, instead each '$' has to be part of a '$$' or be part
1028c973ee2SSimon J. Gerraty	# of a subexpression like '${VAR}'.
1038c973ee2SSimon J. Gerraty	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
1048c973ee2SSimon J. Gerraty
1058c973ee2SSimon J. Gerraty	# The modifier ':q' preserves a '$$' in an expression value instead of
1068c973ee2SSimon J. Gerraty	# expanding it to a single '$', but it's already too late, as that
1078c973ee2SSimon J. Gerraty	# modifier applies after the expression has been evaluated.  Except
1088c973ee2SSimon J. Gerraty	# for debug logging, there is no way to process strings that contain
1098c973ee2SSimon J. Gerraty	# isolated '$'.
1108c973ee2SSimon J. Gerraty	@echo '$@: MAKEFLAGS:q=<'${MAKEFLAGS:q}'>'
1118c973ee2SSimon J. Gerraty
1128c973ee2SSimon J. Gerraty	@${MAKE} -f ${MAKEFILE} dollars_stage_2
1138c973ee2SSimon J. Gerraty
1148c973ee2SSimon J. Gerraty.if make(dollars_stage_2)
1158c973ee2SSimon J. Gerraty# At this point, the variable 'DOLLARS' contains '${varname}', and since
1168c973ee2SSimon J. Gerraty# 'varname' is undefined, that expression evaluates to an empty string.
1178c973ee2SSimon J. Gerraty.  if ${DOLLARS} != ""
1188c973ee2SSimon J. Gerraty.    error
1198c973ee2SSimon J. Gerraty.  endif
1208c973ee2SSimon J. Gerratyvarname=	varvalue
1218c973ee2SSimon J. Gerraty.  if ${DOLLARS} != "varvalue"
1228c973ee2SSimon J. Gerraty.    error
1238c973ee2SSimon J. Gerraty.  endif
1248c973ee2SSimon J. Gerraty.  undef varname
1258c973ee2SSimon J. Gerraty.endif
1268c973ee2SSimon J. Gerratydollars_stage_2:
1278c973ee2SSimon J. Gerraty	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
1288c973ee2SSimon J. Gerraty	@echo '$@: dollars=<'${DOLLARS:Q}'>'
1298c973ee2SSimon J. Gerraty	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
1308c973ee2SSimon J. Gerraty	@${MAKE} -f ${MAKEFILE} dollars_stage_3
1318c973ee2SSimon J. Gerraty
1328c973ee2SSimon J. Gerratydollars_stage_3:
1338c973ee2SSimon J. Gerraty	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
1348c973ee2SSimon J. Gerraty	@echo '$@: dollars=<'${DOLLARS:Uundefined:Q}'>'
1358c973ee2SSimon J. Gerraty	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
1368c973ee2SSimon J. Gerraty
1378c973ee2SSimon J. Gerraty
138*148ee845SSimon J. Gerraty# Demonstrates in which exact order the MAKEFLAGS are built from the parent
139*148ee845SSimon J. Gerraty# MAKEFLAGS and the flags from the command line, in particular that variable
140*148ee845SSimon J. Gerraty# assignments are passed at the end, after the options.
1418c973ee2SSimon J. Gerratyappend_stage_0:
1428c973ee2SSimon J. Gerraty	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
1438c973ee2SSimon J. Gerraty	@${MAKE} -Dbefore-0 -f ${MAKEFILE} append_stage_1 VAR0=value -Dafter-0
1448c973ee2SSimon J. Gerraty
1458c973ee2SSimon J. Gerratyappend_stage_1:
1468c973ee2SSimon J. Gerraty	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
1478c973ee2SSimon J. Gerraty	@${MAKE} -Dbefore-1 -f ${MAKEFILE} append_stage_2 VAR1=value -Dafter-1
1488c973ee2SSimon J. Gerraty
1498c973ee2SSimon J. Gerratyappend_stage_2:
1508c973ee2SSimon J. Gerraty	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
1518c973ee2SSimon J. Gerraty	@${MAKE} -Dbefore-2 -f ${MAKEFILE} append_stage_3 VAR2=value -Dafter-2
1528c973ee2SSimon J. Gerraty
1538c973ee2SSimon J. Gerratyappend_stage_3:
1548c973ee2SSimon J. Gerraty	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
1558c973ee2SSimon J. Gerraty
1568c973ee2SSimon J. Gerraty
1578c973ee2SSimon J. Gerraty# Demonstrates the implementation details of 'MAKEFLAGS', in particular that
1588c973ee2SSimon J. Gerraty# it is an environment variable rather than a global variable.
1598c973ee2SSimon J. Gerratyoverride_stage_0:
1608c973ee2SSimon J. Gerraty	@${MAKE} -f ${MAKEFILE} STAGE=1 VAR=value override_stage_1
1618c973ee2SSimon J. Gerraty
1628c973ee2SSimon J. Gerraty.if make(override_stage_1)
1638c973ee2SSimon J. Gerraty# While parsing the makefiles, 'MAKEFLAGS' is the value of the environment
1648c973ee2SSimon J. Gerraty# variable, in this case provided by stage 0.
1658c973ee2SSimon J. Gerraty.  if ${MAKEFLAGS:M*} != "-r -k"
1668c973ee2SSimon J. Gerraty.    error
1678c973ee2SSimon J. Gerraty.  endif
1688c973ee2SSimon J. GerratyMAKEFLAGS=	overridden	# temporarily override it
1698c973ee2SSimon J. Gerraty.  if ${MAKEFLAGS} != "overridden"
1708c973ee2SSimon J. Gerraty.    error
1718c973ee2SSimon J. Gerraty.  endif
1728c973ee2SSimon J. Gerraty.undef MAKEFLAGS		# make the environment variable visible again
1738c973ee2SSimon J. Gerraty.  if ${MAKEFLAGS:M*} != "-r -k"
1748c973ee2SSimon J. Gerraty.    error
1758c973ee2SSimon J. Gerraty.  endif
1768c973ee2SSimon J. Gerraty.endif
1778c973ee2SSimon J. Gerratyoverride_stage_1:
1788c973ee2SSimon J. Gerraty	@echo '$@: run MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
1798c973ee2SSimon J. Gerraty	@${MAKE} -f ${MAKEFILE} STAGE=2 override_stage_2
1808c973ee2SSimon J. Gerraty
1818c973ee2SSimon J. Gerratyoverride_stage_2:
1828c973ee2SSimon J. Gerraty	@echo '$@: STAGE=<${STAGE}> VAR=<${VAR}>'
183