| @@ -1,27 +1,30 @@ | | | @@ -1,27 +1,30 @@ |
1 | # $NetBSD: directive-include-guard.mk,v 1.1 2023/06/16 09:25:13 rillig Exp $ | | 1 | # $NetBSD: directive-include-guard.mk,v 1.2 2023/06/18 19:16:51 rillig Exp $ |
2 | # | | 2 | # |
3 | # Tests for multiple-inclusion guards in makefiles. | | 3 | # Tests for multiple-inclusion guards in makefiles. |
4 | # | | 4 | # |
5 | # A file that is guarded by a multiple-inclusion guard has the following form: | | 5 | # A file that is guarded by a multiple-inclusion guard has the following form: |
6 | # | | 6 | # |
7 | # .ifndef GUARD_NAME | | 7 | # .ifndef GUARD_NAME |
8 | # GUARD_NAME= # any value | | 8 | # GUARD_NAME= # any value |
9 | # ... | | 9 | # ... |
10 | # .endif | | 10 | # .endif |
11 | # | | 11 | # |
12 | # When such a file is included for the second time, it has no effect as all | | 12 | # When such a file is included for the second time, it has no effect, as all |
13 | # its content is skipped. | | 13 | # its content is skipped. |
14 | # | | 14 | # |
| | | 15 | # See also: |
| | | 16 | # https://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html |
| | | 17 | # |
15 | # TODO: In these cases, do not include the file, to increase performance. | | 18 | # TODO: In these cases, do not include the file, to increase performance. |
16 | | | 19 | |
17 | | | 20 | |
18 | # This is the canonical form of a multiple-inclusion guard. | | 21 | # This is the canonical form of a multiple-inclusion guard. |
19 | INCS+= guarded-ifndef | | 22 | INCS+= guarded-ifndef |
20 | LINES.guarded-ifndef= \ | | 23 | LINES.guarded-ifndef= \ |
21 | '.ifndef GUARDED_IFNDEF' \ | | 24 | '.ifndef GUARDED_IFNDEF' \ |
22 | 'GUARDED_IFNDEF=' \ | | 25 | 'GUARDED_IFNDEF=' \ |
23 | '.endif' | | 26 | '.endif' |
24 | | | 27 | |
25 | # Comments and empty lines have no influence on the multiple-inclusion guard. | | 28 | # Comments and empty lines have no influence on the multiple-inclusion guard. |
26 | INCS+= comments | | 29 | INCS+= comments |
27 | LINES.comments= \ | | 30 | LINES.comments= \ |
| @@ -56,39 +59,44 @@ LINES.varname-mismatch= \ | | | @@ -56,39 +59,44 @@ LINES.varname-mismatch= \ |
56 | 'OTHER_NAME=' \ | | 59 | 'OTHER_NAME=' \ |
57 | '.endif' | | 60 | '.endif' |
58 | | | 61 | |
59 | # The variable name in the assignment must only contain alphanumeric | | 62 | # The variable name in the assignment must only contain alphanumeric |
60 | # characters and underscores, in particular, it must not be a dynamically | | 63 | # characters and underscores, in particular, it must not be a dynamically |
61 | # computed name. | | 64 | # computed name. |
62 | INCS+= varname-indirect | | 65 | INCS+= varname-indirect |
63 | LINES.varname-indirect= \ | | 66 | LINES.varname-indirect= \ |
64 | '.ifndef VARNAME_INDIRECT' \ | | 67 | '.ifndef VARNAME_INDIRECT' \ |
65 | 'VARNAME_$${:UINDIRECT}=' \ | | 68 | 'VARNAME_$${:UINDIRECT}=' \ |
66 | '.endif' | | 69 | '.endif' |
67 | | | 70 | |
68 | # The variable assignment for the guard must directly follow the conditional. | | 71 | # The variable assignment for the guard must directly follow the conditional. |
| | | 72 | # |
| | | 73 | # This requirement may be dropped entirely later, as the guard variable could |
| | | 74 | # also be undefined while reading the file or at a later point, and as long as |
| | | 75 | # the implementation checks the guard variable before skipping the file, the |
| | | 76 | # optimization is still valid. |
69 | INCS+= late-assignment | | 77 | INCS+= late-assignment |
70 | LINES.late-assignment= \ | | 78 | LINES.late-assignment= \ |
71 | '.ifndef LATE_ASSIGNMENT' \ | | 79 | '.ifndef LATE_ASSIGNMENT' \ |
72 | 'OTHER=' \ | | 80 | 'OTHER=' \ |
73 | 'LATE_ASSIGNMENT=' \ | | 81 | 'LATE_ASSIGNMENT=' \ |
74 | '.endif' | | 82 | '.endif' |
75 | | | 83 | |
76 | # There must be no other condition between the guard condition and the | | 84 | # There must be no other condition between the guard condition and the |
77 | # variable assignment. | | 85 | # variable assignment. |
78 | INCS+= two-conditions | | 86 | INCS+= two-conditions |
79 | LINES.two-conditions= \ | | 87 | LINES.two-conditions= \ |
80 | '.ifndef TWO_CONDITIONS' \ | | 88 | '.ifndef TWO_CONDITIONS' \ |
81 | '. if 0' \ | | 89 | '. if 1' \ |
82 | 'TWO_CONDITIONS=' \ | | 90 | 'TWO_CONDITIONS=' \ |
83 | '. endif' \ | | 91 | '. endif' \ |
84 | '.endif' | | 92 | '.endif' |
85 | | | 93 | |
86 | # If the guard variable is already set before the file is included for the | | 94 | # If the guard variable is already set before the file is included for the |
87 | # first time, that file is not considered to be guarded. It's a situation | | 95 | # first time, that file is not considered to be guarded. It's a situation |
88 | # that is uncommon in practice. | | 96 | # that is uncommon in practice. |
89 | INCS+= already-set | | 97 | INCS+= already-set |
90 | LINES.already-set= \ | | 98 | LINES.already-set= \ |
91 | '.ifndef ALREADY_SET' \ | | 99 | '.ifndef ALREADY_SET' \ |
92 | 'ALREADY_SET=' \ | | 100 | 'ALREADY_SET=' \ |
93 | '.endif' | | 101 | '.endif' |
94 | ALREADY_SET= | | 102 | ALREADY_SET= |
| @@ -109,32 +117,84 @@ LINES.twice= \ | | | @@ -109,32 +117,84 @@ LINES.twice= \ |
109 | # variable names. Typical choices are ${PROJECT}_${DIR}_${FILE}_MK. | | 117 | # variable names. Typical choices are ${PROJECT}_${DIR}_${FILE}_MK. |
110 | INCS+= reuse | | 118 | INCS+= reuse |
111 | LINES.reuse= \ | | 119 | LINES.reuse= \ |
112 | ${LINES.guarded-if} | | 120 | ${LINES.guarded-if} |
113 | | | 121 | |
114 | # The conditional must come before the assignment, otherwise the conditional | | 122 | # The conditional must come before the assignment, otherwise the conditional |
115 | # is useless, as it always evaluates to false. | | 123 | # is useless, as it always evaluates to false. |
116 | INCS+= swapped | | 124 | INCS+= swapped |
117 | LINES.swapped= \ | | 125 | LINES.swapped= \ |
118 | 'SWAPPED=' \ | | 126 | 'SWAPPED=' \ |
119 | '.ifndef SWAPPED' \ | | 127 | '.ifndef SWAPPED' \ |
120 | '.endif' | | 128 | '.endif' |
121 | | | 129 | |
| | | 130 | # If the guard variable is undefined at some later point, the guarded file is |
| | | 131 | # included again. |
| | | 132 | INCS+= undef-between |
| | | 133 | LINES.undef-between= \ |
| | | 134 | '.ifndef UNDEF_BETWEEN' \ |
| | | 135 | 'UNDEF_BETWEEN=' \ |
| | | 136 | '.endif' |
| | | 137 | |
| | | 138 | # If the guarded file undefines the guard variable, the guarded file is |
| | | 139 | # included again. |
| | | 140 | INCS+= undef-inside |
| | | 141 | LINES.undef-inside= \ |
| | | 142 | '.ifndef UNDEF_INSIDE' \ |
| | | 143 | 'UNDEF_INSIDE=' \ |
| | | 144 | '.undef UNDEF_INSIDE' \ |
| | | 145 | '.endif' |
| | | 146 | |
| | | 147 | # The outermost '.if' must not have an '.elif' branch. |
| | | 148 | INCS+= if-elif |
| | | 149 | LINES.if-elif = \ |
| | | 150 | '.ifndef IF_ELIF' \ |
| | | 151 | 'IF_ELIF=' \ |
| | | 152 | '.elif 1' \ |
| | | 153 | '.endif' |
| | | 154 | |
| | | 155 | # The outermost '.if' must not have an '.else' branch. |
| | | 156 | INCS+= if-else |
| | | 157 | LINES.if-else = \ |
| | | 158 | '.ifndef IF_ELSE' \ |
| | | 159 | 'IF_ELSE=' \ |
| | | 160 | '.else' \ |
| | | 161 | '.endif' |
| | | 162 | |
| | | 163 | # The inner '.if' directives may have an '.elif' or '.else'. |
| | | 164 | INCS+= inner-if-elif-else |
| | | 165 | LINES.inner-if-elif-else = \ |
| | | 166 | '.ifndef INNER_IF_ELIF_ELSE' \ |
| | | 167 | 'INNER_IF_ELIF_ELSE=' \ |
| | | 168 | '. if 0' \ |
| | | 169 | '. elif 0' \ |
| | | 170 | '. else' \ |
| | | 171 | '. endif' \ |
| | | 172 | '. if 0' \ |
| | | 173 | '. elif 1' \ |
| | | 174 | '. else' \ |
| | | 175 | '. endif' \ |
| | | 176 | '. if 1' \ |
| | | 177 | '. elif 1' \ |
| | | 178 | '. else' \ |
| | | 179 | '. endif' \ |
| | | 180 | '.endif' |
122 | | | 181 | |
123 | # Include each of the files twice. The directive-include-guard.exp file | | 182 | # Include each of the files twice. The directive-include-guard.exp file |
124 | # contains a single entry for the files whose multiple-inclusion guard works, | | 183 | # contains a single entry for the files whose multiple-inclusion guard works, |
125 | # and two entries for the files that are not protected against multiple | | 184 | # and two entries for the files that are not protected against multiple |
126 | # inclusion. | | 185 | # inclusion. |
127 | # | | 186 | # |
128 | # Some debug output lines are suppressed in the .exp file, see ./Makefile. | | 187 | # Some debug output lines are suppressed in the .exp file, see ./Makefile. |
129 | .for i in ${INCS} | | 188 | .for i in ${INCS} |
130 | . for fname in directive-include-guard-$i.tmp | | 189 | . for fname in directive-include-guard-$i.tmp |
131 | _!= printf '%s\n' ${LINES.$i} > ${fname} | | 190 | _!= printf '%s\n' ${LINES.$i} > ${fname} |
132 | .MAKEFLAGS: -dp | | 191 | .MAKEFLAGS: -dp |
133 | .include "${.CURDIR}/${fname}" | | 192 | .include "${.CURDIR}/${fname}" |
| | | 193 | .undef ${i:Mundef-between:%=UNDEF_BETWEEN} |
134 | .include "${.CURDIR}/${fname}" | | 194 | .include "${.CURDIR}/${fname}" |
135 | .MAKEFLAGS: -d0 | | 195 | .MAKEFLAGS: -d0 |
136 | _!= rm ${fname} | | 196 | _!= rm ${fname} |
137 | . endfor | | 197 | . endfor |
138 | .endfor | | 198 | .endfor |
139 | | | 199 | |
140 | all: | | 200 | all: |