chiark / gitweb /
README.md: Config reference: packages and subdirs
[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 cargo generate-lockfile
49 $ nailing-cargo 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", below, for the full reference.
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 The primary config keys here are:
119
120   * `dir`: The build directory.  If relative, it is relative to the
121    parent of the invocation directory (and could be a symlink then).
122    Default is `Build` (assuming `use` is specified).
123
124   * `use`: How to become the build user.  Needs to be combined
125     with other setting(s):
126
127     * `ssh`: Use ssh.  `user` must be given as well and can be
128        a username on localhost, or the `<user>@<host>`
129        argument to ssh.
130
131     * `command_args`: `command` must be specified as a list,
132        specifying a command and arguments which work like `nice`.
133
134     * `command_sh`: `command` must be specified as a list,
135        specifying a command and arguments which work like `sh -c`.
136
137     * `null`: Run builds as the same user.
138
139     * `really`: Use `really` from `chiark-really.deb`.
140        `user` must be given as well.
141
142 Target architecture convenience aliases
143 =======================================
144
145 If you are cross-building you may need to tell cargo `--target=`.
146 The architecture names are quite long and inconvenient.
147
148 A simple shell alias would help a lot, except that cargo rejects
149 `--target=` when it thinks it's not needed.
150
151 In your nailing-cargo config, you can write something like
152 `arch.RPI='arm-unknown-linux-gnueabihf'`.  Then `nailing-cargo -ARPI`
153 will DTRT.  In fact, you do not even need to specify that particular
154 arch alias, since it is built-in to nailing-cargo.
155
156 Default change to offline mode
157 ==============================
158
159 It seems to me that build tools should be explicit about their use of
160 the network.  So by default, nailing-cargo passes `--offline` to
161 cargo.
162
163 If you disagree with my opinion, write `misc.online=true` in your
164 nailing-cargo configuration.  `misc.online=false`, and command line
165 options, are also available, for overriding.
166
167 Command-line options
168 ====================
169
170   * `-v`: Increase verbosity.  Default is 1.
171
172   * `-q`: Set verbosity to 0.
173
174   * `-D`: Increase amount of debugging dump.
175
176   * `-n`: "No action": stop after writing `Cargo.toml.nailing~`
177        everywhere, and do not run any build command.
178
179   * `-A<arch>` | `--arch=<arch>` | `--target=<arch>`
180
181        Specify target architecture.
182
183        This option translates to a `--target=<arch>` option to the
184        ultimate command, unless that is a cargo subcommand which we
185        know would reject it.  `--arch` and `--target` are simply
186        aliases.
187
188        If `<arch>` starts with a capital ascii letter, it is an alias
189        for some other arch: it is looked up in the configuration, and
190        then in the builtin arch alias list.  The builtin list is
191        equivalent to: `[arch]` `RPI='arm-unknown-linux-gnueabihf'`.
192
193   * `-u` | `--cargo-lock-update` | `-U` | `--no-cargo-lock-update`
194
195        Enables, or disables, the dance to allow `Cargo.lock` (or
196        alternative) to be updated in the source directory.
197
198        With this dance enabled the `Cargo.lock` and `Cargo.toml` are
199        copied to the build directory along with a skeleton just big
200        enough to fool cargo.  After cargo has run, the resulting
201        `Cargo.lock` is copied back to the source tree.
202
203        This makes no sense with in-tree builds.
204
205        Default is no update unless the ultimate command is a
206        cargo subcommand which we know needs it.
207
208   * `-m` | `--cargo-manifest-args` | `-M` | `--no-cargo-manifest-args`
209
210        Controls whether we add cargo command line options, relating to
211        finding `Cargo.toml`, to the command to run.
212
213        Default is to add them if we are doing an out-of-tree build,
214        unless we are doing the dance to update the `Cargo.lock` (see
215        above) since in that case all the relevant files can be found
216        by cargo in the build directory.
217
218        The arguments added are
219
220            --manifest-path=<path/to/Cargo.toml>
221            --locked
222            --target-dir=target
223
224   * `-T` | `--no-cargo-target-dir-arg` | `-t` | `--cargo-target-dir-arg`
225
226        `-T` suppresses `--target-dir`; `-t` un-suppresses it.  Only
227        makes any difference with `-m`, since otherwise no
228        `--target-dir` would be passed anyway.  Additionally this is
229        done automatically when nailing-cargo sees that the cargo
230        subcommand is one which needs it, eg `fetch`.
231
232   * `-o` | `--online` | `-O` | `--offline`
233
234        Whether to allow cargo to make network access.  nailing-cargo
235        always passes `--offline` to cargo, unless `--online` is in
236        force.  The default is offline, unless the cargo subcommand is
237        one which implies online (currently, `fetch`).
238
239 Configuration
240 =============
241
242 nailing-cargo reads these configuration files:
243 ```
244     /etc/nailing-cargo/cfg.toml
245     ~/.nailing-cargo.toml
246     ./.nailing-cargo.toml
247     ../Nailing-Cargo.toml
248     ../Cargo.nail
249 ```
250 Settings in later-mentioned files override ones in earlier-mentioned
251 files.
252
253 Source directories and packages (toplevel)
254 ------------------------------------------
255
256 Note that unlike everything else, these keys `packages` and `subdirs`
257 are read only from `Cargo.nail` (see "Limitations and bugs", below).
258
259 These keys specify a combination of (i) a mapping from package name to
260 source subdirectory (ii) a set of subdirectories whose `Cargo.toml`
261 must be massaged.
262
263   * `packages`: a map keyed by package name, giving the subdirectory
264     for each one.
265
266     This causes each mentioned subdirectory's `Cargo.toml` to be
267     massaged, and records that subdirectory as the source for that
268     package.  (nailing-cargo will check that subdirectory actually
269     contains the indicated package.)
270
271     Each value can be just the subdirectory name (eg `[packages]`
272     `mylibrary='mylibrary-test'`) or itself a map with the key `subdir`
273     (eg `[packages.mylibrary]` `subdir='mylibrary-test'`).
274
275   * `subdirs`: a list of subdirectory names to process.
276
277     Each subdirectory's `Cargo.toml` will be massaged; also, the
278     subdirectory will be examined to see what package it contains and
279     it will be used as the source for that package, unless that
280     package appears in an entry in `packages`, or an earlier entry in
281     `subdirs`.
282
283     This can be a list of strings (eg `subdirs =
284     ['myproject','mylibrary']`).  Or it can be single multi-line
285     string containing one subdirectory name per line; in that
286     case, `#`-comments are supported and tabs and spaces are ignored
287     (See "Most basic example usage" above.)
288
289 In each case the subdirectory should usually be a relative pathname;
290 it is relative to the directory containing `Cargo.nail`.
291
292 `[alt_cargolock]`: Alternative `Cargo.lock` filename
293 ----------------------------------------------------
294
295 To control use of alternative `Cargo.lock` filename, use the section
296 `[alt_cargolock]`.  Settings here:
297
298   * `file = <some leafname>`.
299
300   * `file = true`: Equivalent to `file = "Cargo.lock.example"`.
301     (This is the default.)
302
303   * `file = false`: Disables this feature.
304
305   * `force = false`: Uses the alternative filename only if it
306      already exists.  (This is the default.)
307
308   * `force = true`: Always uses the alternative filename.
309
310 Running the command
311 ===================
312
313 Normally you pass cargo as an argument to nailing-cargo.  But you
314 can also pass make or any other command.  You may need to pass
315 `--no-cargo-manifest-args` (aka `-M`) to nailing-cargo, to avoid
316 passing options like `--manifest-path` to make or whatever.
317
318 nailing-cargo passes these environment variables to the build command:
319
320   * `NAILINGCARGO_WORKSPHERE`: invocation `..` (parent)
321   * `NAILINGCARGO_MANIFEST_DIR`: invocation `.` (invocation directory)
322   * `NAILINGCARGO_BUILD_DIR`: build directory (even if same as source)
323   * `NAILINGCARGO_BUILDSPHERE`: only set if out of tree: parent of build dir.
324
325 All of these are absolute paths.
326
327 Limitations and bugs
328 ====================
329
330   * nailing-cargo temporarily dirties your source trees, including
331     particularly `Cargo.toml` and `Cargo.lock`; and if nailing-cargo
332     crashes or is interrupted these changes may be left behind.
333     Unfortunately it is not possible to avoid this temporary dirtying
334     because the cargo team have deliberately made cargo inflexible -
335     [issue#6715](https://github.com/rust-lang/cargo/issues/6715).  
336     At least, running nailing-cargo again will clean up any mess
337     left by an interrupted run.
338
339   * Out of tree builds require a unified filesystem view: eg, different
340     users on the same host, NFS, or something.
341
342     Specifically, the invocation and build execution environments must
343     both have visibility of the source and build directories, at the
344     same absolute pathnames.  The invocation environment must be able
345     to write to the build environment (but vice versa is not
346     required).
347
348     This could be improved.
349
350   * The alternative `Cargo.lock` filename must currently be a leafname.  I
351     think fixing this just involves review to check other values work
352     properly.
353
354   * The alternative `Cargo.lock` file must be on the same filesystem
355     as the source tree.  This is not so easy to fix; we would want the
356     existing algorithm but a fallback for the different-filsystem case.
357
358   * `Cargo.nail` is unconditionally looked for in the parent directory.
359     Ideally this should be configurable, and also perhaps be able to
360     combine multiple `Cargo.nail` files?  Relatedly, although
361     nailing-cargo can read multiple config files, it can only handle
362     one file specifying directories and packages.
363
364   * nailing-cargo uses a single lockfile alongside your `Cargo.nail`,
365     rather than a more sophisticated scheme involving locking
366     particular directories.  This means that if you run multiple
367     copies of nailing-cargo at once, in different directories, but
368     with `Cargo.nail` files which imply overlapping sets of package
369     directories, things will go Badly Wrong.
370
371 Contributing and legal
372 ======================
373
374 nailing-cargo is Free Software.
375
376 Please help improve it.  Contributions (to address the limitations, or
377 to add new facilities to help work with cargo) are welcome by email to
378 `ijackson@chiark.greenend.org.uk` or via the [Salsa
379 project](https://salsa.debian.org/iwj/nailing-cargo).
380
381 If you plan to do substantial work, please do get in touch with a
382 sketch of your proposed changes.
383
384 Legal
385 -----
386
387 This project accepts contributions based on the git commit
388 Signed-off-by convention, by which the contributors certify their
389 contributions according to the Developer Certificate of Origin version
390 1.1 - see the file DEVELOPER-CERTIFICATE.
391
392 Copyright (C) 2019-2020 Ian Jackson and others
393
394 This program is free software: you can redistribute it and/or modify
395 it under the terms of the GNU Affero General Public License as
396 published by the Free Software Foundation, either version 3 of the
397 License, or (at your option) any later version.
398
399 This program is distributed in the hope that it will be useful,
400 but WITHOUT ANY WARRANTY; without even the implied warranty of
401 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
402 GNU Affero General Public License for more details.
403
404 You should have received a copy of the GNU Affero General Public License
405 along with this program.  If not, see <http://www.gnu.org/licenses/>.
406
407 Individual files generally contain the following tag in the copyright
408 notice, instead of the full licence grant text:
409 ```
410    SPDX-License-Identifier: AGPL-3.0-or-later
411 ```
412 As is conventional, this should be read as a licence grant.