github.com/zyedidia/knit@v1.1.2-0.20230901152954-f7d4e39a0e24/docs/knit.md (about)

     1  ## Rules
     2  
     3  A rule consists of four parts:
     4  
     5  * Targets: a list of values that are generated by this rule.
     6  * Prereqs: a list of values that must be generated before this rule can be
     7    executed.
     8  * Attributes: a list of flags that customize how this rule is interpreted.
     9  * Recipe: a list of commands that are run to execute the rule.
    10  
    11  The syntax for a rule is
    12  
    13  ```
    14  targets:attributes: prereqs
    15      recipe
    16  ```
    17  
    18  If the rule has no attributes, it may be omitted, leaving just `targets:
    19  prereqs` on the first line.
    20  
    21  When a rule is embedded in Lua, it is prefixed with a `$`:
    22  
    23  ```
    24  $ targets:attributes: prereqs
    25      recipe
    26  ```
    27  
    28  The rule continues until it is de-indented to the original indentation of the
    29  `$`.
    30  
    31  Direct rules are rules where the targets and prereqs are explicit names of
    32  values. For example,
    33  
    34  ```
    35  foo.o: foo.c
    36      gcc -c foo.c -o foo.o
    37  ```
    38  
    39  Specifies that the file `foo.o` is built from `foo.c`, using the command `gcc
    40  -c foo.c -o foo.o`.
    41  
    42  Within a rule, `#` denotes the start of a comment. Outside of rules, `--` is
    43  the start of a comment (the standard Lua syntax).
    44  
    45  ### Meta rules
    46  
    47  A meta rule is a special rule that describes a generic way to create direct
    48  rules.  The meta rule describes how to match targets and prereqs into a direct
    49  rule.  For example, a `%` meta rule uses `%` to match any sequence of
    50  characters.
    51  
    52  Thus the meta rule
    53  
    54  ```
    55  %.o: %.c
    56      ...
    57  ```
    58  
    59  describes that a direct rule
    60  
    61  ```
    62  foo.o: foo.c
    63      ...
    64  ```
    65  
    66  could be created. This direct rule would be created if another rule needed
    67  `foo.o` to be generated.
    68  
    69  Meta rules may also specify the match by using regular expressions, if the `R`
    70  attribute is provided. For example:
    71  
    72  ```
    73  foo-(.*)-(.*).tar.gz:R: $1/$2/foo
    74      ...
    75  ```
    76  
    77  could create a direct rule
    78  
    79  ```
    80  foo-linux-amd64.tar.gz: linux/amd64/foo
    81      ...
    82  ```
    83  
    84  ### Attributes
    85  
    86  Knit supports the following attributes:
    87  
    88  * `Q` (quiet): do not print this rule's recipe when executing.
    89  * `R` (regex): this meta rule uses regular expression matching.
    90  * `V` (virtual): the value this rule generates is not a file, just a name.
    91  * `M` (no meta): this rule's targets cannot be matched by meta rules.
    92  * `E` (non-stop): this rule does not stop if one of its commands fails.
    93  * `B` (build): this rule must always be built (it is always out-of-date).
    94  * `L` (linked): this rule always runs if an out-of-date sub-rule requires it as
    95    a prereq.
    96  * `O` (order-only): this rule's prereqs are not considered automatically
    97    up-to-date even if this rule is up-to-date.
    98  * `D[depfile]` (dependency): include `depfile` as an additional list of
    99    dependencies for this rule.
   100  
   101  The `D` attribute takes an argument. It is used for including `.d` files for
   102  C headers. For example, this rule
   103  
   104  ```
   105  $ %.o:D[%.d]: %.c
   106      gcc -MMD -c $input -o $output
   107  ```
   108  
   109  specifies that it should read the file `%.d` as a rule file and include any
   110  additional rules (without recipes) as dependencies for the current rule. If the
   111  file does not exist it is ignored, and any rules from the file that can't be
   112  satisfied are ignored instead of returned as errors.
   113  
   114  Attributes can also be applied to particular prerequisites rather than to an
   115  entire rule, using the syntax `prereq[attributes]`. For example:
   116  
   117  ```
   118  foo:V:
   119      echo foo
   120  bar:V: foo[Q]
   121      echo bar
   122  ```
   123  
   124  The `foo` rule will be quiet only when used as a prerequisite to the `bar`
   125  rule.
   126  
   127  Some attributes can only be applied in this way:
   128  
   129  * `I` (implicit): this prereq does not appear in `$input`.
   130  
   131  The `[...][attributes]` syntax can be used to apply attributes to groups of
   132  prerequisites. For example, in the following rule all three prerequisites are
   133  implicit.
   134  
   135  ```
   136  foo: [a b c][I]
   137      ...
   138  ```
   139  
   140  ### Recipes
   141  
   142  A recipe is a list of commands to execute, each separated by a newline. They
   143  are executed within the `sh` shell. Each command is executed in a separate
   144  process, spawned with `sh -c <cmd>`. One implication of this is that a `cd`
   145  command will not persist to future commands. If you wish to run multiple
   146  commands in the same shell, you should use the shell's features (`&&`, `||`, or
   147  `;`) for this. For example, `cd foo; cat bar.txt`. Note that you can use `\` to
   148  escape newlines, so that one command can span multiple lines in the recipe.
   149  
   150  Recipes may use variables that will be expanded before the recipe executes.
   151  Variables are written with `$var`, or full Lua expressions can be written with
   152  `$(expr)`. Variables/expressions are expanded eagerly when the rule is created.
   153  If expansion causes an error, the expansion is delayed until rule evaluation
   154  (when special build variables are available). You can use `$$` to escape a
   155  dollar sign. For example, the recipe `echo $$PWD` will echo the environment
   156  variable `PWD`, while `echo $PWD` would attempt to replace `$PWD` with the Lua
   157  variable `PWD` when the rule is elaborated.
   158  
   159  Some special variables are available during recipe expansion:
   160  
   161  * `input`: a string of rule's prereqs.
   162  * `inputs`: an array of this rule's prereqs.
   163  * `output`: a string of this rule's targets.
   164  * `outputs`: an array of this rule's targets.
   165  * `match`: the value captured with `%` in a meta rule.
   166  * `matches`: a list of matches captured by a regular expression meta rule.
   167  * `dep`: the name of the dependency file (if it exists) for the rule, defined
   168    by the `D[...]` attribute.
   169  
   170  When a rule is encountered, `$` expressions are immediately expanded. If
   171  expansion fails, expansion is re-tried when the rule is evaluated (once the
   172  inputs/outputs are known).
   173  
   174  Lua expressions should not mix uses of special build variables and Lua local
   175  variables. Local variables are only available during immediate expansion, and
   176  special build variables are only available during lazy expansion. This
   177  constraint may be relaxed in the future if it turns out to be a useful feature.
   178  
   179  ### Out-of-date calculation
   180  
   181  To determine if a rule must be re-run, Knit computes whether its output is
   182  up-to-date or not. There are two mechanisms for this: a hash-based one and a
   183  timestamp-based one. By default, Knit uses the hash-based mechanism: if a
   184  file's hash has changed since the previous build, it is considered out-of-date,
   185  and all rules that depend on it must be re-run. When depending on a directory,
   186  its hash is the recursive hash of all files within it. The hash-based method is
   187  good for small builds, but can become too slow for large builds. In those cases
   188  you can disable hashing and use the timestamp-based calculation.
   189  
   190  When hashing is disabled, Knit uses a similar computation to Make that is based
   191  on file modification times. If a rule's prerequisites refer to files that have
   192  been modified more recently (according to the system's file modification
   193  timestamp) than the output file, then the rule is determined to be out-of-date
   194  and must be re-run. Other factors may also cause a rule to be re-run, such as
   195  if its recipe has changed, or if it has a rebuild attribute. If the file refers
   196  to a directory, the system's timestamp is not used. Instead, the modification
   197  time of a directory is the timestamp of the most recently modified file in it
   198  (or in any sub-directory). Depending on a very large directory may hinder
   199  performance.
   200  
   201  Hashing can be disabled on a per-project basis or globally by using the
   202  `.knit.toml` configuration file, described the "Configuration" section of this
   203  documentation.
   204  
   205  ## Knitfiles
   206  
   207  A Knitfile is a Lua 5.1 program with additional support for rule expressions.
   208  The Knitfile ultimately must return a "buildset" -- a list of build rules that
   209  are used to construct the build graph.
   210  
   211  A rule is defined in Lua with the `$` syntax:
   212  
   213  ```
   214  $ targets:attributes: prereqs
   215      ...
   216  ```
   217  
   218  A rule expression may be assigned to a variable
   219  
   220  ```
   221  local rule = $ foo.o: foo.c
   222      gcc -c $input -o $output
   223  ```
   224  
   225  More often, rule expressions are gathered together in a Lua table:
   226  
   227  ```
   228  local rules = {
   229      $ foo.o: foo.c
   230          gcc -c $input -o $output
   231      $ foo: foo.o
   232          gcc $input -o $output
   233  }
   234  ```
   235  
   236  When you run `knit`, Knit will automatically look for a file called `Knitfile`
   237  or `knitfile` (or you can specify a custom name with `-f`). Knit will look in
   238  the current directory, and up to ancestor directories if one does not exist in
   239  the current directory. This allows you to execute the build from anywhere in
   240  your project without fragmenting the build system with multiple Knitfiles. You
   241  can still make directory-specific targets that are namespaced relative to that
   242  directory with sub-builds.
   243  
   244  If you run `knit foo.o` from the `foo` directory, and there is a file
   245  `../Knitfile` that defines a rule for building `foo/foo.o`, Knit will
   246  automatically figure out that you mean to build `foo/foo.o` (relative to `..`),
   247  since you specified `foo.o` (relative to `foo`). In other words, building
   248  sub-files just works.
   249  
   250  Likewise, if you run `knit all` from the `foo` directory, and the `all` rule
   251  is only defined for the root directory, Knit will automatically use that rule
   252  instead of trying to use `foo/all`.
   253  
   254  ### Deviations from Lua 5.1
   255  
   256  There are some differences between Knit Lua and Lua 5.1:
   257  
   258  * Knit supports `$` for creating rules.
   259  * Knit supports `:=` for creating raw strings.
   260  * Knit will give an error message when attempting to access an undeclared
   261    variable, whereas Lua 5.1 will just return nil for the value.
   262  
   263  ## Rulesets
   264  
   265  A table of rules can be converted into a "ruleset" by using the special `r`
   266  function, which converts the table into a Lua "userdata" object representing a
   267  list of build rules.
   268  
   269  
   270  ```
   271  local ruleset = r{
   272      $ foo.o: foo.c
   273          gcc -c $input -o $output
   274      $ foo: foo.o
   275          gcc $input -o $output
   276  }
   277  ```
   278  
   279  Note that two rulesets may be combined with the `+` operator.
   280  
   281  ```
   282  ruleset = ruleset + r{
   283      $ build:V: foo
   284  }
   285  ```
   286  
   287  ## Buildsets
   288  
   289  A buildset is a set of rules associated with a particular directory. A buildset
   290  may also contain other buildsets (rules from other directories). All rules in
   291  the buildset are executed relative to its directory. A buildset can be
   292  constructed by using the special `b` function, which constructs a buildset from
   293  a table of rules, rulesets, or other buildsets.
   294  
   295  ```
   296  local buildset = b{
   297      $ foo.o: foo.c
   298          gcc -c $input -o $output
   299      $ foo: foo.o
   300          gcc $input -o $output
   301  }
   302  ```
   303  
   304  By default the buildset's directory is the current working directory when it is
   305  constructed. A second argument may also be passed to `b` to directly specify the
   306  build directory.
   307  
   308  ```
   309  local buildset = b({
   310      $ foo.o: foo.c
   311          gcc -c $input -o $output
   312      $ foo: foo.o
   313          gcc $input -o $output
   314  }, "directory")
   315  ```
   316  
   317  A buildset must be returned by the Knitfile for a build to take place. When a
   318  buildset is returned, knit expands it and all the buildsets that it returns
   319  into the full set of rules, where each rule is relative to the buildset
   320  directory that it came from. Rules may have cross-buildset dependencies.
   321  
   322  These facilities for making rules relative to directories are for enabling
   323  sub-builds, discussed in the next section.
   324  
   325  ### Sub-builds
   326  
   327  A build may use several buildsets.
   328  
   329  For example:
   330  
   331  ```lua
   332  -- this buildset is relative to the "libfoo" directory
   333  local foorules = b({
   334      $ foo.o: foo.c
   335          gcc -c $input -o $output
   336  }, "libfoo")
   337  
   338  return b{
   339      $ prog.o: prog.c
   340          gcc -c $input -o $output
   341      -- libfoo/foo.o is automatically resolved to correspond to the rule in foorules
   342      $ prog: prog.o libfoo/foo.o
   343          gcc $input -o $output
   344  
   345      -- include the foorules buildset
   346      foorules
   347  }
   348  ```
   349  
   350  This Knitfile assumes the build consists of `prog.c` and `libfoo/foo.c`. It
   351  builds `libfoo/foo.o` using a sub-build and automatically determines that the
   352  `foorules` buildset contains the rule for building `libfoo/foo.o`. Note that
   353  the recipe for `foo.o` is run in the `libfoo` directory. Including a buildset
   354  inside another will automatically including all of its rules namespaced into
   355  the directory that the buildset came from.
   356  
   357  It is also useful to combine sub-builds with the `include(x)` function, which
   358  runs the knit program `x` from the directory where it exists, and returns the
   359  value that `x` produces. This means you can easily use a sub-directory's
   360  Knitfile to create a buildset for use in a sub-build.
   361  
   362  For example, for the previous build we could use the following file system
   363  structure:
   364  
   365  `libfoo/build.knit` contains:
   366  
   367  ```lua
   368  -- this buildset's directory will be the current working directory
   369  return b{
   370      $ foo.o: foo.c
   371          gcc -c $input -o $output
   372  }
   373  ```
   374  
   375  `Knitfile` contains:
   376  
   377  ```lua
   378  return b{
   379      $ prog.o: prog.c
   380          gcc -c $input -o $output
   381      -- libfoo/foo.o is automatically resolved to correspond to the rule in foorules
   382      $ prog: prog.o libfoo/foo.o
   383          gcc $input -o $output
   384  
   385      -- include the libfoo rules: this will change directory into libfoo, execute
   386      -- build.knit, and change back to the current directory, thus giving us a buildset
   387      -- for the libfoo directory automatically
   388      include("libfoo/build.knit")
   389  }
   390  ```
   391  
   392  Note that since knit looks upwards for the nearest Knitfile, you can run `knit
   393  foo.o` from inside `libfoo`, and knit will correctly build `libfoo/foo.o`.
   394  
   395  Since managing the current working directory is important for easily creating
   396  buildsets that automatically reference the correct directory, there are several
   397  functions for this:
   398  
   399  * `include(x)`: runs a Lua file from the directory where it exists.
   400  * `dcall(fn, args)`: calls a Lua function from the directory where it is defined.
   401  * `dcallfrom(dir, fn, args)`: calls a Lua function from a specified directory.
   402  * `rel(files)`: makes all input files relative to the build's root directory.
   403  
   404  ## Configuration
   405  
   406  Knit will search the current directory for a Knitfile called `knitfile` or
   407  `Knitfile`. If one is not found, it will use the Knitfile in
   408  `~/.config/knit/Knitfile.def`, or if that does not exist it will throw an
   409  error.
   410  
   411  Several options are available as command-line flags. They may also be specified
   412  in a `.knit.toml` file. Knit will search upwards from the current directory
   413  for `.knit.toml` files, and use the options set in those files. It will also
   414  search `~/.config/knit/.knit.toml`.
   415  
   416  The default set of flags is:
   417  
   418  ```toml
   419  knitfile = "knitfile"
   420  ncpu = 8 # depends on the number of logical cores on your machine
   421  dryrun = false
   422  directory = ""
   423  always = false
   424  quiet = false
   425  style = "basic"
   426  cache = ""
   427  hash = true
   428  updated = []
   429  root = false
   430  keepgoing = false
   431  shell = "sh"
   432  ```
   433  
   434  ## Sub-tools
   435  
   436  Running `knit [TARGET]` will create a build graph for the target. By default,
   437  knit will then execute that build graph. Using the `-t TOOL` option, you may
   438  specify a sub-tool to run instead of building:
   439  
   440  * `list` - list all available tools
   441  * `graph` - print build graph in specified format: text, tree, dot, pdf
   442  * `clean` - remove all files produced by the build
   443  * `targets` - list all targets (pass 'virtual' for just virtual targets)
   444  * `compdb` - output a compile commands database
   445  * `commands` - output the build commands (formats: knit, json, make, ninja, shell)
   446  * `status` - lists dependencies and whether they are up-to-date
   447  * `path` - shows the path of the current knitfile
   448  
   449  The special target `:all` depends on every target in the build. Thus `knit :all
   450  -t targets` will list all targets.
   451  
   452  Some examples are shown below.
   453  
   454  ### Automatic cleaning
   455  
   456  ```
   457  knit target -t clean
   458  ```
   459  
   460  ### Output a shell script for the build
   461  
   462  ```
   463  knit target -t commands shell
   464  ```
   465  
   466  ### Output a Ninja build file
   467  
   468  ```
   469  knit target -t commands ninja
   470  ```
   471  
   472  ### Output a compile commands database
   473  
   474  ```
   475  knit target -t compdb
   476  ```
   477  
   478  ### Output a PDF build graph
   479  
   480  ```
   481  knit target -t graph pdf > graph.pdf
   482  ```
   483  
   484  ## Special rules
   485  
   486  Knit automatically defines two special rules: `:all` and `:build`.
   487  
   488  The `:all` rule depends on all possible targets in the build (except those
   489  attainable only from meta-rules). For example `knit :all -t targets` will list
   490  all possible targets, and `knit :all -t clean` will clean all possible outputs.
   491  
   492  The `:build` rule is the root rule of the build and depends on all requested
   493  targets. For example `knit a b c` will generate a `:build` rule that depends on
   494  `a`, `b`, and `c`. In general, you should never refer to the `:build` rule
   495  since doing so will usually create a build cycle.
   496  
   497  ## Default rule
   498  
   499  If you run `knit` without a target, Knit will build the first non-meta rule.
   500  
   501  ## Rule priority
   502  
   503  If several rules with recipes that could be used to build a file, Knit uses the
   504  last one. In other words, defining a rule later will override previous
   505  definitions of a rule. However, if a later rule does not have a recipe, it will
   506  not override the rule for the target, but instead just add the new
   507  prerequisites for that target to the previous rule.
   508  
   509  If several rules from different buildsets could be used to build a target, the
   510  rule from the buildset for the target's directory is attempted first. If it
   511  does not exist, then rules are attempted from all other buildsets and the first
   512  buildset to have a matching rule is used. If a meta-rule is used, it is
   513  attmpted in the current buildset before looking in other buildsets.
   514  
   515  ## Built-in Lua syntax
   516  
   517  * `$ ...`: creates a rule. The rule is formatted using string interpolation.
   518    The rule continues until indentation returns to the level of the `$`.
   519  
   520  * `x := ...`: creates a string without quotes. The string value continues until
   521    the end of the line, and is automatically formatted using string
   522    interpolation.
   523  
   524  Both of these expressions are implicitly terminated with a `;`, allowing them
   525  to be used in tables.
   526  
   527  ## Built-in Lua functions
   528  
   529  Note: several functions throw errors. Use the built-in Lua `pcall` function to
   530  perform error handling. `local ok, result = pcall(fn, args)` returns whether
   531  there was an error during the execution of `fn(args)`. The `result` variable
   532  will contain the result, or the error value.
   533  
   534  * `rule(rule)`: define a rule. The `$` syntax is shorthand for this function.
   535  
   536  * `rulefile(file)`: define a rule by reading it from `file`. Throws an error if
   537    the file does not exist.
   538  
   539  * `include(file)`: run a Knitfile from its directory (changes the
   540    current working directory while the file is being executed) and return the
   541    generated ruleset. Throws an error if `file` does not exist.
   542  
   543  * `dcall(fn, args)`: call `fn(args)` from the directory where `fn` is defined.
   544  
   545  * `dcallfrom(dir, fn, args)`: call `fn(args)` from `dir`.
   546  
   547  * `rel(files)`: make all paths in the table `files` relative to the build root
   548    (the location of the Knitfile).
   549  
   550  * `r{$ ...}`, `r({...})`: turn a table of rules into a ruleset.
   551  
   552  * `b{...}`, b({...}, dir): turn a table of rules, rulesets, or buildsets
   553    into a buildset associated with directory `dir`. `dir` is optional, and if
   554    not specified will be the current working directory.
   555  
   556  * `tobool(value)` bool: convert an arbitrary value to a boolean. A nil value
   557    will return nil, the strings `false`, `off`, or `0` will become false. A
   558    boolean will not be converted. Anything else will be true.
   559  
   560  * `eval(code)`: evaluates a Lua expression in the global scope
   561    and returns the result. Throws an error if the code has an error.
   562  
   563  * `f"..."`, `f(s)`: formats a string using `$var` or `$(expr)` to
   564    expand variables/expressions. Throws an error if the variable does not exist,
   565    or the expression has an error.
   566  
   567  * `expand(s)`: formats a string in the same way as `f`, but if there is an
   568    error, it does not expand that particular `$...` expression.
   569  
   570  * `use(pkg)`: imports all fields of `pkg` into the global namespace. Meant to
   571    be used with `require`: `use(require("knit"))`.
   572  
   573  * `sel(cond, a, b)`: if `cond` is true return `a`, otherwise return `b`.
   574  
   575  * `choose(a, b, c...)`: return the first value in the list of arguments that is
   576    not nil.
   577  
   578  * `r{} + r{}`: you may use the `+` operator to combine rulesets together.
   579  
   580  * `b{} + val`: you may use the `+` operator to combine buildsets with
   581    rules/rulesets/buildsets.
   582  
   583  * `{s} + {s}`: string tables returned by knit functions can be added together.
   584  
   585  ## The `knit` Lua package
   586  
   587  The `knit` package can be imported with `require("knit")`, and provides the following functions:
   588  
   589  * `repl(in, patstr, repl)`: replace all occurrences of the Go regular
   590    expression `patstr` with `repl` within the array `in`. Throws an error if
   591    there is an error with `patstr`.
   592  
   593  * `extrepl(in, ext, repl)`: replace all occurrences of the literal string `ext`
   594    as a suffix with `repl` within the array `in`.
   595  
   596  * `glob(pat)`: return all files in the current working directory that match the
   597    glob `pat`.
   598  
   599  * `suffix(in, suffix)`: add the string `suffix` to the end of every string in
   600    the array `in`, and return the new array.
   601  
   602  * `prefix(in, prefix)`: add the string `prefix` to the beginning of every
   603    string in the array `in`, and return the new array.
   604  
   605  * `filterout(in, exclude)`: returns a new table containing all the elements of
   606    `in`, except those in `exclude`.
   607  
   608  * `shell(cmd) string`: execute a command with the shell and return its
   609    output. Throws an error if the command exits with an error.
   610  
   611  * `trim(s)`: trim leading and trailing whitespace from a string.
   612  
   613  * `abs(path)`: return the absolute path of a path.
   614  
   615  * `dir(path)`: return the directory part of a path.
   616  
   617  * `base(path)`: return the basename of a path.
   618  
   619  * `os`: a string containing the operating system name.
   620  
   621  * `arch`: a string containing the machine architecture name.
   622  
   623  * `flags`: a struct containing the values of the flags when Knit was invoked.
   624    See https://pkg.go.dev/github.com/zyedidia/knit#Flags.
   625  
   626  * `addpath(p)`: adds the path `p` to the global require path. Files with ending
   627    with `.lua` or `.knit` are added.
   628  
   629  * `knit(flags)`: executes the shell command `knit flags` (where `flags` is a
   630    string of CLI arguments) using the current instance of Knit.
   631  
   632  ## CLI and environment variables
   633  
   634  Variables may be set at the command-line when invoking Knit with the syntax
   635  `var=value`. These variables will be available in the Knitfile in the `cli`
   636  table. Environment variables are similarly available in the `env` table.