directive-ifmake.mk revision 1.9 1 # $NetBSD: directive-ifmake.mk,v 1.9 2022/01/22 16:23:56 rillig Exp $
2 #
3 # Tests for the .ifmake directive, which provides a shortcut for asking
4 # whether a certain target is requested to be made from the command line.
5 #
6 # TODO: Describe why the shortcut may be useful (if it's useful at all),
7 # instead of using the more versatile '.if make(target)'.
8
9 .MAKEFLAGS: first second
10
11 # This is the most basic form.
12 .ifmake first
13 . info ok: positive condition works
14 .else
15 . warning positive condition fails
16 .endif
17
18 # The '!' is interpreted as 'not'. A possible alternative interpretation of
19 # this condition is whether the target named "!first" was requested. To
20 # distinguish these cases, see the next test.
21 .ifmake !first
22 . warning unexpected
23 .else
24 . info ok: negation works
25 .endif
26
27 # See if the exclamation mark really means "not", or if it is just part of
28 # the target name. Since it means 'not', the two exclamation marks are
29 # effectively ignored, and 'first' is indeed a requested target. If the
30 # exclamation mark were part of the name instead, the name would be '!!first',
31 # and such a target was not requested to be made.
32 .ifmake !!first
33 . info ok: double negation works
34 .else
35 . warning double negation fails
36 .endif
37
38 # Multiple targets can be combined using the && and || operators.
39 .ifmake first && second
40 . info ok: both mentioned
41 .else
42 . warning && does not work as expected
43 .endif
44
45 # Negation also works in complex conditions.
46 .ifmake first && !unmentioned
47 . info ok: only those mentioned
48 .else
49 . warning && with ! does not work as expected
50 .endif
51
52 # Using the .MAKEFLAGS special dependency target, arbitrary command
53 # line options can be added at parse time. This means that it is
54 # possible to extend the targets to be made.
55 .MAKEFLAGS: late-target
56 .ifmake late-target
57 . info Targets can even be added at parse time.
58 .else
59 . info No, targets cannot be added at parse time anymore.
60 .endif
61
62 # Numbers are interpreted as numbers, no matter whether the directive is
63 # a plain .if or an .ifmake.
64 .ifmake 0
65 . error
66 .endif
67 .ifmake 1
68 .else
69 . error
70 .endif
71
72 # A condition that consists of a variable expression only (without any
73 # comparison operator) can be used with .if and the other .ifxxx directives.
74 .ifmake ${:Ufirst}
75 . info ok
76 .else
77 . error
78 .endif
79
80
81 # As an edge case, a target can actually be named "!first" on the command
82 # line. There is no way to define a target of this name though since in a
83 # dependency line, a plain '!' is interpreted as a dependency operator.
84
85 .MAKEFLAGS: !edge
86 .ifmake edge
87 . error
88 .endif
89
90 # The '\!edge' in the following condition is parsed as a bare word. For such
91 # a bare word, there is no escaping mechanism so the backslash passes through.
92 # Since the condition function 'make' accepts a pattern instead of a plain
93 # target name, the '\' is finally discarded in Str_Match.
94 .ifmake \!edge
95 .else
96 . error
97 .endif
98
99 # In a dependency line, a plain '!' is interpreted as a dependency operator
100 # (the other two are ':' and '::'). If the '!' is escaped by a '\', as
101 # implemented in ParseDependencyTargetWord, the additional backslash is never
102 # removed though. The target name thus becomes '\!edge' instead of the
103 # intended '!edge'. Defining a target whose name contains a '!' will either
104 # require additional tricks, or it may even be impossible.
105
106 first second unmentioned late-target \!edge:
107 : $@
108