...

Text file src/github.com/emissary-ingress/emissary/v3/DevDocumentation/gnu-make.md

Documentation: github.com/emissary-ingress/emissary/v3/DevDocumentation

     1A quick primer on GNU Make syntax
     2=================================
     3
     4This tries to cover the syntax that is hard to ctrl-f for in
     5<https://www.gnu.org/software/make/manual/make.html> (err, hard to
     6C-s for in `M-: (info "Make")`).
     7
     8  At the core is a "rule":
     9
    10      target: dependency1 dependency2
    11      	command to run
    12
    13  If `target` something that isn't a real file (like 'build', 'lint', or
    14  'test'), then it should be marked as "phony":
    15
    16      target: dependency1 dependency2
    17      	command to run
    18      .PHONY: target
    19
    20  You can write reusable "pattern" rules:
    21
    22      %.o: %.c
    23      	command to run
    24
    25  Of course, if you don't have variables for the inputs and outputs,
    26  it's hard to write a "command to run" for a pattern rule.  The
    27  variables that you should know are:
    28
    29      $@ = the target
    30      $^ = the list of dependencies (space separated)
    31      $< = the first (left-most) dependency
    32      $* = the value of the % glob in a pattern rule
    33
    34      Each of these have $(@D) and $(@F) variants that are the
    35      directory-part and file-part of each value, respectively.
    36
    37      I think those are easy enough to remember mnemonically:
    38        - $@ is where you should direct the output at.
    39        - $^ points up at the dependency list
    40        - $< points at the left-most member of the dependency list
    41        - $* is the % glob; "*" is well-known as the glob char in other languages
    42
    43  Make will do its best to guess whether to apply a pattern rule for a
    44  given file.  Or, you can explicitly tell it by using a 3-field
    45  (2-colon) version:
    46
    47      foo.o bar.o: %.o: %.c
    48      	command to run
    49
    50  In a non-pattern rule, if there are multiple targets listed, then it
    51  is as if rule were duplicated for each target:
    52
    53      target1 target2: deps
    54      	command to run
    55
    56      # is the same as
    57
    58      target1: deps
    59      	command to run
    60      target2: deps
    61      	command to run
    62
    63  Because of this, if you have a command that generates multiple
    64  outputs, it _must_ be a pattern rule:
    65
    66      %.c %.h: %.y
    67      	command to run
    68
    69  Normally, Make crawls the entire tree of dependencies, updating a file
    70  if any of its dependencies have been updated.  There's a really poorly
    71  named feature called "order-only" dependencies:
    72
    73      target: normal-deps | order-only-deps
    74
    75  Dependencies after the `|` are created if they don't exist, but if
    76  they already exist, then don't bother updating them.
    77
    78Tips:
    79-----
    80
    81 - Use absolute filenames; it's silly, but can often reduce headaches.
    82   Use `$(OSS_HOME)` to spell the absolute filenames.
    83
    84   Though, this isn't so helpful in Emissary anymore.  The main case
    85   where this helps is when the same directory-specific Makefile might
    86   be `include`d from several different top-level directories; as the
    87   Helm chart Makefile used to be from the main Emissary Makefile, or
    88   the Emissary Makefile used to be from Edge Stack.  But Emissary no
    89   longer does this.
    90
    91 - If you have a multiple-output command where the output files have
    92   dissimilar names, have `%` be just the directory (the above tip
    93   about using absolute filenames makes this easier--this is a real
    94   pain if you have such a target in the top-level directory and
    95   aren't using absolute filenames).
    96
    97 - It can be useful to use the 2-colon form of a pattern rule when
    98   writing a rule for just one file; it lets you use `%` and `$*` to
    99   avoid repeating yourself, which can be especially useful with long
   100   filenames.

View as plain text