Skip to content

Commit c923c21

Browse files
authored
Polish up the Feature Debugging post (#9)
1 parent 89b1688 commit c923c21

File tree

1 file changed

+29
-29
lines changed
  • content/blog/2024/12-12-rust-feature-debugging

1 file changed

+29
-29
lines changed
Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
+++
2-
title = "Rust crate feature debugging"
2+
title = "Rust Crate Feature Debugging"
33
date = 2024-12-12
44
[extra]
55
tags=["rust","bevy","cargo"]
66
hidden = true
7-
custom_summary = "Figure out what enabled a feature in a crate in your dependencies breaking your build."
7+
custom_summary = "Want to figure out what dependency enabled a feature which breaks your build?"
88
+++
99

10-
In this short post we look at how to debug a recent build breakage we encountered due to a *feature* being enabled on one of our dependencies that is not compatible with our build target: **wasm**.
10+
In this short post, we will look at how we recently debugged a build breaking due to a *feature* being enabled on one of our dependencies that is not compatible with one of our build targets: **Wasm**.
1111

12-
# What happened
12+
# What Happened
1313

14-
After porting our bevy based game [tinytakeoff](https://tinytakeoff.com) to the newest Bevy release: [0.15](https://bevyengine.org/news/bevy-0-15/) our build broke with the following error on **wasm**:
14+
After porting our Bevy-based game, [TinyTakeoff](https://tinytakeoff.com) to the newest Bevy release at the time of writing this, [0.15](https://bevyengine.org/news/bevy-0-15/), our build broke with the following error on **Wasm**:
1515

1616
```sh
1717
cargo:warning=In file included from vendor/basis_universal/encoder/pvpngreader.cpp:14:
@@ -21,25 +21,25 @@ cargo:warning= | ^~~~~~~~~~
2121
cargo:warning=1 error generated.
2222
```
2323

24-
So it looks like some crate is trying to build C-code under the hood which depends on `stdlib.h`. That is not a problem on native build targets but it won't fly on **wasm**.
24+
Looks like some crate is trying to build C-code under the hood, which depends on `stdlib.h`. That is not a problem on native build targets, but it won't work on **Wasm**.
2525

26-
This happens in the `basis-universal` crate, what could that be good for? Reading up on it's [crates.io page](https://crates.io/crates/basis-universal) we find out that it is:
26+
This happens in the `basis-universal` crate. Wonder what that is for? Reading up on its [crates.io page](https://crates.io/crates/basis-universal), we can see that it is:
2727

2828
> Bindings for Binomial LLC's basis-universal Supercompressed GPU Texture Codec
2929
30-
Looking into the [Bevy Migration Guide for 0.14 to 0.15](https://bevyengine.org/learn/migration-guides/0-14-to-0-15) we find exactly one [place](https://bevyengine.org/learn/migration-guides/0-14-to-0-15/#add-feature-requirement-info-to-image-loading-docs) of it being mentioned:
30+
Looking into the [Bevy Migration Guide for 0.14 to 0.15](https://bevyengine.org/learn/migration-guides/0-14-to-0-15) we find exactly one [place](https://bevyengine.org/learn/migration-guides/0-14-to-0-15/#add-feature-requirement-info-to-image-loading-docs) where it is mentioned:
3131

3232
<img src="screen1.png" alt="changelog screenshot" class="centered" style="max-width: 70%"/>
3333

34-
So this dependency is for sure nothing we need as we did not start making use of said image format. How did it get introduced?
34+
So, this dependency is nothing that we need or want, given we are not making use of that image format. How did it get introduced into our dependencies in the first place?
3535

36-
Let's find the cause for this.
36+
Let's dive right in and find out!
3737

38-
# How to find the cause
38+
# How to Find the Cause
3939

40-
We first want to find out where in our tree of dependencies this one is used. `cargo tree` is the tool to help you analyze your dependencies as the graph structure they make up.
40+
We first want to find out _where_ in our dependency tree that `basis-universal` is brought in from. `cargo tree` is the tool to help you analyze your dependencies by showing them in a nifty graph structure.
4141

42-
When running `cargo tree` we get over 1.000 lines of output where we can search for `basis-universal`:
42+
When running `cargo tree`, we get over 1.000 outputted lines that we have to search, for somewhere inside this haystack is `basis-universal`:
4343

4444
```sh
4545
│ │ ├── bevy_image v0.15.0
@@ -49,17 +49,17 @@ When running `cargo tree` we get over 1.000 lines of output where we can search
4949
│ │ │ │ │ └── cc v1.2.3 (*)
5050
```
5151

52-
We got a winner. It is used by `bevy_image`. The problem is that we do not know why. Based on the changelog linked above we know it is supposed to be behind a `feature` flag called `basis_universal`, looking at our `Cargo.toml` we do not enable it though.
52+
We got a winner! It is used by `bevy_image`. The problem now is that we do not know why `bevy_image` is suddenly bringing this in. Based on the changelog linked above, we know it is supposed to be behind a `feature` flag on the `bevy` crate, called `basis_universal`. Looking at our `Cargo.toml`, we don't enable it.
5353

5454
> Cargo will enable the minimum subset of `features` needed so that every dependency using `bevy` gets the features they ask for.
5555
56-
The question therefore is: Which crate asks for this feature?
56+
The question therefore is, which crate enables this feature?
5757

5858
# Playing Cargo Feature Detective
5959

60-
There is a little-known feature in `cargo tree` that allows us to not only see our dependency tree but also the features that are enabled in each crate.
60+
There is a little-known feature in `cargo tree` that allows us to not only see our dependency tree, but also the features that are enabled in each crate that is pulled in.
6161

62-
Running `cargo tree -e features` in our repository root we get over 3.000 lines of this:
62+
Running `cargo tree -e features` in our repository root, we get over 3.000 lines of this:
6363

6464
```sh
6565
├── winit v0.30.5
@@ -79,7 +79,7 @@ Running `cargo tree -e features` in our repository root we get over 3.000 lines
7979
│ │ └── tracing-attributes v0.1.28 (proc-macro)
8080
```
8181

82-
Luckily we now know already what feature we are looking for: `basis-universal`, so let's search for `bevy feature "basis-universal"`:
82+
Luckily, we now know what feature we are looking for, `basis-universal`. So, let's search for `bevy feature "basis-universal"`:
8383

8484
```sh
8585
├── bevy_libgdx_atlas feature "default"
@@ -88,12 +88,12 @@ Luckily we now know already what feature we are looking for: `basis-universal`,
8888
│ │ ├── bevy v0.15.0 (*)
8989
```
9090

91-
Here we go. Our own crate `bevy_libgdx_atlas` enables the feature `basis-universal` which in turn enables the dependency `basis-universal` which breaks our build on **wasm**. That makes it easier to fix. Funny enough it was used to enable `bevy_image` while trying to depend on the smallest subset of features of `bevy`. This is a known issue in Bevy 0.15, see [#16563](https://github.com/bevyengine/bevy/issues/16563). But there is a cleaner workaround by just enabling the `bevy_image` feature in `bevy_internal` see [here](https://github.com/rustunit/bevy_libgdx_atlas/commit/20cb2e99ef8dd696dfbbff3ef120591cae82703b).
91+
There we go, and would you look at that? One of our own crates, `bevy_libgdx_atlas`, enables the feature `basis-universal`, which in turn enables the dependency `basis-universal`, which then breaks our build on **Wasm**. At least it being our own crate will make it easier to fix this time around. Funnily enough, it was used to enable `bevy_image` while trying to depend on the smallest subset of features of `bevy`. This is a known issue in Bevy 0.15, see [#16563](https://github.com/bevyengine/bevy/issues/16563), but, luckily, there is a cleaner workaround to this issue. You just need to enable the `bevy_image` feature in `bevy_internal` see [here](https://github.com/rustunit/bevy_libgdx_atlas/commit/20cb2e99ef8dd696dfbbff3ef120591cae82703b).
9292

93-
## Improving ergonomics
93+
## Improving Ergonomics
9494

95-
In case you run into multiple crates doing this and depending on said feature it is more ergonomic to invert the tree using: `cargo tree -e features -p bevy --invert`.
96-
With this we limit our root to `bevy` and we will find *one* entry for the feature and a subtree of dependencies using it:
95+
In case you run into multiple crates enabling an unwanted feature, it can be more ergonomic to invert the tree using: `cargo tree -e features -p bevy --invert`.
96+
With this command, we limit our root to `bevy`, and we will find *one* entry for the feature, and a subtree of dependencies using it:
9797

9898
```sh
9999
├── bevy feature "basis-universal"
@@ -104,16 +104,16 @@ With this we limit our root to `bevy` and we will find *one* entry for the featu
104104

105105
# Conclusion
106106

107-
The feature option in `cargo tree` is a very powerful tool in fighting against the subtle way dependencies and features in them can creep into your codebase.
107+
The feature option in `cargo tree` is a powerful tool in fighting against the subtle ways that dependencies, and the features enabled by them, can creep into your codebase.
108108

109-
Since it is close to Christmas I want to make a wishlist to improve the situation:
109+
Since it is close to Christmas, I want to make a small wishlist to improve the situation:
110110

111-
1. A `cargo deny` like tool that allows me to white/blacklist features in dependencies.
112-
2. `cargo tree` should generate a computer-readable format (ron/json whatever) to facilitate point 1.
113-
3. In a perfect world there would be a `cargo tree-tui` allowing to interactively inspect dependencies, their features, and fan in (who uses it) and fan out (what it is using).
111+
1. A `cargo deny`-like tool that allows me to whitelist, and or blacklist, features in dependencies.
112+
2. `cargo tree` should generate a computer-readable format (RON, JSON, or whatever) to help with the first point.
113+
3. In a perfect world, there would be a `cargo tree-tui` allowing me to interactively inspect dependencies, their features, and fan in (who uses it) and fan out (what it is using).
114114

115-
That being said `cargo tree` seems underutilized, so go and run it on your Bevy project to figure out what features of dependencies like Bevy you actually compile. This can have a huge impact on your wasm binary size!
115+
That being said, `cargo tree` seems underused, so go and run it on your Bevy project yourself and see what features of dependencies like Bevy you actually compile. This can have a huge impact on your Wasm binary size!
116116

117117
---
118118

119-
Do you need support building your Bevy or Rust project? Our team of experts can support you! [Contact us.](@/contact.md)
119+
Do you need support building your Bevy or Rust project? Our team of experts can support you! [Contact us.](@/contact.md)

0 commit comments

Comments
 (0)