xref: /freebsd/contrib/bmake/unit-tests/directive-ifmake.mk (revision 833a452e9f082a7982a31c21f0da437dbbe0a39d)
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
106first second unmentioned late-target \!edge:
107	: $@
108