xref: /freebsd/contrib/bmake/unit-tests/directive-ifmake.mk (revision e1c4c8dd8d2d10b6104f06856a77bd5b4813a801)
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
113first second unmentioned late-target \!edge:
114	: $@
115