Home | History | Annotate | Line # | Download | only in unit-tests
varname-dot-makeflags.mk revision 1.5
      1 # $NetBSD: varname-dot-makeflags.mk,v 1.5 2023/02/25 11:11:16 rillig Exp $
      2 #
      3 # Tests for the special .MAKEFLAGS variable, which collects almost all
      4 # command line arguments and passes them on to any child processes via
      5 # the environment variable MAKEFLAGS (without leading '.').
      6 #
      7 # See also:
      8 #	varname-dot-makeoverrides.mk
      9 
     10 all: spaces_stage_0 dollars_stage_0 append_stage_0 override_stage_0
     11 
     12 
     13 # When options are parsed, the option and its argument are appended as
     14 # separate words to .MAKEFLAGS.  Special characters in the option argument
     15 # are not quoted though.  It seems to have not been necessary since at least
     16 # 1993.
     17 spaces_stage_0:
     18 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
     19 	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
     20 	@${MAKE} -f ${MAKEFILE} spaces_stage_1 -d00000 -D"VARNAME WITH SPACES"
     21 
     22 # At this point, the 'VARNAME WITH SPACES' is no longer recognizable as a
     23 # single command line argument.  In practice, variable names don't contain
     24 # spaces.
     25 spaces_stage_1:
     26 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
     27 	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
     28 
     29 
     30 # Demonstrate that '$' characters are altered when they are passed on to child
     31 # make processes via MAKEFLAGS.
     32 dollars_stage_0:
     33 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
     34 
     35 	# The '$$$$' becomes a literal '$$' when building the '${MAKE}'
     36 	# command line, making the actual argument 'DOLLARS=$${varname}'.
     37 	# At this stage, MAKEFLAGS is not yet involved.
     38 	@${MAKE} -f ${MAKEFILE} dollars_stage_1 DOLLARS='$$$${varname}'
     39 
     40 .if make(dollars_stage_1)
     41 # At this point, the variable 'DOLLARS' contains '$${varname}', which
     42 # evaluates to a literal '$' followed by '{varname}'.
     43 .  if ${DOLLARS} != "\${varname}"
     44 .    error
     45 .  endif
     46 .endif
     47 dollars_stage_1:
     48 	# At this point, the stage 1 make provides the environment variable
     49 	# 'MAKEFLAGS' to its child processes, even if the child process is not
     50 	# another make.
     51 	#
     52 	# expect: dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}>
     53 	#
     54 	# The 'DOLLARS=\$\{varname\}' assignment is escaped so that the stage
     55 	# 2 make will see it as a single word.
     56 	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
     57 
     58 	# At this point, evaluating the environment variable 'MAKEFLAGS' leads
     59 	# to strange side effects as the string '\$\{varname\}' is interpreted
     60 	# as:
     61 	#
     62 	#	\		a literal string of a single backslash
     63 	#	$\		the value of the variable named '\'
     64 	#	{varname\}	a literal string
     65 	#
     66 	# Since the variable name '\' is not defined, the resulting value is
     67 	# '\{varname\}'.  Make doesn't handle isolated '$' characters in
     68 	# strings well, instead each '$' has to be part of a '$$' or be part
     69 	# of a subexpression like '${VAR}'.
     70 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
     71 
     72 	# The modifier ':q' preserves a '$$' in an expression value instead of
     73 	# expanding it to a single '$', but it's already too late, as that
     74 	# modifier applies after the expression has been evaluated.  Except
     75 	# for debug logging, there is no way to process strings that contain
     76 	# isolated '$'.
     77 	@echo '$@: MAKEFLAGS:q=<'${MAKEFLAGS:q}'>'
     78 
     79 	@${MAKE} -f ${MAKEFILE} dollars_stage_2
     80 
     81 .if make(dollars_stage_2)
     82 # At this point, the variable 'DOLLARS' contains '${varname}', and since
     83 # 'varname' is undefined, that expression evaluates to an empty string.
     84 .  if ${DOLLARS} != ""
     85 .    error
     86 .  endif
     87 varname=	varvalue
     88 .  if ${DOLLARS} != "varvalue"
     89 .    error
     90 .  endif
     91 .  undef varname
     92 .endif
     93 dollars_stage_2:
     94 	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
     95 	@echo '$@: dollars=<'${DOLLARS:Q}'>'
     96 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
     97 	@${MAKE} -f ${MAKEFILE} dollars_stage_3
     98 
     99 dollars_stage_3:
    100 	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
    101 	@echo '$@: dollars=<'${DOLLARS:Uundefined:Q}'>'
    102 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    103 
    104 
    105 # Demonstrates in which exact order the MAKEFLAGS are built together from the
    106 # parent MAKEFLAGS and the flags from the command line, in particular that
    107 # variable assignments are passed at the end, after the options.
    108 append_stage_0:
    109 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    110 	@${MAKE} -Dbefore-0 -f ${MAKEFILE} append_stage_1 VAR0=value -Dafter-0
    111 
    112 append_stage_1:
    113 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    114 	@${MAKE} -Dbefore-1 -f ${MAKEFILE} append_stage_2 VAR1=value -Dafter-1
    115 
    116 append_stage_2:
    117 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    118 	@${MAKE} -Dbefore-2 -f ${MAKEFILE} append_stage_3 VAR2=value -Dafter-2
    119 
    120 append_stage_3:
    121 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    122 
    123 
    124 # Demonstrates the implementation details of 'MAKEFLAGS', in particular that
    125 # it is an environment variable rather than a global variable.
    126 override_stage_0:
    127 	@${MAKE} -f ${MAKEFILE} STAGE=1 VAR=value override_stage_1
    128 
    129 .if make(override_stage_1)
    130 # While parsing the makefiles, 'MAKEFLAGS' is the value of the environment
    131 # variable, in this case provided by stage 0.
    132 .  if ${MAKEFLAGS:M*} != "-r -k"
    133 .    error
    134 .  endif
    135 MAKEFLAGS=	overridden	# temporarily override it
    136 .  if ${MAKEFLAGS} != "overridden"
    137 .    error
    138 .  endif
    139 .undef MAKEFLAGS		# make the environment variable visible again
    140 .  if ${MAKEFLAGS:M*} != "-r -k"
    141 .    error
    142 .  endif
    143 .endif
    144 override_stage_1:
    145 	@echo '$@: run MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    146 	@${MAKE} -f ${MAKEFILE} STAGE=2 override_stage_2
    147 
    148 override_stage_2:
    149 	@echo '$@: STAGE=<${STAGE}> VAR=<${VAR}>'
    150