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