1# $NetBSD: directive-include-guard.mk,v 1.11 2023/06/21 21:21:52 sjg Exp $ 2# 3# Tests for multiple-inclusion guards in makefiles. 4# 5# A file that is guarded by a multiple-inclusion guard has one of the 6# following forms: 7# 8# .ifndef GUARD_VARIABLE 9# .endif 10# 11# .if !defined(GUARD_VARIABLE) 12# .endif 13# 14# .if !target(guard-target) 15# .endif 16# 17# When such a file is included for the second or later time, and the guard 18# variable or the guard target is defined, including the file has no effect, 19# as all its content is skipped. 20# 21# See also: 22# https://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html 23 24# Each of the following test cases creates a temporary file named after the 25# test case and writes some lines of text to that file. That file is then 26# included twice, to see whether the second '.include' is skipped. 27 28 29# This is the canonical form of a variable-based multiple-inclusion guard. 30INCS+= variable-ifndef 31LINES.variable-ifndef= \ 32 '.ifndef VARIABLE_IFNDEF' \ 33 'VARIABLE_IFNDEF=' \ 34 '.endif' 35# expect: Parse_PushInput: file variable-ifndef.tmp, line 1 36# expect: Skipping 'variable-ifndef.tmp' because 'VARIABLE_IFNDEF' is defined 37 38# A file that reuses a guard from a previous file (or whose guard is defined 39# for any other reason) is only processed once, to see whether it is guarded. 40# Its content is skipped, therefore the syntax error is not detected. 41INCS+= variable-ifndef-reuse 42LINES.variable-ifndef-reuse= \ 43 '.ifndef VARIABLE_IFNDEF' \ 44 'syntax error' \ 45 '.endif' 46# expect: Parse_PushInput: file variable-ifndef-reuse.tmp, line 1 47# expect: Skipping 'variable-ifndef-reuse.tmp' because 'VARIABLE_IFNDEF' is defined 48 49# Comments and empty lines do not affect the multiple-inclusion guard. 50INCS+= comments 51LINES.comments= \ 52 '\# comment' \ 53 '' \ 54 '.ifndef COMMENTS' \ 55 '\# comment' \ 56 'COMMENTS=\#comment' \ 57 '.endif' \ 58 '\# comment' 59# expect: Parse_PushInput: file comments.tmp, line 1 60# expect: Skipping 'comments.tmp' because 'COMMENTS' is defined 61 62# An alternative form uses the 'defined' function. It is more verbose than 63# the canonical form but avoids the '.ifndef' directive, as that directive is 64# not commonly used. 65INCS+= variable-if 66LINES.variable-if= \ 67 '.if !defined(VARIABLE_IF)' \ 68 'VARIABLE_IF=' \ 69 '.endif' 70# expect: Parse_PushInput: file variable-if.tmp, line 1 71# expect: Skipping 'variable-if.tmp' because 'VARIABLE_IF' is defined 72 73# A file that reuses a guard from a previous file (or whose guard is defined 74# for any other reason) is only processed once, to see whether it is guarded. 75# Its content is skipped, therefore the syntax error is not detected. 76INCS+= variable-if-reuse 77LINES.variable-if-reuse= \ 78 '.if !defined(VARIABLE_IF)' \ 79 'syntax error' \ 80 '.endif' 81# expect: Parse_PushInput: file variable-if-reuse.tmp, line 1 82# expect: Skipping 'variable-if-reuse.tmp' because 'VARIABLE_IF' is defined 83 84# Triple negation is so uncommon that it's not recognized, even though it has 85# the same effect as a single negation. 86INCS+= variable-if-triple-negation 87LINES.variable-if-triple-negation= \ 88 '.if !!!defined(VARIABLE_IF_TRIPLE_NEGATION)' \ 89 'VARIABLE_IF_TRIPLE_NEGATION=' \ 90 '.endif' 91# expect: Parse_PushInput: file variable-if-triple-negation.tmp, line 1 92# expect: Parse_PushInput: file variable-if-triple-negation.tmp, line 1 93 94# A conditional other than '.if' or '.ifndef' does not guard the file, even if 95# it is otherwise equivalent to the above accepted forms. 96INCS+= variable-ifdef-negated 97LINES.variable-ifdef-negated= \ 98 '.ifdef !VARIABLE_IFDEF_NEGATED' \ 99 'VARIABLE_IFDEF_NEGATED=' \ 100 '.endif' 101# expect: Parse_PushInput: file variable-ifdef-negated.tmp, line 1 102# expect: Parse_PushInput: file variable-ifdef-negated.tmp, line 1 103 104# The variable names in the '.if' and the assignment must be the same. 105INCS+= variable-name-mismatch 106LINES.variable-name-mismatch= \ 107 '.ifndef VARIABLE_NAME_MISMATCH' \ 108 'VARIABLE_NAME_DIFFERENT=' \ 109 '.endif' 110# expect: Parse_PushInput: file variable-name-mismatch.tmp, line 1 111# expect: Parse_PushInput: file variable-name-mismatch.tmp, line 1 112 113# The variable name '!VARNAME' cannot be used in an '.ifndef' directive, as 114# the '!' would be a negation. It is syntactically valid in a '.if !defined' 115# condition, but ignored there. Furthermore, when defining the variable, the 116# character '!' has to be escaped, to prevent it from being interpreted as the 117# '!' dependency operator. 118INCS+= variable-name-exclamation 119LINES.variable-name-exclamation= \ 120 '.if !defined(!VARIABLE_NAME_EXCLAMATION)' \ 121 '${:U!}VARIABLE_NAME_EXCLAMATION=' \ 122 '.endif' 123# expect: Parse_PushInput: file variable-name-exclamation.tmp, line 1 124# expect: Parse_PushInput: file variable-name-exclamation.tmp, line 1 125 126# A variable name can contain a '!' in the middle, as that character is 127# interpreted as an ordinary character in conditions as well as on the left 128# side of a variable assignment. For guard variable names, the '!' is not 129# supported in any place, though. 130INCS+= variable-name-exclamation-middle 131LINES.variable-name-exclamation-middle= \ 132 '.ifndef VARIABLE_NAME!MIDDLE' \ 133 'VARIABLE_NAME!MIDDLE=' \ 134 '.endif' 135# expect: Parse_PushInput: file variable-name-exclamation-middle.tmp, line 1 136# expect: Parse_PushInput: file variable-name-exclamation-middle.tmp, line 1 137 138# A variable name can contain balanced parentheses, at least in conditions and 139# on the left side of a variable assignment. There are enough places in make 140# where parentheses or braces are handled inconsistently to make this naming 141# choice a bad idea, therefore these characters are not allowed in guard 142# variable names. 143INCS+= variable-name-parentheses 144LINES.variable-name-parentheses= \ 145 '.ifndef VARIABLE_NAME(&)PARENTHESES' \ 146 'VARIABLE_NAME(&)PARENTHESES=' \ 147 '.endif' 148# expect: Parse_PushInput: file variable-name-parentheses.tmp, line 1 149# expect: Parse_PushInput: file variable-name-parentheses.tmp, line 1 150 151# The guard condition must consist of only the guard variable, nothing else. 152INCS+= variable-ifndef-plus 153LINES.variable-ifndef-plus= \ 154 '.ifndef VARIABLE_IFNDEF_PLUS && VARIABLE_IFNDEF_SECOND' \ 155 'VARIABLE_IFNDEF_PLUS=' \ 156 'VARIABLE_IFNDEF_SECOND=' \ 157 '.endif' 158# expect: Parse_PushInput: file variable-ifndef-plus.tmp, line 1 159# expect: Parse_PushInput: file variable-ifndef-plus.tmp, line 1 160 161# The guard condition must consist of only the guard variable, nothing else. 162INCS+= variable-if-plus 163LINES.variable-if-plus= \ 164 '.if !defined(VARIABLE_IF_PLUS) && !defined(VARIABLE_IF_SECOND)' \ 165 'VARIABLE_IF_PLUS=' \ 166 'VARIABLE_IF_SECOND=' \ 167 '.endif' 168# expect: Parse_PushInput: file variable-if-plus.tmp, line 1 169# expect: Parse_PushInput: file variable-if-plus.tmp, line 1 170 171# The variable name in an '.ifndef' guard must be given directly, it must not 172# contain any '$' expression. 173INCS+= variable-ifndef-indirect 174LINES.variable-ifndef-indirect= \ 175 '.ifndef $${VARIABLE_IFNDEF_INDIRECT:L}' \ 176 'VARIABLE_IFNDEF_INDIRECT=' \ 177 '.endif' 178# expect: Parse_PushInput: file variable-ifndef-indirect.tmp, line 1 179# expect: Parse_PushInput: file variable-ifndef-indirect.tmp, line 1 180 181# The variable name in an '.if' guard must be given directly, it must not 182# contain any '$' expression. 183INCS+= variable-if-indirect 184LINES.variable-if-indirect= \ 185 '.if !defined($${VARIABLE_IF_INDIRECT:L})' \ 186 'VARIABLE_IF_INDIRECT=' \ 187 '.endif' 188# expect: Parse_PushInput: file variable-if-indirect.tmp, line 1 189# expect: Parse_PushInput: file variable-if-indirect.tmp, line 1 190 191# The variable name in the guard condition must only contain alphanumeric 192# characters and underscores. The guard variable is more flexible, it can be 193# defined anywhere, as long as it is defined at the point where the file is 194# included the next time. 195INCS+= variable-assign-indirect 196LINES.variable-assign-indirect= \ 197 '.ifndef VARIABLE_ASSIGN_INDIRECT' \ 198 '$${VARIABLE_ASSIGN_INDIRECT:L}=' \ 199 '.endif' 200# expect: Parse_PushInput: file variable-assign-indirect.tmp, line 1 201# expect: Skipping 'variable-assign-indirect.tmp' because 'VARIABLE_ASSIGN_INDIRECT' is defined 202 203# The time at which the guard variable is defined doesn't matter, as long as 204# it is defined at the point where the file is included the next time. 205INCS+= variable-assign-late 206LINES.variable-assign-late= \ 207 '.ifndef VARIABLE_ASSIGN_LATE' \ 208 'VARIABLE_ASSIGN_LATE_OTHER=' \ 209 'VARIABLE_ASSIGN_LATE=' \ 210 '.endif' 211# expect: Parse_PushInput: file variable-assign-late.tmp, line 1 212# expect: Skipping 'variable-assign-late.tmp' because 'VARIABLE_ASSIGN_LATE' is defined 213 214# The time at which the guard variable is defined doesn't matter, as long as 215# it is defined at the point where the file is included the next time. 216INCS+= variable-assign-nested 217LINES.variable-assign-nested= \ 218 '.ifndef VARIABLE_ASSIGN_NESTED' \ 219 '. if 1' \ 220 '. for i in once' \ 221 'VARIABLE_ASSIGN_NESTED=' \ 222 '. endfor' \ 223 '. endif' \ 224 '.endif' 225# expect: Parse_PushInput: file variable-assign-nested.tmp, line 1 226# expect: Skipping 'variable-assign-nested.tmp' because 'VARIABLE_ASSIGN_NESTED' is defined 227 228# If the guard variable is defined before the file is included for the first 229# time, the file is considered guarded as well. In such a case, the parser 230# skips almost all lines, as they are irrelevant, but the structure of the 231# top-level '.if/.endif' conditional can be determined reliably enough to 232# decide whether the file is guarded. 233INCS+= variable-already-defined 234LINES.variable-already-defined= \ 235 '.ifndef VARIABLE_ALREADY_DEFINED' \ 236 'VARIABLE_ALREADY_DEFINED=' \ 237 '.endif' 238VARIABLE_ALREADY_DEFINED= 239# expect: Parse_PushInput: file variable-already-defined.tmp, line 1 240# expect: Skipping 'variable-already-defined.tmp' because 'VARIABLE_ALREADY_DEFINED' is defined 241 242# If the guard variable is defined before the file is included the first time, 243# the file is processed but its content is skipped. If that same guard 244# variable is undefined when the file is included the second time, the file is 245# processed as usual. 246INCS+= variable-defined-then-undefined 247LINES.variable-defined-then-undefined= \ 248 '.ifndef VARIABLE_DEFINED_THEN_UNDEFINED' \ 249 '.endif' 250VARIABLE_DEFINED_THEN_UNDEFINED= 251UNDEF_BETWEEN.variable-defined-then-undefined= \ 252 VARIABLE_DEFINED_THEN_UNDEFINED 253# expect: Parse_PushInput: file variable-defined-then-undefined.tmp, line 1 254# expect: Parse_PushInput: file variable-defined-then-undefined.tmp, line 1 255 256# The whole file content must be guarded by a single '.if' conditional, not by 257# several, even if they have the same effect. This case is not expected to 258# occur in practice, as the two parts would rather be split into separate 259# files. 260INCS+= variable-two-times 261LINES.variable-two-times= \ 262 '.ifndef VARIABLE_TWO_TIMES_1' \ 263 'VARIABLE_TWO_TIMES_1=' \ 264 '.endif' \ 265 '.ifndef VARIABLE_TWO_TIMES_2' \ 266 'VARIABLE_TWO_TIMES_2=' \ 267 '.endif' 268# expect: Parse_PushInput: file variable-two-times.tmp, line 1 269# expect: Parse_PushInput: file variable-two-times.tmp, line 1 270 271# When multiple files use the same guard variable name, the optimization of 272# skipping the file affects each of these files. 273# 274# Choosing unique guard names is the responsibility of the makefile authors. 275# A typical pattern of guard variable names is '${PROJECT}_${DIR}_${FILE}_MK'. 276# System-provided files typically start the guard names with '_'. 277INCS+= variable-clash 278LINES.variable-clash= \ 279 ${LINES.variable-if} 280# expect: Parse_PushInput: file variable-clash.tmp, line 1 281# expect: Skipping 'variable-clash.tmp' because 'VARIABLE_IF' is defined 282 283# The conditional must come before the assignment, otherwise the conditional 284# is useless, as it always evaluates to false. 285INCS+= variable-swapped 286LINES.variable-swapped= \ 287 'SWAPPED=' \ 288 '.ifndef SWAPPED' \ 289 '. error' \ 290 '.endif' 291# expect: Parse_PushInput: file variable-swapped.tmp, line 1 292# expect: Parse_PushInput: file variable-swapped.tmp, line 1 293 294# If the guard variable is undefined between the first and the second time the 295# file is included, the guarded file is included again. 296INCS+= variable-undef-between 297LINES.variable-undef-between= \ 298 '.ifndef VARIABLE_UNDEF_BETWEEN' \ 299 'VARIABLE_UNDEF_BETWEEN=' \ 300 '.endif' 301UNDEF_BETWEEN.variable-undef-between= \ 302 VARIABLE_UNDEF_BETWEEN 303# expect: Parse_PushInput: file variable-undef-between.tmp, line 1 304# expect: Parse_PushInput: file variable-undef-between.tmp, line 1 305 306# If the guard variable is undefined while the file is included the first 307# time, the guard does not have an effect, and the file is included again. 308INCS+= variable-undef-inside 309LINES.variable-undef-inside= \ 310 '.ifndef VARIABLE_UNDEF_INSIDE' \ 311 'VARIABLE_UNDEF_INSIDE=' \ 312 '.undef VARIABLE_UNDEF_INSIDE' \ 313 '.endif' 314# expect: Parse_PushInput: file variable-undef-inside.tmp, line 1 315# expect: Parse_PushInput: file variable-undef-inside.tmp, line 1 316 317# If the file does not define the guard variable, the guard does not have an 318# effect, and the file is included again. 319INCS+= variable-not-defined 320LINES.variable-not-defined= \ 321 '.ifndef VARIABLE_NOT_DEFINED' \ 322 '.endif' 323# expect: Parse_PushInput: file variable-not-defined.tmp, line 1 324# expect: Parse_PushInput: file variable-not-defined.tmp, line 1 325 326# The outermost '.if' must not have an '.elif' branch. 327INCS+= if-elif 328LINES.if-elif= \ 329 '.ifndef IF_ELIF' \ 330 'IF_ELIF=' \ 331 '.elif 1' \ 332 '.endif' 333# expect: Parse_PushInput: file if-elif.tmp, line 1 334# expect: Parse_PushInput: file if-elif.tmp, line 1 335 336# When a file with an '.if/.elif/.endif' conditional at the top level is 337# included, it is never optimized, as one of its branches is taken. 338INCS+= if-elif-reuse 339LINES.if-elif-reuse= \ 340 '.ifndef IF_ELIF' \ 341 'syntax error' \ 342 '.elif 1' \ 343 '.endif' 344# expect: Parse_PushInput: file if-elif-reuse.tmp, line 1 345# expect: Parse_PushInput: file if-elif-reuse.tmp, line 1 346 347# The outermost '.if' must not have an '.else' branch. 348INCS+= if-else 349LINES.if-else= \ 350 '.ifndef IF_ELSE' \ 351 'IF_ELSE=' \ 352 '.else' \ 353 '.endif' 354# expect: Parse_PushInput: file if-else.tmp, line 1 355# expect: Parse_PushInput: file if-else.tmp, line 1 356 357# When a file with an '.if/.else/.endif' conditional at the top level is 358# included, it is never optimized, as one of its branches is taken. 359INCS+= if-else-reuse 360LINES.if-else-reuse= \ 361 '.ifndef IF_ELSE' \ 362 'syntax error' \ 363 '.else' \ 364 '.endif' 365# expect: Parse_PushInput: file if-else-reuse.tmp, line 1 366# expect: Parse_PushInput: file if-else-reuse.tmp, line 1 367 368# The inner '.if' directives may have an '.elif' or '.else', and it doesn't 369# matter which of their branches are taken. 370INCS+= inner-if-elif-else 371LINES.inner-if-elif-else= \ 372 '.ifndef INNER_IF_ELIF_ELSE' \ 373 'INNER_IF_ELIF_ELSE=' \ 374 '. if 0' \ 375 '. elif 0' \ 376 '. else' \ 377 '. endif' \ 378 '. if 0' \ 379 '. elif 1' \ 380 '. else' \ 381 '. endif' \ 382 '. if 1' \ 383 '. elif 1' \ 384 '. else' \ 385 '. endif' \ 386 '.endif' 387# expect: Parse_PushInput: file inner-if-elif-else.tmp, line 1 388# expect: Skipping 'inner-if-elif-else.tmp' because 'INNER_IF_ELIF_ELSE' is defined 389 390# The guard can also be a target instead of a variable. Using a target as a 391# guard has the benefit that a target cannot be undefined once it is defined. 392# The target should be declared '.NOTMAIN'. Since the target names are 393# usually chosen according to a pattern that doesn't interfere with real 394# target names, they don't need to be declared '.PHONY' as they don't generate 395# filesystem operations. 396INCS+= target 397LINES.target= \ 398 '.if !target(__target.tmp__)' \ 399 '__target.tmp__: .NOTMAIN' \ 400 '.endif' 401# expect: Parse_PushInput: file target.tmp, line 1 402# expect: Skipping 'target.tmp' because '__target.tmp__' is defined 403 404# When used for system files, the target name may include '<' and '>', for 405# symmetry with the '.include <sys.mk>' directive. The characters '<' and '>' 406# are ordinary characters. 407INCS+= target-sys 408LINES.target-sys= \ 409 '.if !target(__<target-sys.tmp>__)' \ 410 '__<target-sys.tmp>__: .NOTMAIN' \ 411 '.endif' 412# expect: Parse_PushInput: file target-sys.tmp, line 1 413# expect: Skipping 'target-sys.tmp' because '__<target-sys.tmp>__' is defined 414 415# The target name may include variable references. These references are 416# expanded as usual. Due to the current implementation, the expressions are 417# evaluated twice: Once for checking whether the condition evaluates to true, 418# and once for determining the guard name. This double evaluation should not 419# matter in practice, as guard expressions are expected to be simple, 420# deterministic and without side effects. 421INCS+= target-indirect 422LINES.target-indirect= \ 423 '.if !target($${target-indirect.tmp:L})' \ 424 'target-indirect.tmp: .NOTMAIN' \ 425 '.endif' 426# expect: Parse_PushInput: file target-indirect.tmp, line 1 427# expect: Skipping 'target-indirect.tmp' because 'target-indirect.tmp' is defined 428 429# A common form of guard target is __${.PARSEFILE}__. This form can only be 430# used if all files using this form have unique basenames. To get a robust 431# pattern based on the same idea, use __${.PARSEDIR}/${.PARSEFILE}__ instead. 432# This form does not work when the basename contains whitespace characters, as 433# it is not possible to define a target with whitespace, not even by cheating. 434INCS+= target-indirect-PARSEFILE 435LINES.target-indirect-PARSEFILE= \ 436 '.if !target(__$${.PARSEFILE}__)' \ 437 '__$${.PARSEFILE}__: .NOTMAIN' \ 438 '.endif' 439# expect: Parse_PushInput: file target-indirect-PARSEFILE.tmp, line 1 440# expect: Skipping 'target-indirect-PARSEFILE.tmp' because '__target-indirect-PARSEFILE.tmp__' is defined 441 442# Two files with different basenames can both use the same syntactic pattern 443# for the target guard name, as the expressions expand to different strings. 444INCS+= target-indirect-PARSEFILE2 445LINES.target-indirect-PARSEFILE2= \ 446 '.if !target(__$${.PARSEFILE}__)' \ 447 '__$${.PARSEFILE}__: .NOTMAIN' \ 448 '.endif' 449# expect: Parse_PushInput: file target-indirect-PARSEFILE2.tmp, line 1 450# expect: Skipping 'target-indirect-PARSEFILE2.tmp' because '__target-indirect-PARSEFILE2.tmp__' is defined 451 452# Using plain .PARSEFILE without .PARSEDIR leads to name clashes. The include 453# guard is the same as in the test case 'target-indirect-PARSEFILE', as the 454# guard name only contains the basename but not the directory name. 455INCS+= subdir/target-indirect-PARSEFILE 456LINES.subdir/target-indirect-PARSEFILE= \ 457 '.if !target(__$${.PARSEFILE}__)' \ 458 '__$${.PARSEFILE}__: .NOTMAIN' \ 459 '.endif' 460# expect: Parse_PushInput: file subdir/target-indirect-PARSEFILE.tmp, line 1 461# expect: Skipping 'subdir/target-indirect-PARSEFILE.tmp' because '__target-indirect-PARSEFILE.tmp__' is defined 462 463# Another common form of guard target is __${.PARSEDIR}/${.PARSEFILE}__ 464# or __${.PARSEDIR:tA}/${.PARSEFILE}__ to be truely unique. 465INCS+= target-indirect-PARSEDIR-PARSEFILE 466LINES.target-indirect-PARSEDIR-PARSEFILE= \ 467 '.if !target(__$${.PARSEDIR}/$${.PARSEFILE}__)' \ 468 '__$${.PARSEDIR}/$${.PARSEFILE}__: .NOTMAIN' \ 469 '.endif' 470# expect: Parse_PushInput: file target-indirect-PARSEDIR-PARSEFILE.tmp, line 1 471# expect: Skipping 'target-indirect-PARSEDIR-PARSEFILE.tmp' because '__target-indirect-PARSEDIR-PARSEFILE.tmp__' is defined 472# The actual target starts with '__${.OBJDIR}/', see the .rawout file, but the 473# string '${.OBJDIR}/' gets stripped in post processing. 474 475# Using the combination of '.PARSEDIR' and '.PARSEFILE', a file in a 476# subdirectory gets a different guard target name than the previous one. 477INCS+= subdir/target-indirect-PARSEDIR-PARSEFILE 478LINES.subdir/target-indirect-PARSEDIR-PARSEFILE= \ 479 '.if !target(__$${.PARSEDIR}/$${.PARSEFILE}__)' \ 480 '__$${.PARSEDIR}/$${.PARSEFILE}__: .NOTMAIN' \ 481 '.endif' 482# expect: Parse_PushInput: file subdir/target-indirect-PARSEDIR-PARSEFILE.tmp, line 1 483# expect: Skipping 'subdir/target-indirect-PARSEDIR-PARSEFILE.tmp' because '__subdir/target-indirect-PARSEDIR-PARSEFILE.tmp__' is defined 484# The actual target starts with '__${.OBJDIR}/', see the .rawout file, but the 485# string '${.OBJDIR}/' gets stripped in post processing. 486 487# If the guard target is not defined when including the file the next time, 488# the file is processed again. 489INCS+= target-unguarded 490LINES.target-unguarded= \ 491 '.if !target(target-unguarded)' \ 492 '.endif' 493# expect: Parse_PushInput: file target-unguarded.tmp, line 1 494# expect: Parse_PushInput: file target-unguarded.tmp, line 1 495 496# The guard condition must consist of only the guard target, nothing else. 497INCS+= target-plus 498LINES.target-plus= \ 499 '.if !target(target-plus) && 1' \ 500 'target-plus: .NOTMAIN' \ 501 '.endif' 502# expect: Parse_PushInput: file target-plus.tmp, line 1 503# expect: Parse_PushInput: file target-plus.tmp, line 1 504 505# If the guard target is defined before the file is included the first time, 506# the file is not considered guarded. 507INCS+= target-already-defined 508LINES.target-already-defined= \ 509 '.if !target(target-already-defined)' \ 510 'target-already-defined: .NOTMAIN' \ 511 '.endif' 512target-already-defined: .NOTMAIN 513# expect: Parse_PushInput: file target-already-defined.tmp, line 1 514# expect: Skipping 'target-already-defined.tmp' because 'target-already-defined' is defined 515 516# A target name cannot contain the character '!'. In the condition, the '!' 517# is syntactically valid, but in the dependency declaration line, the '!' is 518# interpreted as the '!' dependency operator, no matter whether it occurs at 519# the beginning or in the middle of a target name. Escaping it as '${:U!}' 520# doesn't work, as the whole line is first expanded and then scanned for the 521# dependency operator. Escaping it as '\!' doesn't work either, even though 522# the '\' escapes the '!' from being a dependency operator, but when reading 523# the target name, the '\' is kept, resulting in the target name 524# '\!target-name-exclamation' instead of '!target-name-exclamation'. 525INCS+= target-name-exclamation 526LINES.target-name-exclamation= \ 527 '.if !target(!target-name-exclamation)' \ 528 '\!target-name-exclamation: .NOTMAIN' \ 529 '.endif' 530# expect: Parse_PushInput: file target-name-exclamation.tmp, line 1 531# expect: Parse_PushInput: file target-name-exclamation.tmp, line 1 532 533# Now run all test cases by including each of the files twice and looking at 534# the debug output. The files that properly guard against multiple inclusion 535# generate a 'Skipping' line, the others repeat the 'Parse_PushInput' line. 536# 537# Some debug output lines are suppressed in the .exp file, see ./Makefile. 538.for i in ${INCS} 539. for fname in $i.tmp 540_:= ${fname:H:N.:@dir@${:!mkdir -p ${dir}!}@} 541_!= printf '%s\n' ${LINES.$i} > ${fname} 542.MAKEFLAGS: -dp 543.include "${.CURDIR}/${fname}" 544.undef ${UNDEF_BETWEEN.$i:U} 545.include "${.CURDIR}/${fname}" 546.MAKEFLAGS: -d0 547_!= rm ${fname} 548_:= ${fname:H:N.:@dir@${:!rmdir ${dir}!}@} 549. endfor 550.endfor 551 552all: 553