diff options
Diffstat (limited to 'usr.bin/make/unit-tests')
73 files changed, 2530 insertions, 0 deletions
diff --git a/usr.bin/make/unit-tests/Makefile b/usr.bin/make/unit-tests/Makefile new file mode 100644 index 0000000..07aaceb --- /dev/null +++ b/usr.bin/make/unit-tests/Makefile @@ -0,0 +1,139 @@ +# $NetBSD: Makefile,v 1.53 2018/05/24 00:25:44 christos Exp $ +# +# Unit tests for make(1) +# The main targets are: +# +# all: run all the tests +# test: run 'all', and compare to expected results +# accept: move generated output to expected results +# +# Adding a test case. +# Each feature should get its own set of tests in its own suitably +# named makefile (*.mk), with its own set of expected results (*.exp), +# and it should be added to the TESTNAMES list. +# + +.MAIN: all + +UNIT_TESTS:= ${.PARSEDIR} +.PATH: ${UNIT_TESTS} + +# Each test is in a sub-makefile. +# Keep the list sorted. +TESTNAMES= \ + comment \ + cond1 \ + cond2 \ + error \ + export \ + export-all \ + export-env \ + doterror \ + dotwait \ + forloop \ + forsubst \ + hash \ + misc \ + moderrs \ + modmatch \ + modmisc \ + modorder \ + modts \ + modword \ + order \ + posix \ + qequals \ + sunshcmd \ + sysv \ + ternary \ + unexport \ + unexport-env \ + varcmd \ + varmisc \ + varquote \ + varshell + +# these tests were broken by referting POSIX chanegs +STRICT_POSIX_TESTS = \ + escape \ + impsrc \ + phony-end \ + posix1 \ + suffixes + +# Override make flags for certain tests +flags.doterror= +flags.order=-j1 + +OUTFILES= ${TESTNAMES:S/$/.out/} + +all: ${OUTFILES} + +CLEANFILES += *.rawout *.out *.status *.tmp *.core *.tmp +CLEANFILES += obj*.[och] lib*.a # posix1.mk +CLEANFILES += issue* .[ab]* # suffixes.mk +CLEANRECURSIVE += dir dummy # posix1.mk + +clean: + rm -f ${CLEANFILES} +.if !empty(CLEANRECURSIVE) + rm -rf ${CLEANRECURSIVE} +.endif + +TEST_MAKE?= ${.MAKE} +TOOL_SED?= sed + +# ensure consistent results from sort(1) +LC_ALL= C +LANG= C +.export LANG LC_ALL + +# the tests are actually done with sub-makes. +.SUFFIXES: .mk .rawout .out +.mk.rawout: + @echo ${TEST_MAKE} ${flags.${.TARGET:R}:U-k} -f ${.IMPSRC} + -@cd ${.OBJDIR} && \ + { ${TEST_MAKE} ${flags.${.TARGET:R}:U-k} -f ${.IMPSRC} \ + 2>&1 ; echo $$? >${.TARGET:R}.status ; } > ${.TARGET}.tmp + @mv ${.TARGET}.tmp ${.TARGET} + +# We always pretend .MAKE was called 'make' +# and strip ${.CURDIR}/ from the output +# and replace anything after 'stopped in' with unit-tests +# so the results can be compared. +.rawout.out: + @echo postprocess ${.TARGET} + @${TOOL_SED} -e 's,^${TEST_MAKE:T:C/\./\\\./g}[][0-9]*:,make:,' \ + -e 's,${TEST_MAKE:C/\./\\\./g},make,' \ + -e '/stopped/s, /.*, unit-tests,' \ + -e 's,${.CURDIR:C/\./\\\./g}/,,g' \ + -e 's,${UNIT_TESTS:C/\./\\\./g}/,,g' \ + < ${.IMPSRC} > ${.TARGET}.tmp + @echo "exit status `cat ${.TARGET:R}.status`" >> ${.TARGET}.tmp + @mv ${.TARGET}.tmp ${.TARGET} + +# Compare all output files +test: ${OUTFILES} .PHONY + @failed= ; \ + for test in ${TESTNAMES}; do \ + diff -u ${UNIT_TESTS}/$${test}.exp $${test}.out \ + || failed="$${failed}$${failed:+ }$${test}" ; \ + done ; \ + if [ -n "$${failed}" ]; then \ + echo "Failed tests: $${failed}" ; false ; \ + else \ + echo "All tests passed" ; \ + fi + +accept: + @for test in ${TESTNAMES}; do \ + cmp -s ${UNIT_TESTS}/$${test}.exp $${test}.out \ + || { echo "Replacing $${test}.exp" ; \ + cp $${test}.out ${UNIT_TESTS}/$${test}.exp ; } \ + done + +.if exists(${TEST_MAKE}) +${TESTNAMES:S/$/.rawout/}: ${TEST_MAKE} +.endif + +.-include <bsd.obj.mk> diff --git a/usr.bin/make/unit-tests/comment.exp b/usr.bin/make/unit-tests/comment.exp new file mode 100644 index 0000000..9a97df0 --- /dev/null +++ b/usr.bin/make/unit-tests/comment.exp @@ -0,0 +1,5 @@ +comment testing start +this is foo +This is how a comment looks: # comment +comment testing done +exit status 0 diff --git a/usr.bin/make/unit-tests/comment.mk b/usr.bin/make/unit-tests/comment.mk new file mode 100644 index 0000000..7dd7dbb --- /dev/null +++ b/usr.bin/make/unit-tests/comment.mk @@ -0,0 +1,31 @@ +# This is a comment +.if ${MACHINE_ARCH} == something +FOO=bar +.endif + +#\ + Multiline comment + +BAR=# defined +FOOBAR= # defined + +# This is an escaped comment \ +that keeps going until the end of this line + +# Another escaped comment \ +that \ +goes \ +on + +# This is NOT an escaped comment due to the double backslashes \\ +all: hi foo bar + @echo comment testing done + +hi: + @echo comment testing start + +foo: + @echo this is $@ + +bar: + @echo This is how a comment looks: '# comment' diff --git a/usr.bin/make/unit-tests/cond1.exp b/usr.bin/make/unit-tests/cond1.exp new file mode 100644 index 0000000..701d504 --- /dev/null +++ b/usr.bin/make/unit-tests/cond1.exp @@ -0,0 +1,23 @@ +make: "cond1.mk" line 75: warning: extra else +make: "cond1.mk" line 85: warning: extra else +2 is prime +A='other' B='unknown' C='clever' o='no,no' +Passed: + var + ("var") + (var != var) + var != var + !((var != var) && defined(name)) + var == quoted + +1 is not prime +2 is prime +3 is prime +4 is not prime +5 is prime + +make: warning: String comparison operator should be either == or != +make: Bad conditional expression `"0" > 0' in "0" > 0?OK:No + +OK +exit status 0 diff --git a/usr.bin/make/unit-tests/cond1.mk b/usr.bin/make/unit-tests/cond1.mk new file mode 100644 index 0000000..e361832 --- /dev/null +++ b/usr.bin/make/unit-tests/cond1.mk @@ -0,0 +1,109 @@ +# $Id: cond1.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +# hard code these! +TEST_UNAME_S= NetBSD +TEST_UNAME_M= sparc +TEST_MACHINE= i386 + +.if ${TEST_UNAME_S} +Ok=var, +.endif +.if ("${TEST_UNAME_S}") +Ok+=(\"var\"), +.endif +.if (${TEST_UNAME_M} != ${TEST_MACHINE}) +Ok+=(var != var), +.endif +.if ${TEST_UNAME_M} != ${TEST_MACHINE} +Ok+= var != var, +.endif +.if !((${TEST_UNAME_M} != ${TEST_MACHINE}) && defined(X)) +Ok+= !((var != var) && defined(name)), +.endif +# from bsd.obj.mk +MKOBJ?=no +.if ${MKOBJ} == "no" +o= no +Ok+= var == "quoted", +.else +.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR) +.if defined(notMAKEOBJDIRPREFIX) +o=${MAKEOBJDIRPREFIX}${__curdir} +.else +o= ${MAKEOBJDIR} +.endif +.endif +o= o +.endif + +# repeat the above to check we get the same result +.if ${MKOBJ} == "no" +o2= no +.else +.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR) +.if defined(notMAKEOBJDIRPREFIX) +o2=${MAKEOBJDIRPREFIX}${__curdir} +.else +o2= ${MAKEOBJDIR} +.endif +.endif +o2= o +.endif + +PRIMES=2 3 5 7 11 +NUMBERS=1 2 3 4 5 + +n=2 +.if ${PRIMES:M$n} == "" +X=not +.else +X= +.endif + +.if ${MACHINE_ARCH} == no-such +A=one +.else +.if ${MACHINE_ARCH} == not-this +.if ${MACHINE_ARCH} == something-else +A=unlikely +.else +A=no +.endif +.endif +A=other +# We expect an extra else warning - we're not skipping here +.else +A=this should be an error +.endif + +.if $X != "" +.if $X == not +B=one +.else +B=other +# We expect an extra else warning - we are skipping here +.else +B=this should be an error +.endif +.else +B=unknown +.endif + +.if "quoted" == quoted +C=clever +.else +C=dim +.endif + +.if defined(nosuch) && ${nosuch:Mx} != "" +# this should not happen +.info nosuch is x +.endif + +all: + @echo "$n is $X prime" + @echo "A='$A' B='$B' C='$C' o='$o,${o2}'" + @echo "Passed:${.newline} ${Ok:S/,/${.newline}/}" + @echo "${NUMBERS:@n@$n is ${("${PRIMES:M$n}" == ""):?not:} prime${.newline}@}" + @echo "${"${DoNotQuoteHere:U0}" > 0:?OK:No}" + @echo "${${NoSuchNumber:U42} > 0:?OK:No}" diff --git a/usr.bin/make/unit-tests/cond2.exp b/usr.bin/make/unit-tests/cond2.exp new file mode 100644 index 0000000..22e76a5 --- /dev/null +++ b/usr.bin/make/unit-tests/cond2.exp @@ -0,0 +1,7 @@ +make: Bad conditional expression ` == "empty"' in == "empty"?oops:ok +make: "cond2.mk" line 13: Malformed conditional ({TEST_TYPO} == "Ok") +TEST_NOT_SET is empty or not defined +make: "cond2.mk" line 20: Malformed conditional (${TEST_NOT_SET} == "empty") +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/usr.bin/make/unit-tests/cond2.mk b/usr.bin/make/unit-tests/cond2.mk new file mode 100644 index 0000000..aeb5a8c --- /dev/null +++ b/usr.bin/make/unit-tests/cond2.mk @@ -0,0 +1,29 @@ +# $Id: cond2.mk,v 1.2 2015/12/02 00:28:24 sjg Exp $ + +TEST_UNAME_S= NetBSD + +# this should be ok +X:= ${${TEST_UNAME_S} == "NetBSD":?Ok:fail} +.if $X == "Ok" +Y= good +.endif +# expect: Bad conditional expression ` == "empty"' in == "empty"?oops:ok +X:= ${${TEST_NOT_SET} == "empty":?oops:ok} +# expect: Malformed conditional ({TEST_TYPO} == "Ok") +.if {TEST_TYPO} == "Ok" +Y= oops +.endif +.if empty(TEST_NOT_SET) +Y!= echo TEST_NOT_SET is empty or not defined >&2; echo +.endif +# expect: Malformed conditional (${TEST_NOT_SET} == "empty") +.if ${TEST_NOT_SET} == "empty" +Y= oops +.endif + +.if defined(.NDEF) && ${.NDEF} > 0 +Z= yes +.endif + +all: + @echo $@ diff --git a/usr.bin/make/unit-tests/doterror.exp b/usr.bin/make/unit-tests/doterror.exp new file mode 100644 index 0000000..5655644 --- /dev/null +++ b/usr.bin/make/unit-tests/doterror.exp @@ -0,0 +1,9 @@ +At first, I am +happy +and now: sad +*** Error code 1 + +Stop. +make: stopped in unit-tests +.ERROR: Looks like 'sad' is upset. +exit status 1 diff --git a/usr.bin/make/unit-tests/doterror.mk b/usr.bin/make/unit-tests/doterror.mk new file mode 100644 index 0000000..7f1c78f --- /dev/null +++ b/usr.bin/make/unit-tests/doterror.mk @@ -0,0 +1,20 @@ +# $Id: doterror.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + + +.BEGIN: + @echo At first, I am + +.END: + @echo not reached + +.ERROR: + @echo "$@: Looks like '${.ERROR_TARGET}' is upset." + +all: happy sad + +happy: + @echo $@ + +sad: + @echo and now: $@; exit 1 + diff --git a/usr.bin/make/unit-tests/dotwait.exp b/usr.bin/make/unit-tests/dotwait.exp new file mode 100644 index 0000000..bdc0a0e --- /dev/null +++ b/usr.bin/make/unit-tests/dotwait.exp @@ -0,0 +1,30 @@ +simple.1 +simple.1 +simple.2 +simple.2 +recursive.1.1.* +recursive.1.1.* +recursive.1.1.* +recursive.1.1.* +recursive.1.99 +recursive.1.99 +recursive.2.1.* +recursive.2.1.* +recursive.2.1.* +recursive.2.1.* +recursive.2.99 +recursive.2.99 +shared.0 +shared.0 +shared.1.99 +shared.1.99 +shared.2.1 +shared.2.1 +shared.2.99 +shared.2.99 +cycle.1.99 +cycle.1.99 +make: Graph cycles through `cycle.2.99' +make: Graph cycles through `cycle.2.98' +make: Graph cycles through `cycle.2.97' +exit status 0 diff --git a/usr.bin/make/unit-tests/dotwait.mk b/usr.bin/make/unit-tests/dotwait.mk new file mode 100644 index 0000000..bab5993 --- /dev/null +++ b/usr.bin/make/unit-tests/dotwait.mk @@ -0,0 +1,61 @@ +# $NetBSD: dotwait.mk,v 1.2 2017/10/08 20:44:19 sjg Exp $ + +THISMAKEFILE:= ${.PARSEDIR}/${.PARSEFILE} + +TESTS= simple recursive shared cycle +PAUSE= sleep 1 + +# Use a .for loop rather than dependencies here, to ensure +# that the tests are run one by one, with parallelism +# only within tests. +# Ignore "--- target ---" lines printed by parallel make. +all: +.for t in ${TESTS} + @${.MAKE} -f ${THISMAKEFILE} -j4 $t 2>&1 | grep -v "^--- " +.endfor + +# +# Within each test, the names of the sub-targets follow these +# conventions: +# * If it's expected that two or more targets may be made in parallel, +# then the target names will differ only in an alphabetic component +# such as ".a" or ".b". +# * If it's expected that two or more targets should be made in sequence +# then the target names will differ in numeric components, such that +# lexical ordering of the target names matches the expected order +# in which the targets should be made. +# +# Targets may echo ${PARALLEL_TARG} to print a modified version +# of their own name, in which alphabetic components like ".a" or ".b" +# are converted to ".*". Two targets that are expected to +# be made in parallel will thus print the same strings, so that the +# output is independent of the order in which these targets are made. +# +PARALLEL_TARG= ${.TARGET:C/\.[a-z]/.*/g:Q} +.DEFAULT: + @echo ${PARALLEL_TARG}; ${PAUSE}; echo ${PARALLEL_TARG} +_ECHOUSE: .USE + @echo ${PARALLEL_TARG}; ${PAUSE}; echo ${PARALLEL_TARG} + +# simple: no recursion, no cycles +simple: simple.1 .WAIT simple.2 + +# recursive: all children of the left hand side of the .WAIT +# must be made before any child of the right hand side. +recursive: recursive.1.99 .WAIT recursive.2.99 +recursive.1.99: recursive.1.1.a recursive.1.1.b _ECHOUSE +recursive.2.99: recursive.2.1.a recursive.2.1.b _ECHOUSE + +# shared: both shared.1.99 and shared.2.99 depend on shared.0. +# shared.0 must be made first, even though it is a child of +# the right hand side of the .WAIT. +shared: shared.1.99 .WAIT shared.2.99 +shared.1.99: shared.0 _ECHOUSE +shared.2.99: shared.2.1 shared.0 _ECHOUSE + +# cycle: the cyclic dependency must not cause infinite recursion +# leading to stack overflow and a crash. +cycle: cycle.1.99 .WAIT cycle.2.99 +cycle.2.99: cycle.2.98 _ECHOUSE +cycle.2.98: cycle.2.97 _ECHOUSE +cycle.2.97: cycle.2.99 _ECHOUSE diff --git a/usr.bin/make/unit-tests/error.exp b/usr.bin/make/unit-tests/error.exp new file mode 100644 index 0000000..a2bf71b --- /dev/null +++ b/usr.bin/make/unit-tests/error.exp @@ -0,0 +1,4 @@ +make: "error.mk" line 3: just FYI +make: "error.mk" line 4: warning: this could be serious +make: "error.mk" line 5: this is fatal +exit status 1 diff --git a/usr.bin/make/unit-tests/error.mk b/usr.bin/make/unit-tests/error.mk new file mode 100644 index 0000000..721ed50 --- /dev/null +++ b/usr.bin/make/unit-tests/error.mk @@ -0,0 +1,10 @@ +# $Id: error.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +.info just FYI +.warning this could be serious +.error this is fatal + +all: + +.info.html: + @echo this should be ignored diff --git a/usr.bin/make/unit-tests/escape.exp b/usr.bin/make/unit-tests/escape.exp new file mode 100644 index 0000000..6238e27 --- /dev/null +++ b/usr.bin/make/unit-tests/escape.exp @@ -0,0 +1,104 @@ +var-1bs +printf "%s=:%s:\n" VAR1BS 111\\111; printf "%s=:%s:\n" VAR1BSa 111\\aaa; printf "%s=:%s:\n" VAR1BSA 111\\aaa; printf "%s=:%s:\n" VAR1BSda 111\\\$\{a\}; printf "%s=:%s:\n" VAR1BSdA 111\\\$\{A\}; printf "%s=:%s:\n" VAR1BSc 111\#\ backslash\ escapes\ comment\ char,\ so\ this\ is\ part\ of\ the\ value; printf "%s=:%s:\n" VAR1BSsc 111\\\ ; +VAR1BS=:111\111: +VAR1BSa=:111\aaa: +VAR1BSA=:111\aaa: +VAR1BSda=:111\${a}: +VAR1BSdA=:111\${A}: +VAR1BSc=:111# backslash escapes comment char, so this is part of the value: +VAR1BSsc=:111\ : +var-2bs +printf "%s=:%s:\n" VAR2BS 222\\\\222; printf "%s=:%s:\n" VAR2BSa 222\\\\aaa; printf "%s=:%s:\n" VAR2BSA 222\\\\aaa; printf "%s=:%s:\n" VAR2BSda 222\\\\\$\{a\}; printf "%s=:%s:\n" VAR2BSdA 222\\\\\$\{A\}; printf "%s=:%s:\n" VAR2BSc 222\\\\; printf "%s=:%s:\n" VAR2BSsc 222\\\\; +VAR2BS=:222\\222: +VAR2BSa=:222\\aaa: +VAR2BSA=:222\\aaa: +VAR2BSda=:222\\${a}: +VAR2BSdA=:222\\${A}: +VAR2BSc=:222\\: +VAR2BSsc=:222\\: +var-1bsnl +printf "%s=:%s:\n" VAR1BSNL 111\ 111; printf "%s=:%s:\n" VAR1BSNLa 111\ aaa; printf "%s=:%s:\n" VAR1BSNLA 111\ aaa; printf "%s=:%s:\n" VAR1BSNLda 111\ \$\{a\}; printf "%s=:%s:\n" VAR1BSNLdA 111\ \$\{A\}; printf "%s=:%s:\n" VAR1BSNLc 111; printf "%s=:%s:\n" VAR1BSNLsc 111; +VAR1BSNL=:111 111: +VAR1BSNLa=:111 aaa: +VAR1BSNLA=:111 aaa: +VAR1BSNLda=:111 ${a}: +VAR1BSNLdA=:111 ${A}: +VAR1BSNLc=:111: +VAR1BSNLsc=:111: +var-2bsnl +printf "%s=:%s:\n" VAR2BSNL 222\\\\; printf "%s=:%s:\n" VAR2BSNLa 222\\\\; printf "%s=:%s:\n" VAR2BSNLA 222\\\\; printf "%s=:%s:\n" VAR2BSNLda 222\\\\; printf "%s=:%s:\n" VAR2BSNLdA 222\\\\; printf "%s=:%s:\n" VAR2BSNLc 222\\\\; printf "%s=:%s:\n" VAR2BSNLsc 222\\\\; +VAR2BSNL=:222\\: +VAR2BSNLa=:222\\: +VAR2BSNLA=:222\\: +VAR2BSNLda=:222\\: +VAR2BSNLdA=:222\\: +VAR2BSNLc=:222\\: +VAR2BSNLsc=:222\\: +var-3bsnl +printf "%s=:%s:\n" VAR3BSNL 333\\\\\ 333=; printf "%s=:%s:\n" VAR3BSNLa 333\\\\\ aaa=; printf "%s=:%s:\n" VAR3BSNLA 333\\\\\ aaa=; printf "%s=:%s:\n" VAR3BSNLda 333\\\\\ \$\{a\}=; printf "%s=:%s:\n" VAR3BSNLdA 333\\\\\ \$\{A\}=; printf "%s=:%s:\n" VAR3BSNLc 333\\\\; printf "%s=:%s:\n" VAR3BSNLsc 333\\\\; +VAR3BSNL=:333\\ 333=: +VAR3BSNLa=:333\\ aaa=: +VAR3BSNLA=:333\\ aaa=: +VAR3BSNLda=:333\\ ${a}=: +VAR3BSNLdA=:333\\ ${A}=: +VAR3BSNLc=:333\\: +VAR3BSNLsc=:333\\: +var-1bsnl-space +printf "%s=:%s:\n" VAR1BSNL00 first\ line; printf "%s=:%s:\n" VAR1BSNL0 first\ line\ no\ space\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLs first\ line\ one\ space\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLss first\ line\ two\ spaces\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLt first\ line\ one\ tab\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLtt first\ line\ two\ tabs\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLxx first\ line\ many\ spaces\ and\ tabs\ \[\ \ \ \ \]\ on\ second\ line; +VAR1BSNL00=:first line: +VAR1BSNL0=:first line no space on second line: +VAR1BSNLs=:first line one space on second line: +VAR1BSNLss=:first line two spaces on second line: +VAR1BSNLt=:first line one tab on second line: +VAR1BSNLtt=:first line two tabs on second line: +VAR1BSNLxx=:first line many spaces and tabs [ ] on second line: +cmd-1bsnl +echo :'first line\ +#second line without space\ +third line': +:first line\ +#second line without space\ +third line: +echo :'first line\ + second line spaces should be retained': +:first line\ + second line spaces should be retained: +echo :'first line\ +second line tab should be elided': +:first line\ +second line tab should be elided: +echo :'first line\ + only one tab should be elided, second tab remains' +:first line\ + only one tab should be elided, second tab remains +cmd-1bsnl-eof +echo :'command ending with backslash-newline'; \ + +:command ending with backslash-newline +cmd-2bsnl +echo take one\\ +take one\ +echo take two\\ +take two\ +echo take three\\ +take three\ +cmd-3bsnl +echo :'first line\\\ +#second line without space\\\ +third line': +:first line\\\ +#second line without space\\\ +third line: +echo :'first line\\\ + second line spaces should be retained': +:first line\\\ + second line spaces should be retained: +echo :'first line\\\ +second line tab should be elided': +:first line\\\ +second line tab should be elided: +echo :'first line\\\ + only one tab should be elided, second tab remains' +:first line\\\ + only one tab should be elided, second tab remains +exit status 0 diff --git a/usr.bin/make/unit-tests/escape.mk b/usr.bin/make/unit-tests/escape.mk new file mode 100644 index 0000000..829403d --- /dev/null +++ b/usr.bin/make/unit-tests/escape.mk @@ -0,0 +1,246 @@ +# $Id: escape.mk,v 1.10 2014/09/09 10:22:27 apb Exp $ +# +# Test backslash escaping. + +# Extracts from the POSIX 2008 specification +# <http://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html>: +# +# Comments start with a <number-sign> ( '#' ) and continue until an +# unescaped <newline> is reached. +# +# When an escaped <newline> (one preceded by a <backslash>) is found +# anywhere in the makefile except in a command line, an include +# line, or a line immediately preceding an include line, it shall +# be replaced, along with any leading white space on the following +# line, with a single <space>. +# +# When an escaped <newline> is found in a command line in a +# makefile, the command line shall contain the <backslash>, the +# <newline>, and the next line, except that the first character of +# the next line shall not be included if it is a <tab>. +# +# When an escaped <newline> is found in an include line or in a +# line immediately preceding an include line, the behavior is +# unspecified. +# +# Notice that the behaviour of <backslash><backslash> or +# <backslash><anything other than newline> is not mentioned. I think +# this implies that <backslash> should be taken literally everywhere +# except before <newline>. +# +# Our practice, despite what POSIX might say, is that "\#" +# in a variable assignment stores "#" as part of the value. +# The "\" is not taken literally, and the "#" does not begin a comment. +# +# Also, our practice is that an even number of backslashes before a +# newline in a variable assignment simply stores the backslashes as part +# of the value, and treats the newline as though it was not escaped. +# Similarly, ann even number of backslashes before a newline in a +# command simply uses the backslashes as part of the command test, but +# does not escape the newline. This is compatible with GNU make. + +all: .PHONY +# We will add dependencies like "all: yet-another-test" later. + +# Some variables to be expanded in tests +# +a = aaa +A = ${a} + +# Backslash at end of line in a comment\ +should continue the comment. \ +# This is also tested in comment.mk. + +__printvars: .USE .MADE + @echo ${.TARGET} + ${.ALLSRC:@v@ printf "%s=:%s:\n" ${v:Q} ${${v}:Q}; @} + +# Embedded backslash in variable should be taken literally. +# +VAR1BS = 111\111 +VAR1BSa = 111\${a} +VAR1BSA = 111\${A} +VAR1BSda = 111\$${a} +VAR1BSdA = 111\$${A} +VAR1BSc = 111\# backslash escapes comment char, so this is part of the value +VAR1BSsc = 111\ # This is a comment. Value ends with <backslash><space> + +all: var-1bs +var-1bs: .PHONY __printvars VAR1BS VAR1BSa VAR1BSA VAR1BSda VAR1BSdA \ + VAR1BSc VAR1BSsc + +# Double backslash in variable should be taken as two literal backslashes. +# +VAR2BS = 222\\222 +VAR2BSa = 222\\${a} +VAR2BSA = 222\\${A} +VAR2BSda = 222\\$${a} +VAR2BSdA = 222\\$${A} +VAR2BSc = 222\\# backslash does not escape comment char, so this is a comment +VAR2BSsc = 222\\ # This is a comment. Value ends with <backslash><backslash> + +all: var-2bs +var-2bs: .PHONY __printvars VAR2BS VAR2BSa VAR2BSA VAR2BSda VAR2BSdA \ + VAR2BSc VAR2BSsc + +# Backslash-newline in a variable setting is replaced by a single space. +# +VAR1BSNL = 111\ +111 +VAR1BSNLa = 111\ +${a} +VAR1BSNLA = 111\ +${A} +VAR1BSNLda = 111\ +$${a} +VAR1BSNLdA = 111\ +$${A} +VAR1BSNLc = 111\ +# this should be processed as a comment +VAR1BSNLsc = 111\ + # this should be processed as a comment + +all: var-1bsnl +var-1bsnl: .PHONY +var-1bsnl: .PHONY __printvars \ + VAR1BSNL VAR1BSNLa VAR1BSNLA VAR1BSNLda VAR1BSNLdA \ + VAR1BSNLc VAR1BSNLsc + +# Double-backslash-newline in a variable setting. +# Both backslashes should be taken literally, and the newline is NOT escaped. +# +# The second lines below each end with '=' so that they will not +# generate syntax errors regardless of whether or not they are +# treated as part of the value. +# +VAR2BSNL = 222\\ +222= +VAR2BSNLa = 222\\ +${a}= +VAR2BSNLA = 222\\ +${A}= +VAR2BSNLda = 222\\ +$${a}= +VAR2BSNLdA = 222\\ +$${A}= +VAR2BSNLc = 222\\ +# this should be processed as a comment +VAR2BSNLsc = 222\\ + # this should be processed as a comment + +all: var-2bsnl +var-2bsnl: .PHONY __printvars \ + VAR2BSNL VAR2BSNLa VAR2BSNLA VAR2BSNLda VAR2BSNLdA \ + VAR2BSNLc VAR2BSNLsc + +# Triple-backslash-newline in a variable setting. +# First two should be taken literally, and last should escape the newline. +# +# The second lines below each end with '=' so that they will not +# generate syntax errors regardless of whether or not they are +# treated as part of the value. +# +VAR3BSNL = 333\\\ +333= +VAR3BSNLa = 333\\\ +${a}= +VAR3BSNLA = 333\\\ +${A}= +VAR3BSNLda = 333\\\ +$${a}= +VAR3BSNLdA = 333\\\ +$${A}= +VAR3BSNLc = 333\\\ +# this should be processed as a comment +VAR3BSNLsc = 333\\\ + # this should be processed as a comment + +all: var-3bsnl +var-3bsnl: .PHONY __printvars \ + VAR3BSNL VAR3BSNLa VAR3BSNLA VAR3BSNLda VAR3BSNLdA \ + VAR3BSNLc VAR3BSNLsc + +# Backslash-newline in a variable setting, plus any amount of white space +# on the next line, is replaced by a single space. +# +VAR1BSNL00= first line\ + +# above line is entirely empty, and this is a comment +VAR1BSNL0= first line\ +no space on second line +VAR1BSNLs= first line\ + one space on second line +VAR1BSNLss= first line\ + two spaces on second line +VAR1BSNLt= first line\ + one tab on second line +VAR1BSNLtt= first line\ + two tabs on second line +VAR1BSNLxx= first line\ + many spaces and tabs [ ] on second line + +all: var-1bsnl-space +var-1bsnl-space: .PHONY __printvars \ + VAR1BSNL00 VAR1BSNL0 VAR1BSNLs VAR1BSNLss VAR1BSNLt VAR1BSNLtt \ + VAR1BSNLxx + +# Backslash-newline in a command is retained. +# +# The "#" in "# second line without space" makes it a comment instead +# of a syntax error if the preceding line is parsed incorretly. +# The ":" in "third line':" makes it look like the start of a +# target instead of a syntax error if the first line is parsed incorrectly. +# +all: cmd-1bsnl +cmd-1bsnl: .PHONY + @echo ${.TARGET} + echo :'first line\ +#second line without space\ +third line': + echo :'first line\ + second line spaces should be retained': + echo :'first line\ + second line tab should be elided': + echo :'first line\ + only one tab should be elided, second tab remains' + +# When backslash-newline appears at the end of a command script, +# both the backslash and the newline should be passed to the shell. +# The shell should elide the backslash-newline. +# +all: cmd-1bsnl-eof +cmd-1bsnl-eof: + @echo ${.TARGET} + echo :'command ending with backslash-newline'; \ + +# above line must be blank + +# Double-backslash-newline in a command. +# Both backslashes are retained, but the newline is not escaped. +# XXX: This may differ from POSIX, but matches gmake. +# +# When make passes two backslashes to the shell, the shell will pass one +# backslash to the echo commant. +# +all: cmd-2bsnl +cmd-2bsnl: .PHONY + @echo ${.TARGET} + echo take one\\ +# this should be a comment + echo take two\\ + echo take three\\ + +# Triple-backslash-newline in a command is retained. +# +all: cmd-3bsnl +cmd-3bsnl: .PHONY + @echo ${.TARGET} + echo :'first line\\\ +#second line without space\\\ +third line': + echo :'first line\\\ + second line spaces should be retained': + echo :'first line\\\ + second line tab should be elided': + echo :'first line\\\ + only one tab should be elided, second tab remains' diff --git a/usr.bin/make/unit-tests/export-all.exp b/usr.bin/make/unit-tests/export-all.exp new file mode 100644 index 0000000..e3aefd4 --- /dev/null +++ b/usr.bin/make/unit-tests/export-all.exp @@ -0,0 +1,12 @@ +UT_ALL=even this gets exported +UT_BADDIR=unit-tests +UT_DOLLAR=This is $UT_FU +UT_F=fine +UT_FOO=foobar is fubar +UT_FU=fubar +UT_NO=all +UT_OK=good +UT_OKDIR=unit-tests +UT_TEST=export-all +UT_ZOO=hoopie +exit status 0 diff --git a/usr.bin/make/unit-tests/export-all.mk b/usr.bin/make/unit-tests/export-all.mk new file mode 100644 index 0000000..576487b --- /dev/null +++ b/usr.bin/make/unit-tests/export-all.mk @@ -0,0 +1,23 @@ +# $Id: export-all.mk,v 1.2 2015/04/10 20:41:59 sjg Exp $ + +UT_OK=good +UT_F=fine + +# the old way to do :tA +M_tAbad = C,.*,cd & \&\& 'pwd',:sh +# the new +M_tA = tA + +here := ${.PARSEDIR} + +# this will cause trouble (recursing if we let it) +UT_BADDIR = ${${here}/../${here:T}:L:${M_tAbad}:T} +# this will be ok +UT_OKDIR = ${${here}/../${here:T}:L:${M_tA}:T} + +.export + +.include "export.mk" + +UT_TEST=export-all +UT_ALL=even this gets exported diff --git a/usr.bin/make/unit-tests/export-env.exp b/usr.bin/make/unit-tests/export-env.exp new file mode 100644 index 0000000..8a779e6 --- /dev/null +++ b/usr.bin/make/unit-tests/export-env.exp @@ -0,0 +1,11 @@ +make: +UT_TEST=export-env.mk +UT_ENV=not-exported +UT_EXP=not-exported +UT_LIT=literal export-env.mk +env: +UT_TEST=export-env.mk +UT_ENV=exported +UT_EXP=exported +UT_LIT=literal ${UT_TEST} +exit status 0 diff --git a/usr.bin/make/unit-tests/export-env.mk b/usr.bin/make/unit-tests/export-env.mk new file mode 100644 index 0000000..c4d3e75 --- /dev/null +++ b/usr.bin/make/unit-tests/export-env.mk @@ -0,0 +1,27 @@ +# $Id: export-env.mk,v 1.2 2016/02/18 20:25:08 sjg Exp $ + +# our normal .export, subsequent changes affect the environment +UT_TEST=this +.export UT_TEST +UT_TEST:= ${.PARSEFILE} + +# not so with .export-env +UT_ENV=exported +.export-env UT_ENV +UT_ENV=not-exported + +# gmake style export goes further; affects nothing but the environment +UT_EXP=before-export +export UT_EXP=exported +UT_EXP=not-exported + +UT_LIT= literal ${UT_TEST} +.export-literal UT_LIT + +all: + @echo make:; ${UT_TEST UT_ENV UT_EXP UT_LIT:L:@v@echo $v=${$v};@} + @echo env:; ${UT_TEST UT_ENV UT_EXP UT_LIT:L:@v@echo $v=$${$v};@} + + + + diff --git a/usr.bin/make/unit-tests/export.exp b/usr.bin/make/unit-tests/export.exp new file mode 100644 index 0000000..143771c --- /dev/null +++ b/usr.bin/make/unit-tests/export.exp @@ -0,0 +1,6 @@ +UT_DOLLAR=This is $UT_FU +UT_FOO=foobar is fubar +UT_FU=fubar +UT_TEST=export +UT_ZOO=hoopie +exit status 0 diff --git a/usr.bin/make/unit-tests/export.mk b/usr.bin/make/unit-tests/export.mk new file mode 100644 index 0000000..1b4ee72 --- /dev/null +++ b/usr.bin/make/unit-tests/export.mk @@ -0,0 +1,22 @@ +# $Id: export.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +UT_TEST=export +UT_FOO=foo${BAR} +UT_FU=fubar +UT_ZOO=hoopie +UT_NO=all +# belive it or not, we expect this one to come out with $UT_FU unexpanded. +UT_DOLLAR= This is $$UT_FU + +.export UT_FU UT_FOO +.export UT_DOLLAR +# this one will be ignored +.export .MAKE.PID + +BAR=bar is ${UT_FU} + +.MAKE.EXPORTED+= UT_ZOO UT_TEST + +all: + @env | grep '^UT_' | sort + diff --git a/usr.bin/make/unit-tests/forloop.exp b/usr.bin/make/unit-tests/forloop.exp new file mode 100644 index 0000000..df14b75 --- /dev/null +++ b/usr.bin/make/unit-tests/forloop.exp @@ -0,0 +1,19 @@ +x=one +x="two and three" +x=four +x="five" +x=-I/this +x=-I"This or that" +x=-Ithat +x="-DTHIS=\"this and that\"" +cfl=-I/this -I"This or that" -Ithat "-DTHIS=\"this and that\"" +a=one b="two and three" +a=four b="five" +a=ONE b="TWO AND THREE" +a=FOUR b="FIVE" +We expect an error next: +make: "forloop.mk" line 38: Wrong number of words (9) in .for substitution list with 2 vars +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +OK +exit status 0 diff --git a/usr.bin/make/unit-tests/forloop.mk b/usr.bin/make/unit-tests/forloop.mk new file mode 100644 index 0000000..e0399f3 --- /dev/null +++ b/usr.bin/make/unit-tests/forloop.mk @@ -0,0 +1,45 @@ +# $Id: forloop.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +all: for-loop + +LIST = one "two and three" four "five" + +.if make(for-fail) +for-fail: + +XTRA_LIST = xtra +.else + +.for x in ${LIST} +X!= echo 'x=$x' >&2; echo +.endfor + +CFL = -I/this -I"This or that" -Ithat "-DTHIS=\"this and that\"" +cfl= +.for x in ${CFL} +X!= echo 'x=$x' >&2; echo +.if empty(cfl) +cfl= $x +.else +cfl+= $x +.endif +.endfor +X!= echo 'cfl=${cfl}' >&2; echo + +.if ${cfl} != ${CFL} +.error ${.newline}'${cfl}' != ${.newline}'${CFL}' +.endif + +.for a b in ${EMPTY} +X!= echo 'a=$a b=$b' >&2; echo +.endfor +.endif + +.for a b in ${LIST} ${LIST:tu} ${XTRA_LIST} +X!= echo 'a=$a b=$b' >&2; echo +.endfor + +for-loop: + @echo We expect an error next: + @(cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} for-fail) && \ + { echo "Oops that should have failed!"; exit 1; } || echo OK diff --git a/usr.bin/make/unit-tests/forsubst.exp b/usr.bin/make/unit-tests/forsubst.exp new file mode 100644 index 0000000..0a98c00 --- /dev/null +++ b/usr.bin/make/unit-tests/forsubst.exp @@ -0,0 +1,2 @@ +.for with :S;... OK +exit status 0 diff --git a/usr.bin/make/unit-tests/forsubst.mk b/usr.bin/make/unit-tests/forsubst.mk new file mode 100644 index 0000000..00cd9b6 --- /dev/null +++ b/usr.bin/make/unit-tests/forsubst.mk @@ -0,0 +1,10 @@ +# $Id: forsubst.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +all: for-subst + +here := ${.PARSEDIR} +# this should not run foul of the parser +.for file in ${.PARSEFILE} +for-subst: ${file:S;^;${here}/;g} + @echo ".for with :S;... OK" +.endfor diff --git a/usr.bin/make/unit-tests/hash.exp b/usr.bin/make/unit-tests/hash.exp new file mode 100644 index 0000000..0a24234 --- /dev/null +++ b/usr.bin/make/unit-tests/hash.exp @@ -0,0 +1,9 @@ +b2af338b +3360ac65 +7747f046 +9ca87054 +880fe816 +208fcbd3 +d5d376eb +de41416c +exit status 0 diff --git a/usr.bin/make/unit-tests/hash.mk b/usr.bin/make/unit-tests/hash.mk new file mode 100644 index 0000000..1ed84e7 --- /dev/null +++ b/usr.bin/make/unit-tests/hash.mk @@ -0,0 +1,18 @@ +STR1= +STR2= a +STR3= ab +STR4= abc +STR5= abcd +STR6= abcde +STR7= abcdef +STR8= abcdefghijklmnopqrstuvwxyz + +all: + @echo ${STR1:hash} + @echo ${STR2:hash} + @echo ${STR3:hash} + @echo ${STR4:hash} + @echo ${STR5:hash} + @echo ${STR6:hash} + @echo ${STR7:hash} + @echo ${STR8:hash} diff --git a/usr.bin/make/unit-tests/impsrc.exp b/usr.bin/make/unit-tests/impsrc.exp new file mode 100644 index 0000000..23e8347 --- /dev/null +++ b/usr.bin/make/unit-tests/impsrc.exp @@ -0,0 +1,13 @@ +expected: source4 +actual: source4 +expected: target1.x +actual: target1.x +expected: target1.y +actual: target1.y +expected: source1 +actual: source1 +expected: source2 +actual: source2 +expected: source1 +actual: source1 +exit status 0 diff --git a/usr.bin/make/unit-tests/impsrc.mk b/usr.bin/make/unit-tests/impsrc.mk new file mode 100644 index 0000000..95ae0c3 --- /dev/null +++ b/usr.bin/make/unit-tests/impsrc.mk @@ -0,0 +1,43 @@ +# $NetBSD: impsrc.mk,v 1.2 2014/08/30 22:21:07 sjg Exp $ + +# Does ${.IMPSRC} work properly? +# It should be set, in order of precedence, to ${.TARGET} of: +# 1) the implied source of a transformation rule, +# 2) the first prerequisite from the dependency line of an explicit rule, or +# 3) the first prerequisite of an explicit rule. +# + +all: target1.z target2 target3 target4 + +.SUFFIXES: .x .y .z + +.x.y: source1 + @echo 'expected: target1.x' + @echo 'actual: $<' + +.y.z: source2 + @echo 'expected: target1.y' + @echo 'actual: $<' + +target1.y: source3 + +target1.x: source4 + @echo 'expected: source4' + @echo 'actual: $<' + +target2: source1 source2 + @echo 'expected: source1' + @echo 'actual: $<' + +target3: source1 +target3: source2 source3 + @echo 'expected: source2' + @echo 'actual: $<' + +target4: source1 +target4: + @echo 'expected: source1' + @echo 'actual: $<' + +source1 source2 source3 source4: + diff --git a/usr.bin/make/unit-tests/misc.exp b/usr.bin/make/unit-tests/misc.exp new file mode 100644 index 0000000..39a9383 --- /dev/null +++ b/usr.bin/make/unit-tests/misc.exp @@ -0,0 +1 @@ +exit status 0 diff --git a/usr.bin/make/unit-tests/misc.mk b/usr.bin/make/unit-tests/misc.mk new file mode 100644 index 0000000..2773e30 --- /dev/null +++ b/usr.bin/make/unit-tests/misc.mk @@ -0,0 +1,16 @@ +# $Id: misc.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +.if !exists(${.CURDIR}/) +.warning ${.CURDIR}/ doesn't exist ? +.endif + +.if !exists(${.CURDIR}/.) +.warning ${.CURDIR}/. doesn't exist ? +.endif + +.if !exists(${.CURDIR}/..) +.warning ${.CURDIR}/.. doesn't exist ? +.endif + +all: + @: all is well diff --git a/usr.bin/make/unit-tests/moderrs.exp b/usr.bin/make/unit-tests/moderrs.exp new file mode 100644 index 0000000..cb51aa0 --- /dev/null +++ b/usr.bin/make/unit-tests/moderrs.exp @@ -0,0 +1,16 @@ +Expect: Unknown modifier 'Z' +make: Unknown modifier 'Z' +VAR:Z= +Expect: Unknown modifier 'Z' +make: Unknown modifier 'Z' +VAR:Z= +Expect: Unclosed variable specification for VAR +make: Unclosed variable specification (expecting '}') for "VAR" (value "Thevariable") modifier S +VAR:S,V,v,=Thevariable +Expect: Unclosed variable specification for VAR +make: Unclosed variable specification after complex modifier (expecting '}') for VAR +VAR:S,V,v,=Thevariable +Expect: Unclosed substitution for VAR (, missing) +make: Unclosed substitution for VAR (, missing) +VAR:S,V,v= +exit status 0 diff --git a/usr.bin/make/unit-tests/moderrs.mk b/usr.bin/make/unit-tests/moderrs.mk new file mode 100644 index 0000000..825e6c7 --- /dev/null +++ b/usr.bin/make/unit-tests/moderrs.mk @@ -0,0 +1,31 @@ +# $Id: moderrs.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ +# +# various modifier error tests + +VAR=TheVariable +# incase we have to change it ;-) +MOD_UNKN=Z +MOD_TERM=S,V,v +MOD_S:= ${MOD_TERM}, + +all: modunkn modunknV varterm vartermV modtermV + +modunkn: + @echo "Expect: Unknown modifier 'Z'" + @echo "VAR:Z=${VAR:Z}" + +modunknV: + @echo "Expect: Unknown modifier 'Z'" + @echo "VAR:${MOD_UNKN}=${VAR:${MOD_UNKN}}" + +varterm: + @echo "Expect: Unclosed variable specification for VAR" + @echo VAR:S,V,v,=${VAR:S,V,v, + +vartermV: + @echo "Expect: Unclosed variable specification for VAR" + @echo VAR:${MOD_TERM},=${VAR:${MOD_S} + +modtermV: + @echo "Expect: Unclosed substitution for VAR (, missing)" + -@echo "VAR:${MOD_TERM}=${VAR:${MOD_TERM}}" diff --git a/usr.bin/make/unit-tests/modmatch.exp b/usr.bin/make/unit-tests/modmatch.exp new file mode 100644 index 0000000..a7bf8b7 --- /dev/null +++ b/usr.bin/make/unit-tests/modmatch.exp @@ -0,0 +1,20 @@ +LIB=a X_LIBS:M${LIB${LIB:tu}} is "/tmp/liba.a" +LIB=a X_LIBS:M*/lib${LIB}.a is "/tmp/liba.a" +LIB=a X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBA.A" +LIB=b X_LIBS:M${LIB${LIB:tu}} is "" +LIB=b X_LIBS:M*/lib${LIB}.a is "" +LIB=b X_LIBS:M*/lib${LIB}.a:tu is "" +LIB=c X_LIBS:M${LIB${LIB:tu}} is "" +LIB=c X_LIBS:M*/lib${LIB}.a is "" +LIB=c X_LIBS:M*/lib${LIB}.a:tu is "" +LIB=d X_LIBS:M${LIB${LIB:tu}} is "/tmp/libd.a" +LIB=d X_LIBS:M*/lib${LIB}.a is "/tmp/libd.a" +LIB=d X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBD.A" +LIB=e X_LIBS:M${LIB${LIB:tu}} is "/tmp/libe.a" +LIB=e X_LIBS:M*/lib${LIB}.a is "/tmp/libe.a" +LIB=e X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBE.A" +Mscanner=OK +Upper=One Two Three Four +Lower=five six seven +nose=One Three five +exit status 0 diff --git a/usr.bin/make/unit-tests/modmatch.mk b/usr.bin/make/unit-tests/modmatch.mk new file mode 100644 index 0000000..4519928 --- /dev/null +++ b/usr.bin/make/unit-tests/modmatch.mk @@ -0,0 +1,34 @@ + +X=a b c d e + +.for x in $X +LIB${x:tu}=/tmp/lib$x.a +.endfor + +X_LIBS= ${LIBA} ${LIBD} ${LIBE} + +LIB?=a + +var = head +res = no +.if !empty(var:M${:Uhead\:tail:C/:.*//}) +res = OK +.endif + +all: show-libs check-cclass + +show-libs: + @for x in $X; do ${.MAKE} -f ${MAKEFILE} show LIB=$$x; done + @echo "Mscanner=${res}" + +show: + @echo 'LIB=${LIB} X_LIBS:M$${LIB$${LIB:tu}} is "${X_LIBS:M${LIB${LIB:tu}}}"' + @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a is "${X_LIBS:M*/lib${LIB}.a}"' + @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a:tu is "${X_LIBS:M*/lib${LIB}.a:tu}"' + +LIST= One Two Three Four five six seven + +check-cclass: + @echo Upper=${LIST:M[A-Z]*} + @echo Lower=${LIST:M[^A-Z]*} + @echo nose=${LIST:M[^s]*[ex]} diff --git a/usr.bin/make/unit-tests/modmisc.exp b/usr.bin/make/unit-tests/modmisc.exp new file mode 100644 index 0000000..e406647 --- /dev/null +++ b/usr.bin/make/unit-tests/modmisc.exp @@ -0,0 +1,10 @@ +path=':/bin:/tmp::/:.:/no/such/dir:.' +path='/bin:/tmp:/:/no/such/dir' +path='/bin:/tmp:/:/no/such/dir' +path='/bin':'/tmp':'/':'/no/such/dir' +path='/bin':'/tmp':'/':'/no/such/dir' +path_/usr/xbin=/opt/xbin/ +paths=/bin /tmp / /no/such/dir /opt/xbin +PATHS=/BIN /TMP / /NO/SUCH/DIR /OPT/XBIN +The answer is 42 +exit status 0 diff --git a/usr.bin/make/unit-tests/modmisc.mk b/usr.bin/make/unit-tests/modmisc.mk new file mode 100644 index 0000000..a292b96 --- /dev/null +++ b/usr.bin/make/unit-tests/modmisc.mk @@ -0,0 +1,38 @@ +# $Id: modmisc.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ +# +# miscellaneous modifier tests + +# do not put any dirs in this list which exist on some +# but not all target systems - an exists() check is below. +path=:/bin:/tmp::/:.:/no/such/dir:. +# strip cwd from path. +MOD_NODOT=S/:/ /g:N.:ts: +# and decorate, note that $'s need to be doubled. Also note that +# the modifier_variable can be used with other modifiers. +MOD_NODOTX=S/:/ /g:N.:@d@'$$d'@ +# another mod - pretend it is more interesting +MOD_HOMES=S,/home/,/homes/, +MOD_OPT=@d@$${exists($$d):?$$d:$${d:S,/usr,/opt,}}@ +MOD_SEP=S,:, ,g + +all: modvar modvarloop modsysv + +modsysv: + @echo "The answer is ${libfoo.a:L:libfoo.a=42}" + +modvar: + @echo "path='${path}'" + @echo "path='${path:${MOD_NODOT}}'" + @echo "path='${path:S,home,homes,:${MOD_NODOT}}'" + @echo "path=${path:${MOD_NODOTX}:ts:}" + @echo "path=${path:${MOD_HOMES}:${MOD_NODOTX}:ts:}" + +.for d in ${path:${MOD_SEP}:N.} /usr/xbin +path_$d?= ${d:${MOD_OPT}:${MOD_HOMES}}/ +paths+= ${d:${MOD_OPT}:${MOD_HOMES}} +.endfor + +modvarloop: + @echo "path_/usr/xbin=${path_/usr/xbin}" + @echo "paths=${paths}" + @echo "PATHS=${paths:tu}" diff --git a/usr.bin/make/unit-tests/modorder.exp b/usr.bin/make/unit-tests/modorder.exp new file mode 100644 index 0000000..4117427 --- /dev/null +++ b/usr.bin/make/unit-tests/modorder.exp @@ -0,0 +1,11 @@ +LIST = one two three four five six seven eight nine ten +LIST:O = eight five four nine one seven six ten three two +LIST:Ox = Ok +LIST:O:Ox = Ok +LISTX = Ok +LISTSX = Ok +make: Bad modifier `:OX' for LIST +BADMOD 1 = } +make: Bad modifier `:OxXX' for LIST +BADMOD 2 = XX} +exit status 0 diff --git a/usr.bin/make/unit-tests/modorder.mk b/usr.bin/make/unit-tests/modorder.mk new file mode 100644 index 0000000..bc24d33 --- /dev/null +++ b/usr.bin/make/unit-tests/modorder.mk @@ -0,0 +1,22 @@ +# $NetBSD: modorder.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +LIST= one two three four five six seven eight nine ten +LISTX= ${LIST:Ox} +LISTSX:= ${LIST:Ox} +TEST_RESULT= && echo Ok || echo Failed + +# unit-tests have to produce the same results on each run +# so we cannot actually include :Ox output. +all: + @echo "LIST = ${LIST}" + @echo "LIST:O = ${LIST:O}" + # Note that 1 in every 10! trials two independently generated + # randomized orderings will be the same. The test framework doesn't + # support checking probabilistic output, so we accept that the test + # will incorrectly fail with probability 2.8E-7. + @echo "LIST:Ox = `test '${LIST:Ox}' != '${LIST:Ox}' ${TEST_RESULT}`" + @echo "LIST:O:Ox = `test '${LIST:O:Ox}' != '${LIST:O:Ox}' ${TEST_RESULT}`" + @echo "LISTX = `test '${LISTX}' != '${LISTX}' ${TEST_RESULT}`" + @echo "LISTSX = `test '${LISTSX}' = '${LISTSX}' ${TEST_RESULT}`" + @echo "BADMOD 1 = ${LIST:OX}" + @echo "BADMOD 2 = ${LIST:OxXX}" diff --git a/usr.bin/make/unit-tests/modts.exp b/usr.bin/make/unit-tests/modts.exp new file mode 100644 index 0000000..3389649 --- /dev/null +++ b/usr.bin/make/unit-tests/modts.exp @@ -0,0 +1,39 @@ +LIST="one two three four five six" +LIST:ts,="one,two,three,four,five,six" +LIST:ts/:tu="ONE/TWO/THREE/FOUR/FIVE/SIX" +LIST:ts::tu="ONE:TWO:THREE:FOUR:FIVE:SIX" +LIST:ts:tu="ONETWOTHREEFOURFIVESIX" +LIST:tu:ts/="ONE/TWO/THREE/FOUR/FIVE/SIX" +LIST:ts:="one:two:three:four:five:six" +LIST:ts="onetwothreefourfivesix" +LIST:ts:S/two/2/="one2threefourfivesix" +LIST:S/two/2/:ts="one2threefourfivesix" +LIST:ts/:S/two/2/="one/2/three/four/five/six" +Pretend the '/' in '/n' etc. below are back-slashes. +LIST:ts/n="one +two +three +four +five +six" +LIST:ts/t="one two three four five six" +LIST:ts/012:tu="ONE +TWO +THREE +FOUR +FIVE +SIX" +LIST:ts/xa:tu="ONE +TWO +THREE +FOUR +FIVE +SIX" +make: Bad modifier `:tx' for LIST +LIST:tx="}" +make: Bad modifier `:ts\X' for LIST +LIST:ts/x:tu="\X:tu}" +FU_mod-ts="a/b/cool" +FU_mod-ts:ts:T="cool" == cool? +B.${AAA:ts}="Baaa" == Baaa? +exit status 0 diff --git a/usr.bin/make/unit-tests/modts.mk b/usr.bin/make/unit-tests/modts.mk new file mode 100644 index 0000000..254aa42 --- /dev/null +++ b/usr.bin/make/unit-tests/modts.mk @@ -0,0 +1,44 @@ + +LIST= one two three +LIST+= four five six + +FU_mod-ts = a / b / cool + +AAA= a a a +B.aaa= Baaa + +all: mod-ts + +# Use print or printf iff they are builtin. +# XXX note that this causes problems, when make decides +# there is no need to use a shell, so avoid where possible. +.if ${type print 2> /dev/null || echo:L:sh:Mbuiltin} != "" +PRINT= print -r -- +.elif ${type printf 2> /dev/null || echo:L:sh:Mbuiltin} != "" +PRINT= printf '%s\n' +.else +PRINT= echo +.endif + +mod-ts: + @echo 'LIST="${LIST}"' + @echo 'LIST:ts,="${LIST:ts,}"' + @echo 'LIST:ts/:tu="${LIST:ts/:tu}"' + @echo 'LIST:ts::tu="${LIST:ts::tu}"' + @echo 'LIST:ts:tu="${LIST:ts:tu}"' + @echo 'LIST:tu:ts/="${LIST:tu:ts/}"' + @echo 'LIST:ts:="${LIST:ts:}"' + @echo 'LIST:ts="${LIST:ts}"' + @echo 'LIST:ts:S/two/2/="${LIST:ts:S/two/2/}"' + @echo 'LIST:S/two/2/:ts="${LIST:S/two/2/:ts}"' + @echo 'LIST:ts/:S/two/2/="${LIST:ts/:S/two/2/}"' + @echo "Pretend the '/' in '/n' etc. below are back-slashes." + @${PRINT} 'LIST:ts/n="${LIST:ts\n}"' + @${PRINT} 'LIST:ts/t="${LIST:ts\t}"' + @${PRINT} 'LIST:ts/012:tu="${LIST:ts\012:tu}"' + @${PRINT} 'LIST:ts/xa:tu="${LIST:ts\xa:tu}"' + @${PRINT} 'LIST:tx="${LIST:tx}"' + @${PRINT} 'LIST:ts/x:tu="${LIST:ts\X:tu}"' + @${PRINT} 'FU_$@="${FU_${@:ts}:ts}"' + @${PRINT} 'FU_$@:ts:T="${FU_${@:ts}:ts:T}" == cool?' + @${PRINT} 'B.$${AAA:ts}="${B.${AAA:ts}}" == Baaa?' diff --git a/usr.bin/make/unit-tests/modword.exp b/usr.bin/make/unit-tests/modword.exp new file mode 100644 index 0000000..258d7ea --- /dev/null +++ b/usr.bin/make/unit-tests/modword.exp @@ -0,0 +1,122 @@ +make: Bad modifier `:[]' for LIST +LIST:[]="" is an error +LIST:[0]="one two three four five six" +LIST:[0x0]="one two three four five six" +LIST:[000]="one two three four five six" +LIST:[*]="one two three four five six" +LIST:[@]="one two three four five six" +LIST:[0]:C/ /,/="one,two three four five six" +LIST:[0]:C/ /,/g="one,two,three,four,five,six" +LIST:[0]:C/ /,/1g="one,two,three,four,five,six" +LIST:[*]:C/ /,/="one,two three four five six" +LIST:[*]:C/ /,/g="one,two,three,four,five,six" +LIST:[*]:C/ /,/1g="one,two,three,four,five,six" +LIST:[@]:C/ /,/="one two three four five six" +LIST:[@]:C/ /,/g="one two three four five six" +LIST:[@]:C/ /,/1g="one two three four five six" +LIST:[@]:[0]:C/ /,/="one,two three four five six" +LIST:[0]:[@]:C/ /,/="one two three four five six" +LIST:[@]:[*]:C/ /,/="one,two three four five six" +LIST:[*]:[@]:C/ /,/="one two three four five six" +EMPTY="" +EMPTY:[#]="1" == 1 ? +ESCAPEDSPACE="\ " +ESCAPEDSPACE:[#]="1" == 1 ? +REALLYSPACE=" " +REALLYSPACE:[#]="1" == 1 ? +LIST:[#]="6" +LIST:[0]:[#]="1" == 1 ? +LIST:[*]:[#]="1" == 1 ? +LIST:[@]:[#]="6" +LIST:[1]:[#]="1" +LIST:[1..3]:[#]="3" +EMPTY:[1]="" +ESCAPEDSPACE="\ " +ESCAPEDSPACE:[1]="\ " +REALLYSPACE=" " +REALLYSPACE:[1]="" == "" ? +REALLYSPACE:[*]:[1]=" " == " " ? +LIST:[1]="one" +make: Bad modifier `:[1.]' for LIST +LIST:[1.]="" is an error +make: Bad modifier `:[1].' for LIST +LIST:[1].="}" is an error +LIST:[2]="two" +LIST:[6]="six" +LIST:[7]="" +LIST:[999]="" +make: Bad modifier `:[-]' for LIST +LIST:[-]="" is an error +make: Bad modifier `:[--]' for LIST +LIST:[--]="" is an error +LIST:[-1]="six" +LIST:[-2]="five" +LIST:[-6]="one" +LIST:[-7]="" +LIST:[-999]="" +LONGLIST:[17]="17" +LONGLIST:[0x11]="17" +LONGLIST:[021]="17" +LIST:[0]:[1]="one two three four five six" +LIST:[*]:[1]="one two three four five six" +LIST:[@]:[1]="one" +LIST:[0]:[2]="" +LIST:[*]:[2]="" +LIST:[@]:[2]="two" +LIST:[*]:C/ /,/:[2]="" +LIST:[*]:C/ /,/:[*]:[2]="" +LIST:[*]:C/ /,/:[@]:[2]="three" +make: Bad modifier `:[1.]' for LIST +LIST:[1.]="" is an error +make: Bad modifier `:[1..]' for LIST +LIST:[1..]="" is an error +LIST:[1..1]="one" +make: Bad modifier `:[1..1.]' for LIST +LIST:[1..1.]="" is an error +LIST:[1..2]="one two" +LIST:[2..1]="two one" +LIST:[3..-2]="three four five" +LIST:[-4..4]="three four" +make: Bad modifier `:[0..1]' for LIST +LIST:[0..1]="" is an error +make: Bad modifier `:[-1..0]' for LIST +LIST:[-1..0]="" is an error +LIST:[-1..1]="six five four three two one" +LIST:[0..0]="one two three four five six" +LIST:[3..99]="three four five six" +LIST:[-3..-99]="four three two one" +LIST:[-99..-3]="one two three four" +HASH="#" == "#" ? +LIST:[${HASH}]="6" +LIST:[${ZERO}]="one two three four five six" +LIST:[${ZERO}x${ONE}]="one" +LIST:[${ONE}]="one" +LIST:[${MINUSONE}]="six" +LIST:[${STAR}]="one two three four five six" +LIST:[${AT}]="one two three four five six" +make: Bad modifier `:[${EMPTY' for LIST +LIST:[${EMPTY}]="" is an error +LIST:[${LONGLIST:[21]:S/2//}]="one" +LIST:[${LIST:[#]}]="six" +LIST:[${LIST:[${HASH}]}]="six" +LIST:S/ /,/="one two three four five six" +LIST:S/ /,/W="one,two three four five six" +LIST:S/ /,/gW="one,two,three,four,five,six" +EMPTY:S/^/,/="," +EMPTY:S/^/,/W="," +LIST:C/ /,/="one two three four five six" +LIST:C/ /,/W="one,two three four five six" +LIST:C/ /,/gW="one,two,three,four,five,six" +EMPTY:C/^/,/="," +EMPTY:C/^/,/W="," +LIST:tW="one two three four five six" +LIST:tw="one two three four five six" +LIST:tW:C/ /,/="one,two three four five six" +LIST:tW:C/ /,/g="one,two,three,four,five,six" +LIST:tW:C/ /,/1g="one,two,three,four,five,six" +LIST:tw:C/ /,/="one two three four five six" +LIST:tw:C/ /,/g="one two three four five six" +LIST:tw:C/ /,/1g="one two three four five six" +LIST:tw:tW:C/ /,/="one,two three four five six" +LIST:tW:tw:C/ /,/="one two three four five six" +exit status 0 diff --git a/usr.bin/make/unit-tests/modword.mk b/usr.bin/make/unit-tests/modword.mk new file mode 100644 index 0000000..00a56de --- /dev/null +++ b/usr.bin/make/unit-tests/modword.mk @@ -0,0 +1,151 @@ +# $Id: modword.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ +# +# Test behaviour of new :[] modifier + +all: mod-squarebrackets mod-S-W mod-C-W mod-tW-tw + +LIST= one two three +LIST+= four five six +LONGLIST= 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + +EMPTY= # the space should be ignored +ESCAPEDSPACE=\ # escaped space before the '#' +REALLYSPACE:=${EMPTY:C/^/ /W} +HASH= \# +AT= @ +STAR= * +ZERO= 0 +ONE= 1 +MINUSONE= -1 + +mod-squarebrackets: mod-squarebrackets-0-star-at \ + mod-squarebrackets-hash \ + mod-squarebrackets-n \ + mod-squarebrackets-start-end \ + mod-squarebrackets-nested + +mod-squarebrackets-0-star-at: + @echo 'LIST:[]="${LIST:[]}" is an error' + @echo 'LIST:[0]="${LIST:[0]}"' + @echo 'LIST:[0x0]="${LIST:[0x0]}"' + @echo 'LIST:[000]="${LIST:[000]}"' + @echo 'LIST:[*]="${LIST:[*]}"' + @echo 'LIST:[@]="${LIST:[@]}"' + @echo 'LIST:[0]:C/ /,/="${LIST:[0]:C/ /,/}"' + @echo 'LIST:[0]:C/ /,/g="${LIST:[0]:C/ /,/g}"' + @echo 'LIST:[0]:C/ /,/1g="${LIST:[0]:C/ /,/1g}"' + @echo 'LIST:[*]:C/ /,/="${LIST:[*]:C/ /,/}"' + @echo 'LIST:[*]:C/ /,/g="${LIST:[*]:C/ /,/g}"' + @echo 'LIST:[*]:C/ /,/1g="${LIST:[*]:C/ /,/1g}"' + @echo 'LIST:[@]:C/ /,/="${LIST:[@]:C/ /,/}"' + @echo 'LIST:[@]:C/ /,/g="${LIST:[@]:C/ /,/g}"' + @echo 'LIST:[@]:C/ /,/1g="${LIST:[@]:C/ /,/1g}"' + @echo 'LIST:[@]:[0]:C/ /,/="${LIST:[@]:[0]:C/ /,/}"' + @echo 'LIST:[0]:[@]:C/ /,/="${LIST:[0]:[@]:C/ /,/}"' + @echo 'LIST:[@]:[*]:C/ /,/="${LIST:[@]:[*]:C/ /,/}"' + @echo 'LIST:[*]:[@]:C/ /,/="${LIST:[*]:[@]:C/ /,/}"' + +mod-squarebrackets-hash: + @echo 'EMPTY="${EMPTY}"' + @echo 'EMPTY:[#]="${EMPTY:[#]}" == 1 ?' + @echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"' + @echo 'ESCAPEDSPACE:[#]="${ESCAPEDSPACE:[#]}" == 1 ?' + @echo 'REALLYSPACE="${REALLYSPACE}"' + @echo 'REALLYSPACE:[#]="${REALLYSPACE:[#]}" == 1 ?' + @echo 'LIST:[#]="${LIST:[#]}"' + @echo 'LIST:[0]:[#]="${LIST:[0]:[#]}" == 1 ?' + @echo 'LIST:[*]:[#]="${LIST:[*]:[#]}" == 1 ?' + @echo 'LIST:[@]:[#]="${LIST:[@]:[#]}"' + @echo 'LIST:[1]:[#]="${LIST:[1]:[#]}"' + @echo 'LIST:[1..3]:[#]="${LIST:[1..3]:[#]}"' + +mod-squarebrackets-n: + @echo 'EMPTY:[1]="${EMPTY:[1]}"' + @echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"' + @echo 'ESCAPEDSPACE:[1]="${ESCAPEDSPACE:[1]}"' + @echo 'REALLYSPACE="${REALLYSPACE}"' + @echo 'REALLYSPACE:[1]="${REALLYSPACE:[1]}" == "" ?' + @echo 'REALLYSPACE:[*]:[1]="${REALLYSPACE:[*]:[1]}" == " " ?' + @echo 'LIST:[1]="${LIST:[1]}"' + @echo 'LIST:[1.]="${LIST:[1.]}" is an error' + @echo 'LIST:[1].="${LIST:[1].}" is an error' + @echo 'LIST:[2]="${LIST:[2]}"' + @echo 'LIST:[6]="${LIST:[6]}"' + @echo 'LIST:[7]="${LIST:[7]}"' + @echo 'LIST:[999]="${LIST:[999]}"' + @echo 'LIST:[-]="${LIST:[-]}" is an error' + @echo 'LIST:[--]="${LIST:[--]}" is an error' + @echo 'LIST:[-1]="${LIST:[-1]}"' + @echo 'LIST:[-2]="${LIST:[-2]}"' + @echo 'LIST:[-6]="${LIST:[-6]}"' + @echo 'LIST:[-7]="${LIST:[-7]}"' + @echo 'LIST:[-999]="${LIST:[-999]}"' + @echo 'LONGLIST:[17]="${LONGLIST:[17]}"' + @echo 'LONGLIST:[0x11]="${LONGLIST:[0x11]}"' + @echo 'LONGLIST:[021]="${LONGLIST:[021]}"' + @echo 'LIST:[0]:[1]="${LIST:[0]:[1]}"' + @echo 'LIST:[*]:[1]="${LIST:[*]:[1]}"' + @echo 'LIST:[@]:[1]="${LIST:[@]:[1]}"' + @echo 'LIST:[0]:[2]="${LIST:[0]:[2]}"' + @echo 'LIST:[*]:[2]="${LIST:[*]:[2]}"' + @echo 'LIST:[@]:[2]="${LIST:[@]:[2]}"' + @echo 'LIST:[*]:C/ /,/:[2]="${LIST:[*]:C/ /,/:[2]}"' + @echo 'LIST:[*]:C/ /,/:[*]:[2]="${LIST:[*]:C/ /,/:[*]:[2]}"' + @echo 'LIST:[*]:C/ /,/:[@]:[2]="${LIST:[*]:C/ /,/:[@]:[2]}"' + +mod-squarebrackets-start-end: + @echo 'LIST:[1.]="${LIST:[1.]}" is an error' + @echo 'LIST:[1..]="${LIST:[1..]}" is an error' + @echo 'LIST:[1..1]="${LIST:[1..1]}"' + @echo 'LIST:[1..1.]="${LIST:[1..1.]}" is an error' + @echo 'LIST:[1..2]="${LIST:[1..2]}"' + @echo 'LIST:[2..1]="${LIST:[2..1]}"' + @echo 'LIST:[3..-2]="${LIST:[3..-2]}"' + @echo 'LIST:[-4..4]="${LIST:[-4..4]}"' + @echo 'LIST:[0..1]="${LIST:[0..1]}" is an error' + @echo 'LIST:[-1..0]="${LIST:[-1..0]}" is an error' + @echo 'LIST:[-1..1]="${LIST:[-1..1]}"' + @echo 'LIST:[0..0]="${LIST:[0..0]}"' + @echo 'LIST:[3..99]="${LIST:[3..99]}"' + @echo 'LIST:[-3..-99]="${LIST:[-3..-99]}"' + @echo 'LIST:[-99..-3]="${LIST:[-99..-3]}"' + +mod-squarebrackets-nested: + @echo 'HASH="${HASH}" == "#" ?' + @echo 'LIST:[$${HASH}]="${LIST:[${HASH}]}"' + @echo 'LIST:[$${ZERO}]="${LIST:[${ZERO}]}"' + @echo 'LIST:[$${ZERO}x$${ONE}]="${LIST:[${ZERO}x${ONE}]}"' + @echo 'LIST:[$${ONE}]="${LIST:[${ONE}]}"' + @echo 'LIST:[$${MINUSONE}]="${LIST:[${MINUSONE}]}"' + @echo 'LIST:[$${STAR}]="${LIST:[${STAR}]}"' + @echo 'LIST:[$${AT}]="${LIST:[${AT}]}"' + @echo 'LIST:[$${EMPTY}]="${LIST:[${EMPTY}]}" is an error' + @echo 'LIST:[$${LONGLIST:[21]:S/2//}]="${LIST:[${LONGLIST:[21]:S/2//}]}"' + @echo 'LIST:[$${LIST:[#]}]="${LIST:[${LIST:[#]}]}"' + @echo 'LIST:[$${LIST:[$${HASH}]}]="${LIST:[${LIST:[${HASH}]}]}"' + +mod-C-W: + @echo 'LIST:C/ /,/="${LIST:C/ /,/}"' + @echo 'LIST:C/ /,/W="${LIST:C/ /,/W}"' + @echo 'LIST:C/ /,/gW="${LIST:C/ /,/gW}"' + @echo 'EMPTY:C/^/,/="${EMPTY:C/^/,/}"' + @echo 'EMPTY:C/^/,/W="${EMPTY:C/^/,/W}"' + +mod-S-W: + @echo 'LIST:S/ /,/="${LIST:S/ /,/}"' + @echo 'LIST:S/ /,/W="${LIST:S/ /,/W}"' + @echo 'LIST:S/ /,/gW="${LIST:S/ /,/gW}"' + @echo 'EMPTY:S/^/,/="${EMPTY:S/^/,/}"' + @echo 'EMPTY:S/^/,/W="${EMPTY:S/^/,/W}"' + +mod-tW-tw: + @echo 'LIST:tW="${LIST:tW}"' + @echo 'LIST:tw="${LIST:tw}"' + @echo 'LIST:tW:C/ /,/="${LIST:tW:C/ /,/}"' + @echo 'LIST:tW:C/ /,/g="${LIST:tW:C/ /,/g}"' + @echo 'LIST:tW:C/ /,/1g="${LIST:tW:C/ /,/1g}"' + @echo 'LIST:tw:C/ /,/="${LIST:tw:C/ /,/}"' + @echo 'LIST:tw:C/ /,/g="${LIST:tw:C/ /,/g}"' + @echo 'LIST:tw:C/ /,/1g="${LIST:tw:C/ /,/1g}"' + @echo 'LIST:tw:tW:C/ /,/="${LIST:tw:tW:C/ /,/}"' + @echo 'LIST:tW:tw:C/ /,/="${LIST:tW:tw:C/ /,/}"' diff --git a/usr.bin/make/unit-tests/order.exp b/usr.bin/make/unit-tests/order.exp new file mode 100644 index 0000000..d876914 --- /dev/null +++ b/usr.bin/make/unit-tests/order.exp @@ -0,0 +1,4 @@ +Making the.c +Making the.h +Making the.o from the.h the.c +exit status 0 diff --git a/usr.bin/make/unit-tests/order.mk b/usr.bin/make/unit-tests/order.mk new file mode 100644 index 0000000..f90b627 --- /dev/null +++ b/usr.bin/make/unit-tests/order.mk @@ -0,0 +1,20 @@ +# $NetBSD: order.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +# Test that .ORDER is handled correctly. +# The explicit dependency the.o: the.h will make us examine the.h +# the .ORDER will prevent us building it immediately, +# we should then examine the.c rather than stop. + +all: the.o + +.ORDER: the.c the.h + +the.c the.h: + @echo Making $@ + +.SUFFIXES: .o .c + +.c.o: + @echo Making $@ from $? + +the.o: the.h diff --git a/usr.bin/make/unit-tests/phony-end.exp b/usr.bin/make/unit-tests/phony-end.exp new file mode 100644 index 0000000..c3c517c --- /dev/null +++ b/usr.bin/make/unit-tests/phony-end.exp @@ -0,0 +1,6 @@ +.TARGET="phony" .PREFIX="phony" .IMPSRC="" +.TARGET="all" .PREFIX="all" .IMPSRC="phony" +.TARGET="ok" .PREFIX="ok" .IMPSRC="" +.TARGET="also.ok" .PREFIX="also.ok" .IMPSRC="" +.TARGET="bug" .PREFIX="bug" .IMPSRC="" +exit status 0 diff --git a/usr.bin/make/unit-tests/phony-end.mk b/usr.bin/make/unit-tests/phony-end.mk new file mode 100644 index 0000000..92cc0e6 --- /dev/null +++ b/usr.bin/make/unit-tests/phony-end.mk @@ -0,0 +1,9 @@ +# $Id: phony-end.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +all ok also.ok bug phony: + @echo '${.TARGET .PREFIX .IMPSRC:L:@v@$v="${$v}"@}' + +.END: ok also.ok bug + +phony bug: .PHONY +all: phony diff --git a/usr.bin/make/unit-tests/posix.exp b/usr.bin/make/unit-tests/posix.exp new file mode 100644 index 0000000..7e74cab --- /dev/null +++ b/usr.bin/make/unit-tests/posix.exp @@ -0,0 +1,23 @@ +Posix says we should execute the command as if run by system(3) +Expect 'Hello,' and 'World!' +Hello, +World! +a command +a command prefixed by '+' executes even with -n +another command +make -n +echo a command +echo "a command prefixed by '+' executes even with -n" +a command prefixed by '+' executes even with -n +echo another command +make -n -j1 +{ echo a command +} || exit $? +echo "a command prefixed by '+' executes even with -n" +a command prefixed by '+' executes even with -n +{ echo another command +} || exit $? +Now we expect an error... +*** Error code 1 (continuing) +`all' not remade because of errors. +exit status 0 diff --git a/usr.bin/make/unit-tests/posix.mk b/usr.bin/make/unit-tests/posix.mk new file mode 100644 index 0000000..a73e2e5 --- /dev/null +++ b/usr.bin/make/unit-tests/posix.mk @@ -0,0 +1,24 @@ +# $Id: posix.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +all: x plus subs err + +x: + @echo "Posix says we should execute the command as if run by system(3)" + @echo "Expect 'Hello,' and 'World!'" + @echo Hello,; false; echo "World!" + +plus: + @echo a command + +@echo "a command prefixed by '+' executes even with -n" + @echo another command + +subs: + @echo make -n + @${.MAKE} -f ${MAKEFILE} -n plus + @echo make -n -j1 + @${.MAKE} -f ${MAKEFILE} -n -j1 plus + +err: + @(echo Now we expect an error...; exit 1) + @echo "Oops! you shouldn't see this!" + diff --git a/usr.bin/make/unit-tests/posix1.exp b/usr.bin/make/unit-tests/posix1.exp new file mode 100644 index 0000000..fa1f15d --- /dev/null +++ b/usr.bin/make/unit-tests/posix1.exp @@ -0,0 +1,186 @@ +${VAR} = "foo bar baz" +a +b +c +foo baR baz, bar baz, foo bar baz, fooadd baradd bazadd +mkdir -p 'dir' +touch 'dir/obj_1.h' +mkdir -p 'dir' +printf '#include "obj_1.h"\nconst char* obj_1 = "dir/obj_1.c";\n' \ + >'dir/obj_1.c' +Local variables + ${@}="dir/obj_1.o" ${<}="dir/obj_1.c" + ${*}="dir/obj_1" ${?}="dir/obj_1.h dir/obj_1.c" + ${%}="" + +Directory and filename parts of local variables + ${@D}="dir" ${@F}="obj_1.o" + ${<D}="dir" ${<F}="obj_1.c" + ${*D}="dir" ${*F}="obj_1" + ${?D}="dir dir" ${?F}="obj_1.h obj_1.c" + ${%D}="" ${%F}="" + +Local variable substitutions + ${@:.o=}="dir/obj_1" ${<:.c=.C}="dir/obj_1.C" + ${*:=.h}="dir/obj_1.h" ${?:.h=.H}="dir/obj_1.H dir/obj_1.c" + ${%:=}="" + +Target with suffix transformations + ${@D:=append}="dirappend" + ${@F:.o=.O}="obj_1.O" + + Implied source with suffix transformations + ${<D:r=rr}="dirr" + ${<F:.c=.C}="obj_1.C" + + Suffixless target with suffix transformations + ${*D:.=dot}="dir" + ${*F:.a=}="obj_1" + + Out-of-date dependencies with suffix transformations + ${?D:ir=}="d d" + ${?F:.h=.H}="obj_1.H obj_1.c" + + Member with suffix transformations + ${%D:.=}="" + ${%F:${VAR2}=${VAR}}="" + +cc -c -o 'dir/obj_1.o' 'dir/obj_1.c' +mkdir -p '.' +touch 'dummy' +Local variables + ${@}="lib.a" ${<}="dir/obj_1.o" + ${*}="obj1" ${?}="dir/obj_1.o dummy" + ${%}="obj1.o" + +Directory and filename parts of local variables + ${@D}="." ${@F}="lib.a" + ${<D}="dir" ${<F}="obj_1.o" + ${*D}="." ${*F}="obj1" + ${?D}="dir ." ${?F}="obj_1.o dummy" + ${%D}="." ${%F}="obj1.o" + +Local variable substitutions + ${@:.o=}="lib.a" ${<:.c=.C}="dir/obj_1.o" + ${*:=.h}="obj1.h" ${?:.h=.H}="dir/obj_1.o dummy" + ${%:=}="obj1.o" + +Target with suffix transformations + ${@D:=append}=".append" + ${@F:.o=.O}="lib.a" + + Implied source with suffix transformations + ${<D:r=rr}="dirr" + ${<F:.c=.C}="obj_1.o" + + Suffixless target with suffix transformations + ${*D:.=dot}="dot" + ${*F:.a=}="obj1" + + Out-of-date dependencies with suffix transformations + ${?D:ir=}="d ." + ${?F:.h=.H}="obj_1.o dummy" + + Member with suffix transformations + ${%D:.=}="" + ${%F:${VAR2}=${VAR}}="obj1foo bar baz" + +cp 'dir/obj_1.o' 'obj1.o' +ar -rcv 'lib.a' 'obj1.o' +a - obj1.o +rm -f 'obj1.o' +mkdir -p '.' +printf '#include "obj_2.h"\nconst char* obj_2 = "obj_2.c";\n' \ + >'obj_2.c' +mkdir -p '.' +touch 'obj_2.h' +Local variables + ${@}="obj2.o" ${<}="obj_2.c" + ${*}="obj2" ${?}="obj_2.c obj_2.h dir/obj_1.h" + ${%}="" + +Directory and filename parts of local variables + ${@D}="." ${@F}="obj2.o" + ${<D}="." ${<F}="obj_2.c" + ${*D}="." ${*F}="obj2" + ${?D}=". . dir" ${?F}="obj_2.c obj_2.h obj_1.h" + ${%D}="" ${%F}="" + +Local variable substitutions + ${@:.o=}="obj2" ${<:.c=.C}="obj_2.C" + ${*:=.h}="obj2.h" ${?:.h=.H}="obj_2.c obj_2.H dir/obj_1.H" + ${%:=}="" + +Target with suffix transformations + ${@D:=append}=".append" + ${@F:.o=.O}="obj2.O" + + Implied source with suffix transformations + ${<D:r=rr}="." + ${<F:.c=.C}="obj_2.C" + + Suffixless target with suffix transformations + ${*D:.=dot}="dot" + ${*F:.a=}="obj2" + + Out-of-date dependencies with suffix transformations + ${?D:ir=}=". . d" + ${?F:.h=.H}="obj_2.c obj_2.H obj_1.H" + + Member with suffix transformations + ${%D:.=}="" + ${%F:${VAR2}=${VAR}}="" + +cc -c -o 'obj2.o' 'obj_2.c' +ar -rcv 'lib.a' 'obj2.o' +a - obj2.o +mkdir -p '.' +touch 'obj3.h' +mkdir -p 'dir' +touch 'dir/dummy' +mkdir -p '.' +printf '#include "obj3.h"\nconst char* obj3 = "obj3.c";\n' \ + >'obj3.c' +Local variables + ${@}="lib.a" ${<}="obj3.c" + ${*}="obj3" ${?}="obj3.h dir/dummy obj3.c" + ${%}="obj3.o" + +Directory and filename parts of local variables + ${@D}="." ${@F}="lib.a" + ${<D}="." ${<F}="obj3.c" + ${*D}="." ${*F}="obj3" + ${?D}=". dir ." ${?F}="obj3.h dummy obj3.c" + ${%D}="." ${%F}="obj3.o" + +Local variable substitutions + ${@:.o=}="lib.a" ${<:.c=.C}="obj3.C" + ${*:=.h}="obj3.h" ${?:.h=.H}="obj3.H dir/dummy obj3.c" + ${%:=}="obj3.o" + +Target with suffix transformations + ${@D:=append}=".append" + ${@F:.o=.O}="lib.a" + + Implied source with suffix transformations + ${<D:r=rr}="." + ${<F:.c=.C}="obj3.C" + + Suffixless target with suffix transformations + ${*D:.=dot}="dot" + ${*F:.a=}="obj3" + + Out-of-date dependencies with suffix transformations + ${?D:ir=}=". d ." + ${?F:.h=.H}="obj3.H dummy obj3.c" + + Member with suffix transformations + ${%D:.=}="" + ${%F:${VAR2}=${VAR}}="obj3foo bar baz" + +cc -c -o 'obj3.o' 'obj3.c' +ar -rcv 'lib.a' 'obj3.o' +a - obj3.o +rm -f 'obj3.o' +ar -s 'lib.a' +exit status 0 diff --git a/usr.bin/make/unit-tests/posix1.mk b/usr.bin/make/unit-tests/posix1.mk new file mode 100644 index 0000000..1bf6a56 --- /dev/null +++ b/usr.bin/make/unit-tests/posix1.mk @@ -0,0 +1,184 @@ +# $NetBSD: posix1.mk,v 1.3 2014/08/30 22:21:08 sjg Exp $ + +# Keep the default suffixes from interfering, just in case. +.SUFFIXES: + +all: line-continuations suffix-substitution localvars + +# we need to clean for repeatable results +.BEGIN: clean +clean: + @rm -f lib.a dir/* dummy obj* + +# +# Line continuations +# + +# Escaped newlines and leading whitespace from the next line are replaced +# with single space, except in commands, where the escape and the newline +# are retained, but a single leading tab (if any) from the next line is +# removed. (PR 49085) +# Expect: +# ${VAR} = "foo bar baz" +# a +# b +# c +VAR = foo\ +\ + bar\ + baz + +line-continuations: + @echo '$${VAR} = "${VAR}"' + @echo 'aXbXc' | sed -e 's/X/\ + /g' + + +# +# Suffix substitution +# + +# The only variable modifier accepted by POSIX. +# ${VAR:s1=s2}: replace s1, if found, with s2 at end of each word in +# ${VAR}. s1 and s2 may contain macro expansions. +# Expect: foo baR baz, bar baz, foo bar baz, fooadd baradd bazadd +suffix-substitution: + @echo '${VAR:r=R}, ${VAR:foo=}, ${VAR:not_there=wrong}, ${VAR:=add}' + + +# +# Local variables: regular forms, D/F forms and suffix substitution. +# + +# In the past substitutions did not work with the D/F forms and those +# forms were not available for $?. (PR 49085) + +ARFLAGS = -rcv + +localvars: lib.a + +# $@ = target or archive name $< = implied source +# $* = target without suffix $? = sources newer than target +# $% = archive member name +LOCALS = \ + "Local variables\n\ + \$${@}=\"${@}\" \$${<}=\"${<}\"\n\ + \$${*}=\"${*}\" \$${?}=\"${?}\"\n\ + \$${%%}=\"${%}\"\n\n" + +# $XD = directory part of X $XF = file part of X +# X is one of the local variables. +LOCAL_ALTERNATIVES = \ + "Directory and filename parts of local variables\n\ + \$${@D}=\"${@D}\" \$${@F}=\"${@F}\"\n\ + \$${<D}=\"${<D}\" \$${<F}=\"${<F}\"\n\ + \$${*D}=\"${*D}\" \$${*F}=\"${*F}\"\n\ + \$${?D}=\"${?D}\" \$${?F}=\"${?F}\"\n\ + \$${%%D}=\"${%D}\" \$${%%F}=\"${%F}\"\n\n" + +# Do all kinds of meaningless substitutions on local variables to see +# if they work. Add, remove and replace things. +VAR2 = .o +VAR3 = foo +LOCAL_SUBSTITUTIONS = \ + "Local variable substitutions\n\ + \$${@:.o=}=\"${@:.o=}\" \$${<:.c=.C}=\"${<:.c=.C}\"\n\ + \$${*:=.h}=\"${*:=.h}\" \$${?:.h=.H}=\"${?:.h=.H}\"\n\ + \$${%%:=}=\"${%:=}\"\n\n" + +LOCAL_ALTERNATIVE_SUBSTITUTIONS = \ + "Target with suffix transformations\n\ + \$${@D:=append}=\"${@D:=append}\"\n\ + \$${@F:.o=.O}=\"${@F:.o=.O}\"\n\ + \n\ + Implied source with suffix transformations\n\ + \$${<D:r=rr}=\"${<D:r=rr}\"\n\ + \$${<F:.c=.C}=\"${<F:.c=.C}\"\n\ + \n\ + Suffixless target with suffix transformations\n\ + \$${*D:.=dot}=\"${*D:.=dot}\"\n\ + \$${*F:.a=}=\"${*F:.a=}\"\n\ + \n\ + Out-of-date dependencies with suffix transformations\n\ + \$${?D:ir=}=\"${?D:ir=}\"\n\ + \$${?F:.h=.H}=\"${?F:.h=.H}\"\n\ + \n\ + Member with suffix transformations\n\ + \$${%%D:.=}=\"${%D:.=}\"\n\ + \$${%%F:\$${VAR2}=\$${VAR}}=\"${%F:${VAR2}=${VAR}}\"\n\n" + +.SUFFIXES: .c .o .a + +# The system makefiles make the .c.a rule .PRECIOUS with a special source, +# but such a thing is not POSIX compatible. It's also somewhat useless +# in a test makefile. +.c.a: + @printf ${LOCALS} + @printf ${LOCAL_ALTERNATIVES} + @printf ${LOCAL_SUBSTITUTIONS} + @printf ${LOCAL_ALTERNATIVE_SUBSTITUTIONS} + cc -c -o '${%}' '${<}' + ar ${ARFLAGS} '${@}' '${%}' + rm -f '${%}' + +.c.o: + @printf ${LOCALS} + @printf ${LOCAL_ALTERNATIVES} + @printf ${LOCAL_SUBSTITUTIONS} + @printf ${LOCAL_ALTERNATIVE_SUBSTITUTIONS} + cc -c -o '${@}' '${<}' + +# Some of these rules are padded with useless extra dependencies just so +# that ${?} has more than one file. + +lib.a: lib.a(obj1.o) lib.a(obj2.o) lib.a(obj3.o) + ar -s '${@}' + +# Explicit rule where the dependency is an inferred file. The dependency +# object's name differs from the member's because there was a bug which +# forced a dependency on member even when no such dependency was specified +# (PR 49086). +lib.a(obj1.o): dir/obj_1.o dummy + @printf ${LOCALS} + @printf ${LOCAL_ALTERNATIVES} + @printf ${LOCAL_SUBSTITUTIONS} + @printf ${LOCAL_ALTERNATIVE_SUBSTITUTIONS} + cp 'dir/obj_1.o' '$%' + ar ${ARFLAGS} '${@}' '$%' + rm -f '$%' + +# Excplicit rule where the dependency also has an explicit rule. +lib.a(obj2.o): obj2.o + ar ${ARFLAGS} '${@}' '${%}' + +# Use .c.a inference with an extra dependency. +lib.a(obj3.o): obj3.h dir/dummy + +# Use .c.o inference with an extra dependency. +dir/obj_1.o: dir/obj_1.h + +# According to POSIX, $* is only required for inference rules and $<'s +# value is unspecified outside of inference rules. Strictly speaking +# we shouldn't be expanding them here but who cares. At least we get +# to check that the program does nothing stupid (like crash) with them. +# The C file is named differently from the object file because there +# was a bug which forced dependencies based on inference rules on all +# applicable targets (PR 49086). +obj2.o: obj_2.c obj_2.h dir/obj_1.h + @printf ${LOCALS} + @printf ${LOCAL_ALTERNATIVES} + @printf ${LOCAL_SUBSTITUTIONS} + @printf ${LOCAL_ALTERNATIVE_SUBSTITUTIONS} + cc -c -o '${@}' 'obj_2.c' + +# Hey, this is make, we can make our own test data setup! obj1.c +# and obj2.c are not used, so they should not get created. They're here +# as a bait for a regression into the forced dependencies discussed earlier. +obj1.c dir/obj_1.c obj2.c obj_2.c obj3.c: + mkdir -p '${@D}' + printf '#include "${@F:.c=.h}"\nconst char* ${@F:.c=} = "${@}";\n' \ + >'${@}' + +dir/obj_1.h obj_2.h obj3.h dummy dir/dummy: + mkdir -p '${@D}' + touch '${@}' diff --git a/usr.bin/make/unit-tests/qequals.exp b/usr.bin/make/unit-tests/qequals.exp new file mode 100644 index 0000000..6b2f4dc --- /dev/null +++ b/usr.bin/make/unit-tests/qequals.exp @@ -0,0 +1,2 @@ +V.i386 ?= OK +exit status 0 diff --git a/usr.bin/make/unit-tests/qequals.mk b/usr.bin/make/unit-tests/qequals.mk new file mode 100644 index 0000000..db6d9c3 --- /dev/null +++ b/usr.bin/make/unit-tests/qequals.mk @@ -0,0 +1,8 @@ +# $Id: qequals.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +M= i386 +V.i386= OK +V.$M ?= bug + +all: + @echo 'V.$M ?= ${V.$M}' diff --git a/usr.bin/make/unit-tests/suffixes.exp b/usr.bin/make/unit-tests/suffixes.exp new file mode 100644 index 0000000..2a46e1c --- /dev/null +++ b/usr.bin/make/unit-tests/suffixes.exp @@ -0,0 +1,35 @@ +make: don't know how to make issue3 (continuing) +There should be no text after the colon: +touch .a +There should be no text after the colon: +touch .a.b +There should be no text after the colon: +touch .b.a +touch issue5a.c +first set +cp issue5a.c issue5a.d +touch issue5b.d +first set +cp issue5b.d issue5b.c +touch issue5c.d +first set +cp issue5c.d issue5c +touch issue5d.d +first set +cp issue5d.d issue5d.e +touch issue5e.e +first set +cp issue5e.e issue5e.d +make: don't know how to make issue6.f (continuing) +touch issue10.d +first set +cp issue10.d issue10.e +touch issue11.h +touch issue11.first +.ALLSRC: issue11.h issue11.first +cp issue11.h issue11.i +touch issue11.second +.ALLSRC: issue11.i issue11.second +cp issue11.i issue11.j +`all' not remade because of errors. +exit status 0 diff --git a/usr.bin/make/unit-tests/suffixes.mk b/usr.bin/make/unit-tests/suffixes.mk new file mode 100644 index 0000000..113484a --- /dev/null +++ b/usr.bin/make/unit-tests/suffixes.mk @@ -0,0 +1,89 @@ +# $NetBSD: suffixes.mk,v 1.3 2014/08/30 22:21:08 sjg Exp $ + +# Issues from PR 49086 + +# Issue 3: single suffix rules remain active after .SUFFIXES is cleared +# +# There's a rule for issue3.a, but .a is no longer a known suffix when +# targets are being made, so issue3 should not get made. +all: issue3 + +# Issue 4: suffix rules do not become regular rules when .SUFFIXES is cleared +# +# When the rules were encountered, .a and .b were known suffices, but later +# on they were forgotten. These should get created as regular targets. +all: .a .a.b .b.a + +# Issue 5: adding more suffixes does not make existing rules into suffix rules +# +# When the targets .c.d, .d.c, .d, .d.e, and .e.d were encountered, only .a, +# .b and .c were known suffixes, so all of them were regular rules. Later +# rest of the suffixes were made known, so they should all be suffix +# transformation rules. +all: issue5a.d issue5b.c issue5c issue5d.e issue5e.d + +# Issue 6: transformation search can end up in an infinite loop +# +# There is no file or target from which issue6.f could be made from so +# this should fail. The bug was that because rules .e.f, .d.e and .e.d +# exist, make would try to make .f from .e and then infinitely try +# to do .e from .d and vice versa. +all: issue6.f + +# Issue 10: explicit dependencies affect transformation rule selection +# +# If issue10.e is wanted and both issue10.d and issue10.f are available, +# make should choose the .d.e rule, because .d is before .f in .SUFFIXES. +# The bug was that if issue10.d had an explicit dependency on issue10.f, +# it would choose .f.e instead. +all: issue10.e + +# Issue 11: sources from transformation rules are expanded incorrectly +# +# issue11.j should depend on issue11.i and issue11.second and issue11.i +# should depend on issue11.h and issue11.first. The bug was that +# the dynamic sources were expanded before ${.PREFIX} and ${.TARGET} were +# available, so they would have expanded to a null string. +all: issue11.j + +# we need to clean for repeatable results +.BEGIN: clean +clean: + @rm -f issue* .[ab]* + +.SUFFIXES: .a .b .c + +.a .a.b .b.a: + @echo 'There should be no text after the colon: ${.IMPSRC}' + touch ${.TARGET} + +.c.d .d.c .d .d.e .e.d: + @echo 'first set' + cp ${.IMPSRC} ${.TARGET} + +.SUFFIXES: +.SUFFIXES: .c .d .e .f .g + +.e .e.f .f.e: + @echo 'second set' + cp ${.IMPSRC} ${.TARGET} + +issue3.a: + @echo 'There is a bug if you see this.' + touch ${.TARGET} + +issue5a.c issue5b.d issue5c.d issue5d.d issue5e.e issue10.d issue10.f: + touch ${.TARGET} + +.SUFFIXES: .h .i .j + +.h.i: ${.PREFIX}.first + @echo '.ALLSRC: ${.ALLSRC}' + cp ${.IMPSRC} ${.TARGET} + +.i.j: ${.PREFIX}.second + @echo '.ALLSRC: ${.ALLSRC}' + cp ${.IMPSRC} ${.TARGET} + +issue11.h issue11.first issue11.second: + touch ${.TARGET} diff --git a/usr.bin/make/unit-tests/sunshcmd.exp b/usr.bin/make/unit-tests/sunshcmd.exp new file mode 100644 index 0000000..b14f6b6 --- /dev/null +++ b/usr.bin/make/unit-tests/sunshcmd.exp @@ -0,0 +1,4 @@ +TEST1=hello +TEST2=bye +TEST3=later +exit status 0 diff --git a/usr.bin/make/unit-tests/sunshcmd.mk b/usr.bin/make/unit-tests/sunshcmd.mk new file mode 100644 index 0000000..e3baf90 --- /dev/null +++ b/usr.bin/make/unit-tests/sunshcmd.mk @@ -0,0 +1,10 @@ +BYECMD = echo bye +LATERCMD = echo later +TEST1 :sh = echo hello +TEST2 :sh = ${BYECMD} +TEST3 = ${LATERCMD:sh} + +all: + @echo "TEST1=${TEST1}" + @echo "TEST2=${TEST2}" + @echo "TEST3=${TEST3}" diff --git a/usr.bin/make/unit-tests/sysv.exp b/usr.bin/make/unit-tests/sysv.exp new file mode 100644 index 0000000..4cce2de --- /dev/null +++ b/usr.bin/make/unit-tests/sysv.exp @@ -0,0 +1,7 @@ +FOOBAR = +FOOBAR = foobar fubar +fun +fun +fun +In the Sun +exit status 0 diff --git a/usr.bin/make/unit-tests/sysv.mk b/usr.bin/make/unit-tests/sysv.mk new file mode 100644 index 0000000..3651eda --- /dev/null +++ b/usr.bin/make/unit-tests/sysv.mk @@ -0,0 +1,26 @@ +# $Id: sysv.mk,v 1.2 2014/08/30 22:21:08 sjg Exp $ + +FOO ?= +FOOBAR = ${FOO:=bar} + +_this := ${.PARSEDIR}/${.PARSEFILE} + +B = /b +S = / +FUN = ${B}${S}fun +SUN = the Sun + +# we expect nothing when FOO is empty +all: foo fun + +foo: + @echo FOOBAR = ${FOOBAR} +.if empty(FOO) + @FOO="foo fu" ${.MAKE} -f ${_this} foo +.endif + +fun: + @echo ${FUN:T} + @echo ${FUN:${B}${S}fun=fun} + @echo ${FUN:${B}${S}%=%} + @echo ${In:L:%=% ${SUN}} diff --git a/usr.bin/make/unit-tests/ternary.exp b/usr.bin/make/unit-tests/ternary.exp new file mode 100644 index 0000000..ed9c1bd --- /dev/null +++ b/usr.bin/make/unit-tests/ternary.exp @@ -0,0 +1,10 @@ +The answer is unknown +The answer is unknown +The answer is empty +The answer is known +The answer is +The answer is empty +The answer is known +The answer is 42 +The answer is 42 +exit status 0 diff --git a/usr.bin/make/unit-tests/ternary.mk b/usr.bin/make/unit-tests/ternary.mk new file mode 100644 index 0000000..77f8349 --- /dev/null +++ b/usr.bin/make/unit-tests/ternary.mk @@ -0,0 +1,8 @@ + +all: + @for x in "" A= A=42; do ${.MAKE} -f ${MAKEFILE} show $$x; done + +show: + @echo "The answer is ${A:?known:unknown}" + @echo "The answer is ${A:?$A:unknown}" + @echo "The answer is ${empty(A):?empty:$A}" diff --git a/usr.bin/make/unit-tests/unexport-env.exp b/usr.bin/make/unit-tests/unexport-env.exp new file mode 100644 index 0000000..6d43cab --- /dev/null +++ b/usr.bin/make/unit-tests/unexport-env.exp @@ -0,0 +1,2 @@ +UT_TEST=unexport-env +exit status 0 diff --git a/usr.bin/make/unit-tests/unexport-env.mk b/usr.bin/make/unit-tests/unexport-env.mk new file mode 100644 index 0000000..b8192f1 --- /dev/null +++ b/usr.bin/make/unit-tests/unexport-env.mk @@ -0,0 +1,14 @@ +# $Id: unexport-env.mk,v 1.1 2014/08/21 13:44:52 apb Exp $ + +# pick up a bunch of exported vars +.include "export.mk" + +# an example of setting up a minimal environment. +PATH = /bin:/usr/bin:/sbin:/usr/sbin + +# now clobber the environment to just PATH and UT_TEST +UT_TEST = unexport-env + +# this removes everything +.unexport-env +.export PATH UT_TEST diff --git a/usr.bin/make/unit-tests/unexport.exp b/usr.bin/make/unit-tests/unexport.exp new file mode 100644 index 0000000..7b16ea3 --- /dev/null +++ b/usr.bin/make/unit-tests/unexport.exp @@ -0,0 +1,4 @@ +UT_DOLLAR=This is $UT_FU +UT_FU=fubar +UT_TEST=unexport +exit status 0 diff --git a/usr.bin/make/unit-tests/unexport.mk b/usr.bin/make/unit-tests/unexport.mk new file mode 100644 index 0000000..b3d7d34 --- /dev/null +++ b/usr.bin/make/unit-tests/unexport.mk @@ -0,0 +1,8 @@ +# $Id: unexport.mk,v 1.1 2014/08/21 13:44:52 apb Exp $ + +# pick up a bunch of exported vars +.include "export.mk" + +.unexport UT_ZOO UT_FOO + +UT_TEST = unexport diff --git a/usr.bin/make/unit-tests/varcmd.exp b/usr.bin/make/unit-tests/varcmd.exp new file mode 100644 index 0000000..7803c2b --- /dev/null +++ b/usr.bin/make/unit-tests/varcmd.exp @@ -0,0 +1,11 @@ +default FU=<v>fu</v> FOO=<v>foo</v> VAR=<v></v> +two FU=<v>bar</v> FOO=<v>goo</v> VAR=<v></v> +immutable FU='bar' +immutable FOO='goo' +three FU=<v>bar</v> FOO=<v>goo</v> VAR=<v></v> +four FU=<v>bar</v> FOO=<v>goo</v> VAR=<v>Internal</v> +five FU=<v>bar</v> FOO=<v>goo</v> VAR=<v>Internal</v> +five v=is x k=is x +six v=is y k=is y +show-v v=override k=override +exit status 0 diff --git a/usr.bin/make/unit-tests/varcmd.mk b/usr.bin/make/unit-tests/varcmd.mk new file mode 100644 index 0000000..005ed47 --- /dev/null +++ b/usr.bin/make/unit-tests/varcmd.mk @@ -0,0 +1,60 @@ +# $Id: varcmd.mk,v 1.3 2017/12/08 03:36:42 sjg Exp $ +# +# Test behaviour of recursive make and vars set on command line. + +FU=fu +FOO?=foo +.if !empty(.TARGETS) +TAG=${.TARGETS} +.endif +TAG?=default + +all: one + +show: + @echo "${TAG} FU=<v>${FU}</v> FOO=<v>${FOO}</v> VAR=<v>${VAR}</v>" + +one: show + @${.MAKE} -f ${MAKEFILE} FU=bar FOO+=goo two + +two: show + @${.MAKE} -f ${MAKEFILE} three + +three: show + @${.MAKE} -f ${MAKEFILE} four + + +.ifmake two +# this should not work +FU+= oops +FOO+= oops +_FU:= ${FU} +_FOO:= ${FOO} +two: immutable +immutable: + @echo "$@ FU='${_FU}'" + @echo "$@ FOO='${_FOO}'" +.endif +.ifmake four +VAR=Internal +.MAKEOVERRIDES+= VAR +.endif + +four: show + @${.MAKE} -f ${MAKEFILE} five + +M = x +V.y = is y +V.x = is x +V := ${V.$M} +K := ${V} + +show-v: + @echo '${TAG} v=${V} k=${K}' + +five: show show-v + @${.MAKE} -f ${MAKEFILE} M=y six + +six: show-v + @${.MAKE} -f ${MAKEFILE} V=override show-v + diff --git a/usr.bin/make/unit-tests/varmisc.exp b/usr.bin/make/unit-tests/varmisc.exp new file mode 100644 index 0000000..ffe8f8b --- /dev/null +++ b/usr.bin/make/unit-tests/varmisc.exp @@ -0,0 +1,25 @@ + +:D expanded when var set +true +TRUE +:U expanded when var undef +true +TRUE +:D skipped if var undef + +:U skipped when var set +is set +:? only lhs when value true +true +TRUE +:? only rhs when value false +false +FALSE +do not evaluate or expand :? if discarding +is set +year=2016 month=04 day=01 +date=20160401 +Version=123.456.789 == 123456789 +Literal=3.4.5 == 3004005 +We have target specific vars +exit status 0 diff --git a/usr.bin/make/unit-tests/varmisc.mk b/usr.bin/make/unit-tests/varmisc.mk new file mode 100644 index 0000000..34d32cc --- /dev/null +++ b/usr.bin/make/unit-tests/varmisc.mk @@ -0,0 +1,62 @@ +# $Id: varmisc.mk,v 1.8 2017/01/31 18:56:35 sjg Exp $ +# +# Miscellaneous variable tests. + +all: unmatched_var_paren D_true U_true D_false U_false Q_lhs Q_rhs NQ_none \ + strftime cmpv + +unmatched_var_paren: + @echo ${foo::=foo-text} + +True = ${echo true >&2:L:sh}TRUE +False= ${echo false >&2:L:sh}FALSE + +VSET= is set +.undef UNDEF + +U_false: + @echo :U skipped when var set + @echo ${VSET:U${False}} + +D_false: + @echo :D skipped if var undef + @echo ${UNDEF:D${False}} + +U_true: + @echo :U expanded when var undef + @echo ${UNDEF:U${True}} + +D_true: + @echo :D expanded when var set + @echo ${VSET:D${True}} + +Q_lhs: + @echo :? only lhs when value true + @echo ${1:L:?${True}:${False}} + +Q_rhs: + @echo :? only rhs when value false + @echo ${0:L:?${True}:${False}} + +NQ_none: + @echo do not evaluate or expand :? if discarding + @echo ${VSET:U${1:L:?${True}:${False}}} + +April1= 1459494000 + +# slightly contorted syntax to use utc via variable +strftime: + @echo ${year=%Y month=%m day=%d:L:gmtime=1459494000} + @echo date=${%Y%m%d:L:${gmtime=${April1}:L}} + +# big jumps to handle 3 digits per step +M_cmpv.units = 1 1000 1000000 +M_cmpv = S,., ,g:_:range:@i@+ $${_:[-$$i]} \* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh + +Version = 123.456.789 +cmpv.only = target specific vars + +cmpv: + @echo Version=${Version} == ${Version:${M_cmpv}} + @echo Literal=3.4.5 == ${3.4.5:L:${M_cmpv}} + @echo We have ${${.TARGET:T}.only} diff --git a/usr.bin/make/unit-tests/varquote.exp b/usr.bin/make/unit-tests/varquote.exp new file mode 100644 index 0000000..63107bf --- /dev/null +++ b/usr.bin/make/unit-tests/varquote.exp @@ -0,0 +1,3 @@ +-fdebug-prefix-map=$NETBSDSRCDIR=/usr/src -fdebug-regex-map=/usr/src/(.*)/obj$=/usr/obj/\1 +-fdebug-prefix-map=$NETBSDSRCDIR=/usr/src -fdebug-regex-map=/usr/src/(.*)/obj$=/usr/obj/\1 +exit status 0 diff --git a/usr.bin/make/unit-tests/varquote.mk b/usr.bin/make/unit-tests/varquote.mk new file mode 100644 index 0000000..fb8b106 --- /dev/null +++ b/usr.bin/make/unit-tests/varquote.mk @@ -0,0 +1,14 @@ +# $NetBSD: varquote.mk,v 1.4 2018/12/16 18:53:34 christos Exp $ +# +# Test VAR:q modifier + +.if !defined(REPROFLAGS) +REPROFLAGS+= -fdebug-prefix-map=\$$NETBSDSRCDIR=/usr/src +REPROFLAGS+= -fdebug-regex-map='/usr/src/(.*)/obj$$=/usr/obj/\1' +all: + @${MAKE} -f ${MAKEFILE} REPROFLAGS=${REPROFLAGS:S/\$/&&/g:Q} + @${MAKE} -f ${MAKEFILE} REPROFLAGS=${REPROFLAGS:q} +.else +all: + @printf "%s %s\n" ${REPROFLAGS} +.endif diff --git a/usr.bin/make/unit-tests/varshell.exp b/usr.bin/make/unit-tests/varshell.exp new file mode 100644 index 0000000..6ac8c88 --- /dev/null +++ b/usr.bin/make/unit-tests/varshell.exp @@ -0,0 +1,12 @@ +sh: /bin/no/such/command: not found +make: "varshell.mk" line 5: warning: "/bin/no/such/command" returned non-zero status +make: "varshell.mk" line 6: warning: "kill -14 $$" exited on a signal +make: "varshell.mk" line 7: warning: "false" returned non-zero status +make: "varshell.mk" line 8: warning: "echo "output before the error"; false" returned non-zero status +EXEC_FAILED='' +TERMINATED_BY_SIGNAL='' +ERROR_NO_OUTPUT='' +ERROR_WITH_OUTPUT='output before the error' +NO_ERROR_NO_OUTPUT='' +NO_ERROR_WITH_OUTPUT='this is good' +exit status 0 diff --git a/usr.bin/make/unit-tests/varshell.mk b/usr.bin/make/unit-tests/varshell.mk new file mode 100644 index 0000000..a006736 --- /dev/null +++ b/usr.bin/make/unit-tests/varshell.mk @@ -0,0 +1,18 @@ +# $Id: varshell.mk,v 1.2 2015/04/10 20:41:59 sjg Exp $ +# +# Test VAR != shell command + +EXEC_FAILED != /bin/no/such/command +TERMINATED_BY_SIGNAL != kill -14 $$$$ +ERROR_NO_OUTPUT != false +ERROR_WITH_OUTPUT != echo "output before the error"; false +NO_ERROR_NO_OUTPUT != true +NO_ERROR_WITH_OUTPUT != echo "this is good" + +allvars= EXEC_FAILED TERMINATED_BY_SIGNAL ERROR_NO_OUTPUT ERROR_WITH_OUTPUT \ + NO_ERROR_NO_OUTPUT NO_ERROR_WITH_OUTPUT + +all: +.for v in ${allvars} + @echo ${v}=\'${${v}}\' +.endfor |