Home | History | Annotate | Line # | Download | only in unit-tests
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