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