Home | History | Annotate | Line # | Download | only in unit-tests
      1  1.8  rillig # $NetBSD: varname-makeflags.mk,v 1.8 2023/06/01 07:27:30 rillig Exp $
      2  1.1  rillig #
      3  1.7  rillig # Tests for the environment variable 'MAKEFLAGS', from which additional
      4  1.7  rillig # command line arguments are read before the actual command line arguments.
      5  1.7  rillig #
      6  1.7  rillig # After reading the makefiles and before making the targets, the arguments
      7  1.7  rillig # that were collected in '.MAKEFLAGS' and '.MAKEOVERRIDES' are written back to
      8  1.7  rillig # the environment variable 'MAKEFLAGS'.
      9  1.1  rillig 
     10  1.6  rillig all: spaces_stage_0 dollars_stage_0 append_stage_0 override_stage_0
     11  1.1  rillig 
     12  1.6  rillig 
     13  1.6  rillig .if !make(*stage*)
     14  1.3  rillig 
     15  1.3  rillig # The unit tests are run with an almost empty environment.  In particular,
     16  1.7  rillig # the variable MAKEFLAGS is not set.
     17  1.6  rillig .  if ${MAKEFLAGS:Uundefined} != "undefined"
     18  1.6  rillig .    error
     19  1.6  rillig .  endif
     20  1.3  rillig 
     21  1.3  rillig # The special variable .MAKEFLAGS is influenced though.
     22  1.3  rillig # See varname-dot-makeflags.mk for more details.
     23  1.6  rillig .  if ${.MAKEFLAGS} != " -r -k"
     24  1.6  rillig .    error
     25  1.6  rillig .  endif
     26  1.3  rillig 
     27  1.4  rillig 
     28  1.4  rillig # In POSIX mode, the environment variable MAKEFLAGS can contain letters only,
     29  1.4  rillig # for compatibility.  These letters are exploded to form regular options.
     30  1.4  rillig OUTPUT!=	env MAKEFLAGS=ikrs ${MAKE} -f /dev/null -v .MAKEFLAGS
     31  1.6  rillig .  if ${OUTPUT} != " -i -k -r -s -V .MAKEFLAGS"
     32  1.6  rillig .    error
     33  1.6  rillig .  endif
     34  1.4  rillig 
     35  1.4  rillig # As soon as there is a single non-alphabetic character in the environment
     36  1.4  rillig # variable MAKEFLAGS, it is no longer split.  In this example, the word
     37  1.4  rillig # "d0ikrs" is treated as a target, but the option '-v' prevents any targets
     38  1.4  rillig # from being built.
     39  1.5     sjg OUTPUT!=	env MAKEFLAGS=d0ikrs ${MAKE} -r -f /dev/null -v .MAKEFLAGS
     40  1.6  rillig .  if ${OUTPUT} != " -r -V .MAKEFLAGS"
     41  1.6  rillig .    error ${OUTPUT}
     42  1.6  rillig .  endif
     43  1.6  rillig 
     44  1.4  rillig .endif
     45  1.4  rillig 
     46  1.4  rillig 
     47  1.6  rillig # When options are parsed, the option and its argument are appended as
     48  1.6  rillig # separate words to the MAKEFLAGS for the child processes.  Special characters
     49  1.6  rillig # in the option arguments are not quoted though.
     50  1.6  rillig spaces_stage_0:
     51  1.6  rillig 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
     52  1.6  rillig 	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
     53  1.6  rillig 	@${MAKE} -f ${MAKEFILE} spaces_stage_1 -d00000 -D"VARNAME WITH SPACES"
     54  1.6  rillig 
     55  1.6  rillig # At this point, the 'VARNAME WITH SPACES' is no longer recognizable as a
     56  1.6  rillig # single command line argument.  In practice, variable names don't contain
     57  1.6  rillig # spaces.
     58  1.6  rillig spaces_stage_1:
     59  1.6  rillig 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
     60  1.6  rillig 	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
     61  1.6  rillig 
     62  1.6  rillig 
     63  1.6  rillig # Demonstrate that '$' characters are altered when they are passed on to child
     64  1.6  rillig # make processes via MAKEFLAGS.
     65  1.6  rillig dollars_stage_0:
     66  1.6  rillig 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
     67  1.6  rillig 
     68  1.6  rillig 	# The '$$$$' becomes a literal '$$' when building the '${MAKE}'
     69  1.6  rillig 	# command line, making the actual argument 'DOLLARS=$${varname}'.
     70  1.6  rillig 	# At this stage, MAKEFLAGS is not yet involved.
     71  1.6  rillig 	@${MAKE} -f ${MAKEFILE} dollars_stage_1 DOLLARS='$$$${varname}'
     72  1.6  rillig 
     73  1.6  rillig .if make(dollars_stage_1)
     74  1.6  rillig # At this point, the variable 'DOLLARS' contains '$${varname}', which
     75  1.6  rillig # evaluates to a literal '$' followed by '{varname}'.
     76  1.6  rillig .  if ${DOLLARS} != "\${varname}"
     77  1.6  rillig .    error
     78  1.6  rillig .  endif
     79  1.6  rillig .endif
     80  1.6  rillig dollars_stage_1:
     81  1.6  rillig 	# At this point, the stage 1 make provides the environment variable
     82  1.6  rillig 	# 'MAKEFLAGS' to its child processes, even if the child process is not
     83  1.6  rillig 	# another make.
     84  1.6  rillig 	#
     85  1.6  rillig 	# expect: dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}>
     86  1.6  rillig 	#
     87  1.6  rillig 	# The 'DOLLARS=\$\{varname\}' assignment is escaped so that the stage
     88  1.6  rillig 	# 2 make will see it as a single word.
     89  1.6  rillig 	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
     90  1.6  rillig 
     91  1.6  rillig 	# At this point, evaluating the environment variable 'MAKEFLAGS' leads
     92  1.6  rillig 	# to strange side effects as the string '\$\{varname\}' is interpreted
     93  1.6  rillig 	# as:
     94  1.6  rillig 	#
     95  1.6  rillig 	#	\		a literal string of a single backslash
     96  1.6  rillig 	#	$\		the value of the variable named '\'
     97  1.6  rillig 	#	{varname\}	a literal string
     98  1.6  rillig 	#
     99  1.8  rillig 	# Since the variable named '\' is not defined, the resulting value is
    100  1.6  rillig 	# '\{varname\}'.  Make doesn't handle isolated '$' characters in
    101  1.6  rillig 	# strings well, instead each '$' has to be part of a '$$' or be part
    102  1.6  rillig 	# of a subexpression like '${VAR}'.
    103  1.6  rillig 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    104  1.6  rillig 
    105  1.6  rillig 	# The modifier ':q' preserves a '$$' in an expression value instead of
    106  1.6  rillig 	# expanding it to a single '$', but it's already too late, as that
    107  1.6  rillig 	# modifier applies after the expression has been evaluated.  Except
    108  1.6  rillig 	# for debug logging, there is no way to process strings that contain
    109  1.6  rillig 	# isolated '$'.
    110  1.6  rillig 	@echo '$@: MAKEFLAGS:q=<'${MAKEFLAGS:q}'>'
    111  1.6  rillig 
    112  1.6  rillig 	@${MAKE} -f ${MAKEFILE} dollars_stage_2
    113  1.6  rillig 
    114  1.6  rillig .if make(dollars_stage_2)
    115  1.6  rillig # At this point, the variable 'DOLLARS' contains '${varname}', and since
    116  1.6  rillig # 'varname' is undefined, that expression evaluates to an empty string.
    117  1.6  rillig .  if ${DOLLARS} != ""
    118  1.6  rillig .    error
    119  1.6  rillig .  endif
    120  1.6  rillig varname=	varvalue
    121  1.6  rillig .  if ${DOLLARS} != "varvalue"
    122  1.6  rillig .    error
    123  1.6  rillig .  endif
    124  1.6  rillig .  undef varname
    125  1.6  rillig .endif
    126  1.6  rillig dollars_stage_2:
    127  1.6  rillig 	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
    128  1.6  rillig 	@echo '$@: dollars=<'${DOLLARS:Q}'>'
    129  1.6  rillig 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    130  1.6  rillig 	@${MAKE} -f ${MAKEFILE} dollars_stage_3
    131  1.6  rillig 
    132  1.6  rillig dollars_stage_3:
    133  1.6  rillig 	@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
    134  1.6  rillig 	@echo '$@: dollars=<'${DOLLARS:Uundefined:Q}'>'
    135  1.6  rillig 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    136  1.6  rillig 
    137  1.6  rillig 
    138  1.8  rillig # Demonstrates in which exact order the MAKEFLAGS are built from the parent
    139  1.8  rillig # MAKEFLAGS and the flags from the command line, in particular that variable
    140  1.8  rillig # assignments are passed at the end, after the options.
    141  1.6  rillig append_stage_0:
    142  1.6  rillig 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    143  1.6  rillig 	@${MAKE} -Dbefore-0 -f ${MAKEFILE} append_stage_1 VAR0=value -Dafter-0
    144  1.6  rillig 
    145  1.6  rillig append_stage_1:
    146  1.6  rillig 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    147  1.6  rillig 	@${MAKE} -Dbefore-1 -f ${MAKEFILE} append_stage_2 VAR1=value -Dafter-1
    148  1.6  rillig 
    149  1.6  rillig append_stage_2:
    150  1.6  rillig 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    151  1.6  rillig 	@${MAKE} -Dbefore-2 -f ${MAKEFILE} append_stage_3 VAR2=value -Dafter-2
    152  1.6  rillig 
    153  1.6  rillig append_stage_3:
    154  1.6  rillig 	@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    155  1.6  rillig 
    156  1.6  rillig 
    157  1.6  rillig # Demonstrates the implementation details of 'MAKEFLAGS', in particular that
    158  1.6  rillig # it is an environment variable rather than a global variable.
    159  1.6  rillig override_stage_0:
    160  1.6  rillig 	@${MAKE} -f ${MAKEFILE} STAGE=1 VAR=value override_stage_1
    161  1.6  rillig 
    162  1.6  rillig .if make(override_stage_1)
    163  1.6  rillig # While parsing the makefiles, 'MAKEFLAGS' is the value of the environment
    164  1.6  rillig # variable, in this case provided by stage 0.
    165  1.6  rillig .  if ${MAKEFLAGS:M*} != "-r -k"
    166  1.6  rillig .    error
    167  1.6  rillig .  endif
    168  1.6  rillig MAKEFLAGS=	overridden	# temporarily override it
    169  1.6  rillig .  if ${MAKEFLAGS} != "overridden"
    170  1.6  rillig .    error
    171  1.6  rillig .  endif
    172  1.6  rillig .undef MAKEFLAGS		# make the environment variable visible again
    173  1.6  rillig .  if ${MAKEFLAGS:M*} != "-r -k"
    174  1.6  rillig .    error
    175  1.6  rillig .  endif
    176  1.6  rillig .endif
    177  1.6  rillig override_stage_1:
    178  1.6  rillig 	@echo '$@: run MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
    179  1.6  rillig 	@${MAKE} -f ${MAKEFILE} STAGE=2 override_stage_2
    180  1.6  rillig 
    181  1.6  rillig override_stage_2:
    182  1.6  rillig 	@echo '$@: STAGE=<${STAGE}> VAR=<${VAR}>'
    183