You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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?"
8
8
+++
9
9
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**.
11
11
12
-
# What happened
12
+
# What Happened
13
13
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**:
15
15
16
16
```sh
17
17
cargo:warning=In file included from vendor/basis_universal/encoder/pvpngreader.cpp:14:
@@ -21,25 +21,25 @@ cargo:warning= | ^~~~~~~~~~
21
21
cargo:warning=1 error generated.
22
22
```
23
23
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**.
25
25
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:
27
27
28
28
> Bindings for Binomial LLC's basis-universal Supercompressed GPU Texture Codec
29
29
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:
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?
35
35
36
-
Let's find the cause for this.
36
+
Let's dive right in and find out!
37
37
38
-
# How to find the cause
38
+
# How to Find the Cause
39
39
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.
41
41
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`:
43
43
44
44
```sh
45
45
│ │ ├── 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
49
49
│ │ │ │ │ └── cc v1.2.3 (*)
50
50
```
51
51
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.
53
53
54
54
> Cargo will enable the minimum subset of `features` needed so that every dependency using `bevy` gets the features they ask for.
55
55
56
-
The question therefore is: Which crate asks for this feature?
56
+
The question therefore is, which crate enables this feature?
57
57
58
58
# Playing Cargo Feature Detective
59
59
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.
61
61
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:
63
63
64
64
```sh
65
65
├── winit v0.30.5
@@ -79,7 +79,7 @@ Running `cargo tree -e features` in our repository root we get over 3.000 lines
79
79
│ │ └── tracing-attributes v0.1.28 (proc-macro)
80
80
```
81
81
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"`:
83
83
84
84
```sh
85
85
├── bevy_libgdx_atlas feature "default"
@@ -88,12 +88,12 @@ Luckily we now know already what feature we are looking for: `basis-universal`,
88
88
│ │ ├── bevy v0.15.0 (*)
89
89
```
90
90
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).
92
92
93
-
## Improving ergonomics
93
+
## Improving Ergonomics
94
94
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:
97
97
98
98
```sh
99
99
├── 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
104
104
105
105
# Conclusion
106
106
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.
108
108
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:
110
110
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).
114
114
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!
116
116
117
117
---
118
118
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