Skip to content

Commit 55e498a

Browse files
bors[bot]Johnathan Van Why
and
Johnathan Van Why
authored
Merge #297
297: Add a cargo features doc. r=jrvanwhy a=jrvanwhy [Rendered](https://github.com/jrvanwhy/libtock-rs/blob/features-doc/doc/CargoFeatures.md) This doc describes the issue we've discovered with using cargo features from a workspace, and discusses an alternative that `libtock-rs` developers can use to avoid it. It stems from this code review discussion from several weeks ago: #283 (comment) Co-authored-by: Johnathan Van Why <[email protected]>
2 parents d903bcb + ebc3d5f commit 55e498a

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

doc/CargoFeatures.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
Cargo Features
2+
==============
3+
4+
On the surface, `cargo`'s
5+
[features](https://doc.rust-lang.org/cargo/reference/features.html) mechanism
6+
looks great for `libtock-rs`. Process binary crates can depend on `libtock-rs`,
7+
and use `cargo` features to specify which optional `libtock-rs` functionality
8+
they want.
9+
10+
However, `cargo` assumes that it can compile a crate with features that a binary
11+
does not need. This isn't necessarily true for embedded crates, where process
12+
binary authors care about the app size.
13+
14+
## Process Binaries in a Workspace
15+
16+
When used with workspaces, `cargo` features can result in excess code being
17+
built into a repository.
18+
19+
For example, suppose that `libtock` exposes a `malloc` feature, which adds a
20+
dynamic memory allocator. Then if a `libtock` user creates a `cargo` workspace
21+
with the following process binaries in it:
22+
23+
1. `no_malloc`, which depends on `libtock` and does not depend on the `malloc`
24+
feature.
25+
2. `malloc`, which depends on `libtock` and the `malloc` feature.
26+
27+
With this setup, `malloc` will always work correctly. Also, if you run `cargo
28+
build -p no_malloc`, then `no_malloc` will correctly build without a memory
29+
allocation.
30+
31+
Seems optimal, right?
32+
33+
It's not: if you build the entire workspace with `cargo build --workspace`,
34+
`libtock` will only be built once, with the `malloc` feature! That will result
35+
in a `no_malloc` process binary that contains a memory allocator, which is not
36+
what the author desired.
37+
38+
## Alternative to `cargo` Features
39+
40+
In many cases, `cargo` features can be replaced by splitting a crate up into
41+
smaller crates, and letting process binaries choose what to depend on. For
42+
example, memory allocation can be in a separate crate that process binaries
43+
depend on if and only if they need memory allocation.
44+
45+
Here are some questions to help guide the decision between using a `cargo`
46+
feature and separate crates:
47+
48+
1. Do you forsee a single user writing multiple process binaries, some of which
49+
use this feature? If yes, then maybe it should not be a `cargo` feature.
50+
2. Will the compiler optimize the feature away entirely if it is included but
51+
unused? If yes, then making it a `cargo` feature is probably fine.
52+
53+
In many cases, it will make sense to add a `cargo` feature to `libtock` but use
54+
optional crates to implement the feature internally. This way, users with
55+
multiple process binaries in a workspace can choose whether each process binary
56+
depends on the optimal crate.

0 commit comments

Comments
 (0)