cond-undef-lint.mk revision 1.6 1 1.6 rillig # $NetBSD: cond-undef-lint.mk,v 1.6 2025/01/11 20:16:40 rillig Exp $
2 1.1 rillig #
3 1.1 rillig # Tests for defined and undefined variables in .if conditions, in lint mode.
4 1.1 rillig #
5 1.1 rillig # As of 2020-09-14, lint mode contains experimental code for printing
6 1.1 rillig # accurate error messages in case of undefined variables, instead of the
7 1.1 rillig # wrong "Malformed condition".
8 1.2 rillig #
9 1.2 rillig # See also:
10 1.2 rillig # opt-debug-lint.mk
11 1.1 rillig
12 1.1 rillig .MAKEFLAGS: -dL
13 1.1 rillig
14 1.1 rillig # DEF is defined, UNDEF is not.
15 1.1 rillig DEF= defined
16 1.1 rillig
17 1.1 rillig # An expression based on a defined variable is fine.
18 1.1 rillig .if !${DEF}
19 1.1 rillig . error
20 1.1 rillig .endif
21 1.1 rillig
22 1.1 rillig # Since the condition fails to evaluate, neither of the branches is taken.
23 1.6 rillig # expect+2: Variable "UNDEF" is undefined
24 1.6 rillig # expect+1: Malformed conditional '${UNDEF}'
25 1.1 rillig .if ${UNDEF}
26 1.1 rillig . error
27 1.1 rillig .else
28 1.1 rillig . error
29 1.1 rillig .endif
30 1.1 rillig
31 1.1 rillig # The variable name depends on the undefined variable, which is probably a
32 1.1 rillig # mistake. The variable UNDEF, as used here, can be easily turned into
33 1.1 rillig # an expression that is always defined, using the :U modifier.
34 1.1 rillig #
35 1.1 rillig # The outer expression does not generate an error message since there was
36 1.1 rillig # already an error evaluating this variable's name.
37 1.1 rillig #
38 1.1 rillig # TODO: Suppress the error message "Variable VAR. is undefined". That part
39 1.1 rillig # of the expression must not be evaluated at all.
40 1.4 rillig # expect+3: Variable "UNDEF" is undefined
41 1.4 rillig # expect+2: Variable "VAR." is undefined
42 1.5 rillig # expect+1: Malformed conditional '${VAR.${UNDEF}}'
43 1.1 rillig .if ${VAR.${UNDEF}}
44 1.1 rillig . error
45 1.1 rillig .else
46 1.1 rillig . error
47 1.1 rillig .endif
48 1.1 rillig
49 1.1 rillig # The variable VAR.defined is not defined and thus generates an error message.
50 1.3 rillig #
51 1.3 rillig # TODO: This pattern looks a lot like CFLAGS.${OPSYS}, which is at least
52 1.3 rillig # debatable. Or would any practical use of CFLAGS.${OPSYS} be via an indirect
53 1.3 rillig # expression, as in the next example?
54 1.4 rillig # expect+2: Variable "VAR.defined" is undefined
55 1.5 rillig # expect+1: Malformed conditional '${VAR.${DEF}}'
56 1.1 rillig .if ${VAR.${DEF}}
57 1.1 rillig . error
58 1.1 rillig .else
59 1.1 rillig . error
60 1.1 rillig .endif
61 1.1 rillig
62 1.1 rillig
63 1.1 rillig # Variables that are referenced indirectly may be undefined in a condition.
64 1.1 rillig #
65 1.1 rillig # A practical example for this is CFLAGS, which consists of CWARNS, COPTS
66 1.1 rillig # and a few others. Just because these nested variables are not defined,
67 1.1 rillig # this does not make the condition invalid.
68 1.1 rillig #
69 1.1 rillig # The crucial point is that at the point where the variable appears in the
70 1.1 rillig # condition, there is no way to influence the definedness of the nested
71 1.1 rillig # variables. In particular, there is no modifier that would turn undefined
72 1.1 rillig # nested variables into empty strings, as an equivalent to the :U modifier.
73 1.1 rillig INDIRECT= ${NESTED_UNDEF} ${NESTED_DEF}
74 1.1 rillig NESTED_DEF= nested-defined
75 1.1 rillig
76 1.1 rillig # Since NESTED_UNDEF is not controllable at this point, it must not generate
77 1.2 rillig # an error message, and it doesn't do so, since 2020-09-14.
78 1.1 rillig .if !${INDIRECT}
79 1.1 rillig . error
80 1.1 rillig .endif
81