chiark / gitweb /
README.md: Proposed invocation rework
[nailing-cargo.git] / README.md
1 nailing-cargo
2 =============
3
4 This is a wrapper tool for cargo, the Rust build tool and package
5 manager.  Functions:
6
7  * Conveniently use local crates, including completely
8    unpublished crates.
9
10  * Perform out-of-tree builds, including in an account with
11    no write access to the source tree.
12
13  * Provide convenience aliases for target architecture names.
14
15  * Make the default be offline (ie, not to access the internet)
16
17 These functions are of course configurable.
18
19 The primary source of information for nailing-cargo is the file
20 `../Cargo.nail` (which is in TOML syntax).  You put `Cargo.nail`
21 alongside the top-level git repositories you are working with, and
22 invoke nailing-cargo from the git directory containing the Rust
23 package you want to build.
24
25 Installing
26 ----------
27
28 nailing-cargo is designed to be run out of a git clone:
29
30 ```
31 $ git clone https://salsa.debian.org/iwj/nailing-cargo.git
32 $ ln -s `pwd`/nailing-cargo/nailing-cargo ~/bin
33 ```
34
35 It is self-contained, depending only on a reasonably functional Perl
36 installation.
37
38 Most basic example usage
39 ------------------------
40
41 ```
42 $ cd myproject
43 $ cat >../Cargo.nail
44 subdirs="""
45 myproject
46 mylibrary
47 """
48 $ nailing-cargo generate-lockfile
49 $ nailing-cargo build
50 ```
51
52 Using local crates, or locally modified crates
53 ==============================================
54
55 cargo does not work well with local crates,
56 especially completely unpublished ones.
57 (See [issue#6713](https://github.com/rust-lang/cargo/issues/6713),
58 [stackoverflow](https://stackoverflow.com/questions/33025887/how-to-use-a-local-unpublished-crate),
59 [issue#1481](https://github.com/rust-lang/cargo/issues/1481),
60 [my blog](https://diziet.dreamwidth.org/1805.html).)
61
62 Using a local version of a crate should be possible without putting
63 paths into your `Cargo.toml` and without editing complex
64 configuration.
65
66 How nailing-cargo helps with using local crates
67 -----------------------------------------------
68
69 nailing-cargo temporarily edits all the `Cargo.toml` files in all the
70 subdirectories you mention, to refer to each other; then it runs
71 cargo; and then it puts everything back.
72
73 Telling nailing-cargo how to massage `Cargo.toml`
74 -------------------------------------------------
75
76 To find the subdirectories, and the packages, it looks for `subdirs`
77 and `packages` in `Cargo.nail`.
78
79 For straightforward use, write `subdirs` as a multi-line string
80 containing a list of subdirectory names one per line.  In each of
81 these directories `Cargo.toml` will be massaged, and the package there
82 will be used for other massaged `Cargo.toml`s.
83
84 See "Configuration reference", below, for full details.
85
86 Out-of-tree builds
87 ==================
88
89 It is often desirable to run builds in a way that does not write to
90 the source tree.  cargo's enthusiastic approach to the dependency
91 management task means that it is a good idea to try to insulate your
92 main working environment from the many things cargo has decided to
93 download and execute.
94
95 However, when you tell cargo to do an out of tree build (using
96 `--manifest-path`) it will insist on `Cargo.lock` being in the source
97 directory, and often will insist on writing to it.
98
99 How nailing-cargo helps with out-of-tree builds
100 -----------------------------------------------
101
102 nailing-cargo (configured appropriately) copies files back and forth
103 to between the source and build directories, and runs cargo as your
104 build user.
105
106 The `Cargo.lock` must still be saved in your source tree somewhere.
107 nailing-cargo arranges this for you.  You can either put this file in
108 `.gitignore`; or commit it to git; or you can tell nailing-cargo to
109 save it as something like `Cargo.lock.example`.
110
111 Configuring out-of-tree builds
112 ------------------------------
113
114 To enable out-of-tree-builds, put an `[oot]` section in your
115 `Cargo.nail` or one of nailing-cargo's other config files.
116 In that section, specify at least `use`.
117
118 Also, specify `dir`, or create a symlink `Build` next to `Cargo.nail`,
119 pointing to to your build area.
120
121 For example,
122 ```
123 [oot]
124 use='ssh'
125 user='rustcargo'
126 ```
127 will have nailing-cargo run `ssh rustcargo@localhost` to
128 run build commands.
129
130 Target architecture convenience aliases
131 =======================================
132
133 If you are cross-building you may need to tell cargo `--target=`.
134 The architecture names are quite long and inconvenient.
135
136 A simple shell alias would help a lot, except that cargo rejects
137 `--target=` when it thinks it's not needed.
138
139 In your nailing-cargo config, you can write something like
140 `arch.RPI='arm-unknown-linux-gnueabihf'`.  Then `nailing-cargo -ARPI`
141 will DTRT.  In fact, you do not even need to specify that particular
142 arch alias, since it is built-in to nailing-cargo.
143
144 Default change to offline mode
145 ==============================
146
147 It seems to me that build tools should be explicit about their use of
148 the network.  So by default, nailing-cargo passes `--offline` to
149 cargo.
150
151 If you disagree with my opinion, write `misc.online=true` in your
152 nailing-cargo configuration.  `misc.online=false`, and command line
153 options, are also available, for overriding.
154
155 Invocation and command-line option reference
156 ============================================
157
158 Usages
159 ------
160
161 ```
162 1$ nailing-cargo <nailing-opts> <cargo-opts> [--] <subcmd>...
163 2$ nailing-cargo <nailing-opts> --- <cargo> <cargo-opts> [--] <subcmd>...
164 3$ nailing-cargo <nailing-opts> --- [--] <build-command>...
165 ```
166 Ususally the `--` is not needed.  (It should generally be passed by
167 programs which wrap nailing-cargo.  See below.)
168
169 In usage 1, nailing-cargo runs `cargo` (from `PATH`).  In the usage 2
170 nailing-cargo runs `<cargo>`.  In both these cases it adds its own
171 options to control cargo's behaviour.  In both of these cases
172 nailing-cargo looks at `<subcmd>` to determine the cargo subcommand
173 being run: this controls various defaults, to try to do the right
174 things.
175
176 In the third syntax, nailing-cargo runs `<build-command>...` without
177 additional arguments and does not attempt to identify the cargo
178 subcommand(s) that it will run.  Possibly it will be necessary to pass
179 `--online` or `--cargo-lock-update`, or even `--cargo-*arg*`
180
181 ### Invocation argument disambiguation rules ###
182
183 For authors of tools which call nailing-cargo (and pedants):
184 NB: The usages overlap in syntax!
185 nailing-cargo follows the following rules when
186  interpreting its command line:
187
188    * The first option not recognised as a nailing-cargo option is
189      treated as the start of the `<cargo-opts>`.
190
191    * `<cargo-opts>` are terminated by `--` (which is removed) or the
192      first argument which does not start with a `-`.
193
194      (It is not possible to get nailing-cargo to pass the value `--`
195      as a separate argument to a cargo global option, but cargo global
196      options can typically take the values cuddled with `=`, so doing
197      that is not necessary.)
198
199    * After `---`, nailing-cargo will search for a `--`, to the end of
200      the arguments if necessary.  The position of the `--` determines
201      whether this is usage 2 or usage 3, and what `<subcmd>` is.
202
203      If the arguments after `nailing-cargo ... ---` might contain `--`
204      anywhere, an explicit `--` should be passed.
205
206    * If no `--` appears after `---`, the word after `---` is the
207      command to run; if its final pathname component contains the
208      string `cargo`, it is treated as `<cargo>` (implying usage 2 and
209      the search for `<subcmd>`).  Otherwise it is treated as
210      `<build-command>` (usage 3).
211
212 Options
213 -------
214
215   * `-v`: Increase verbosity.  Default is 1.
216
217   * `-q`: Set verbosity to 0.
218
219   * `-D`: Increase amount of debugging dump.
220
221   * `-n`: "No action": stop after writing `Cargo.toml.nailing~`
222        everywhere, and do not run any build command.
223
224   * `-A<arch>` | `--arch=<arch>` | `--target=<arch>`
225
226        Specify target architecture.
227
228        This option translates to a `--target=<arch>` option to the
229        ultimate command, unless that is a cargo subcommand which we
230        know would reject it.  `--arch` and `--target` are simply
231        aliases.
232
233        If `<arch>` starts with a capital ascii letter, it is an alias
234        for some other arch: it is looked up in the configuration, and
235        then in the builtin arch alias list.  The builtin list is
236        equivalent to: `[arch]` `RPI='arm-unknown-linux-gnueabihf'`.
237
238   * `-u` | `--cargo-lock-update` | `-U` | `--no-cargo-lock-update`
239
240        Enables, or disables, the dance to allow `Cargo.lock` (or
241        alternative) to be updated in the source directory.
242
243        With this dance enabled the `Cargo.lock` and `Cargo.toml` are
244        copied to the build directory along with a skeleton just big
245        enough to fool cargo.  After cargo has run, the resulting
246        `Cargo.lock` is copied back to the source tree.
247
248        This makes no sense with in-tree builds.
249
250        Default is no update unless the ultimate command is a
251        cargo subcommand which we know needs it.
252
253   * `-m` | `--cargo-manifest-args` | `-M` | `--no-cargo-manifest-args`
254
255        Controls whether we add cargo command line options, relating to
256        finding `Cargo.toml`, to the command to run.
257
258        Default is to add them if we are doing an out-of-tree build,
259        unless we are doing the dance to update the `Cargo.lock` (see
260        above) since in that case all the relevant files can be found
261        by cargo in the build directory.
262
263        The arguments added are
264
265            --manifest-path=<path/to/Cargo.toml>
266            --locked
267            --target-dir=target
268
269   * `-T` | `--no-cargo-target-dir-arg` | `-t` | `--cargo-target-dir-arg`
270
271        `-T` suppresses `--target-dir`; `-t` un-suppresses it.  Only
272        makes any difference with `-m`, since otherwise no
273        `--target-dir` would be passed anyway.  Additionally this is
274        done automatically when nailing-cargo sees that the cargo
275        subcommand is one which needs it, eg `fetch`.
276
277   * `-o` | `--online` | `-O` | `--offline`
278
279        Whether to allow cargo to make network access.  nailing-cargo
280        always passes `--offline` to cargo, unless `--online` is in
281        force.  The default value depends on the configuration and the
282        cargo subcommand - see `[misc]` `online` in "Configuration".
283
284 Environment of the build command
285 --------------------------------
286
287 nailing-cargo passes these environment variables to the build command:
288
289   * `NAILINGCARGO_WORKSPHERE`: invocation `..` (parent)
290   * `NAILINGCARGO_MANIFEST_DIR`: invocation `.` (invocation directory)
291   * `NAILINGCARGO_BUILD_DIR`: build directory (even if same as source)
292   * `NAILINGCARGO_BUILDSPHERE`: only set if out of tree: parent of build dir.
293
294 All of these are absolute paths.
295
296 Configuration reference
297 =======================
298
299 nailing-cargo reads these configuration files:
300 ```
301     /etc/nailing-cargo/cfg.toml
302     ~/.nailing-cargo.toml
303     ./.nailing-cargo.toml
304     ../Nailing-Cargo.toml
305     ../Cargo.nail
306 ```
307 Settings in later-mentioned files override ones in earlier-mentioned
308 files.
309
310 Source directories and packages (toplevel)
311 ------------------------------------------
312
313 Note that unlike everything else, these keys (`packages` and
314 `subdirs`) are read only from `Cargo.nail` (see "Limitations and
315 bugs", below).
316
317 These keys specify a combination of (i) a mapping from package name to
318 source subdirectory (ii) a set of subdirectories whose `Cargo.toml`
319 must be massaged.
320
321   * `packages`: a map keyed by package name, giving the subdirectory
322     for each one.
323
324     This causes each mentioned subdirectory's `Cargo.toml` to be
325     massaged, and records that subdirectory as the source for that
326     package.  (nailing-cargo will check that subdirectory actually
327     contains the indicated package.)
328
329     Each value can be just the subdirectory name (eg `[packages]`
330     `mylibrary='mylibrary-test'`) or itself a map with the key `subdir`
331     (eg `[packages.mylibrary]` `subdir='mylibrary-test'`).
332
333   * `subdirs`: a list of subdirectory names to process.
334
335     Each subdirectory's `Cargo.toml` will be massaged.  Also, the
336     subdirectory will be examined to see what package it contains; it
337     will then be used as the source for that package, unless that
338     package appears in an entry in `packages`, or an earlier entry in
339     `subdirs`.
340
341     This can be a list of strings (eg `subdirs =
342     ['myproject','mylibrary']`).  Or it can be single multi-line
343     string containing one subdirectory name per line; in that
344     case, `#`-comments are supported and tabs and spaces are ignored
345     (see "Most basic example usage" above.)
346
347 In each case the subdirectory should usually be a relative pathname;
348 it is relative to the directory containing `Cargo.nail`.
349
350 `[alt_cargolock]`: Alternative `Cargo.lock` filename
351 ----------------------------------------------------
352
353 To control use of alternative `Cargo.lock` filename, use the section
354 `[alt_cargolock]`.  Settings here:
355
356   * `file = <some leafname>`.
357
358   * `file = true`: Equivalent to `file = "Cargo.lock.example"`.
359     (This is the default.)
360
361   * `file = false`: Disables this feature.
362
363   * `force = false`: Uses the alternative filename only if it
364      already exists.  (This is the default.)
365
366   * `force = true`: Always uses the alternative filename.
367
368 `[oot]`: Out-of-tree build support
369 ----------------------------------
370
371   * `dir`: The build directory.  If relative, it is relative to the
372    parent of the invocation directory (and could be a symlink then).
373    Default is `Build` (assuming `use` is specified).
374
375    The build directory will contain one subdir for each package: each
376    subdir in the build dir corresponds to one source dir where
377    nailing-cargo was invoked.  nailing-cargo will arrange to create
378    these subdirectories, so the build directory can start out empty.
379
380   * `use`: How to become the build user.  Needs to be combined
381     with other setting(s):
382
383     * `ssh`: Use ssh.  `user` must be given as well and can be
384        a username on localhost, or the `<user>@<host>`
385        argument to ssh.
386
387     * `command_args`: `command` must be specified as a list,
388        specifying a command and arguments which work like `nice`.
389
390     * `command_sh`: `command` must be specified as a list,
391        specifying a command and arguments which work like `sh -c`.
392
393     * `null`: Run builds as the same user.
394
395     * `really`: Use `really` from `chiark-really.deb`.
396        `user` must be given as well.
397
398  * `command`: The command to run for `command_sh` or `command_args`.
399
400  * `user`: The local username for `really` and `ssh`, or
401    `<user>@<host>` for `ssh`.
402
403 `[arch]`: Architecture convenience aliases
404 ------------------------------------------
405
406 This is a map from archictecture aliases to full cargo architecture
407 names.  The keys are the aliases; each entry should be a string, the
408 cargo architecture name.
409
410 Only keys starting with an ascii uppercase letter are relevant, since
411 other names are not looked up in this alias map.
412
413 `[misc]`: Miscellaneous individual nailing-cargo config
414 -------------------------------------------------------
415
416  * `online`: boolean, specifying whether to pass `--offline` to cargo
417    (cargo's default is online mode).  The default is offline, unless
418    nailing-cargo can see that the cargo subcommand being invoked is
419    one which requires online access (currently, `fetch`), in which
420    case the default is online.
421
422 Limitations and bugs
423 ====================
424
425   * nailing-cargo temporarily dirties your source trees, including
426     particularly `Cargo.toml` and `Cargo.lock`; and if nailing-cargo
427     crashes or is interrupted these changes may be left behind.
428     Unfortunately it is not possible to avoid this temporary dirtying
429     because the cargo team have deliberately made cargo inflexible -
430     [issue#6715](https://github.com/rust-lang/cargo/issues/6715).  
431     At least, running nailing-cargo again will clean up any mess
432     left by an interrupted run.
433
434   * Out of tree builds require a unified filesystem view: eg, different
435     users on the same host, NFS, or something.
436
437     Specifically, the invocation and build execution environments must
438     both have visibility of the source and build directories, at the
439     same absolute pathnames.  The invocation environment must be able
440     to write to the build environment (but vice versa is not
441     required).
442
443     This could be improved.
444
445   * The alternative `Cargo.lock` filename must currently be a leafname.  I
446     think fixing this just involves review to check other values work
447     properly.
448
449   * The alternative `Cargo.lock` file must be on the same filesystem
450     as the source tree.  This is not so easy to fix; we would want the
451     existing algorithm but a fallback for the different-filsystem case.
452
453   * `Cargo.nail` is unconditionally looked for in the parent directory.
454     Ideally this should be configurable, and also perhaps be able to
455     combine multiple `Cargo.nail` files?  Relatedly, although
456     nailing-cargo can read multiple config files, it can only handle
457     one file specifying directories and packages.
458
459   * nailing-cargo uses a single lockfile alongside your `Cargo.nail`,
460     rather than a more sophisticated scheme involving locking
461     particular directories.  This means that if you run multiple
462     copies of nailing-cargo at once, in different directories, but
463     with `Cargo.nail` files which imply overlapping sets of package
464     directories, things will go Badly Wrong.
465
466 Contributing and legal
467 ======================
468
469 nailing-cargo is Free Software.
470
471 Please help improve it.  Contributions (to address the limitations, or
472 to add new facilities to help work with cargo) are welcome by email to
473 `ijackson@chiark.greenend.org.uk` or via the [Salsa
474 project](https://salsa.debian.org/iwj/nailing-cargo).
475
476 If you plan to do substantial work, please do get in touch with a
477 sketch of your proposed changes.
478
479 Legal
480 -----
481
482 This project accepts contributions based on the git commit
483 Signed-off-by convention, by which the contributors certify their
484 contributions according to the Developer Certificate of Origin version
485 1.1 - see the file DEVELOPER-CERTIFICATE.
486
487 Copyright (C) 2019-2020 Ian Jackson and others
488
489 This program is free software: you can redistribute it and/or modify
490 it under the terms of the GNU Affero General Public License as
491 published by the Free Software Foundation, either version 3 of the
492 License, or (at your option) any later version.
493
494 This program is distributed in the hope that it will be useful,
495 but WITHOUT ANY WARRANTY; without even the implied warranty of
496 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
497 GNU Affero General Public License for more details.
498
499 You should have received a copy of the GNU Affero General Public License
500 along with this program.  If not, see <http://www.gnu.org/licenses/>.
501
502 Individual files generally contain the following tag in the copyright
503 notice, instead of the full licence grant text:
504 ```
505    SPDX-License-Identifier: AGPL-3.0-or-later
506 ```
507 As is conventional, this should be read as a licence grant.