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."
8
+
+++
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**.
11
+
12
+
# What happened
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**:
15
+
16
+
```sh
17
+
cargo:warning=In file included from vendor/basis_universal/encoder/pvpngreader.cpp:14:
18
+
cargo:warning=vendor/basis_universal/encoder/../transcoder/basisu.h:53:10: fatal error: 'stdlib.h' file not found
19
+
cargo:warning= 53 |#include <stdlib.h>
20
+
cargo:warning= | ^~~~~~~~~~
21
+
cargo:warning=1 error generated.
22
+
```
23
+
24
+
So that looks like some crate tries to build some c code under the hood. That is not a problem on native build targets but wont fly on **wasm**.
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:
27
+
28
+
> Bindings for Binomial LLC's basis-universal Supercompressed GPU Texture Codec
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:
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?
35
+
36
+
Let's find the cause for this.
37
+
38
+
# How to find the cause
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.
41
+
42
+
When running `cargo tree` we get get over 1.000 lines of output where we can search for `basis-universal`:
43
+
44
+
```sh
45
+
│ │ ├── bevy_image v0.15.0
46
+
│ │ │ ├── basis-universal v0.3.1
47
+
│ │ │ │ ├── basis-universal-sys v0.3.1
48
+
│ │ │ │ │ [build-dependencies]
49
+
│ │ │ │ │ └── cc v1.2.3 (*)
50
+
```
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.
53
+
54
+
> Cargo will enable the minimum subset of `features` needed so that every dependency using `bevy` get the features they ask for.
55
+
56
+
The question therefore is: Which crate asks for this feature?
57
+
58
+
# Playing Cargo Feature Detective
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.
61
+
62
+
Running `cargo tree -e features` in our repository root we get over 3.000 lines of this:
63
+
64
+
```sh
65
+
├── winit v0.30.5
66
+
│ ├── tracing v0.1.41
67
+
│ │ ├── tracing-core v0.1.33
68
+
│ │ │ └── once_cell feature "default"
69
+
│ │ │ ├── once_cell v1.20.2
70
+
│ │ │ └── once_cell feature "std"
71
+
│ │ │ ├── once_cell v1.20.2
72
+
│ │ │ └── once_cell feature "alloc"
73
+
│ │ │ ├── once_cell v1.20.2
74
+
│ │ │ └── once_cell feature "race"
75
+
│ │ │ └── once_cell v1.20.2
76
+
│ │ ├── pin-project-lite feature "default"
77
+
│ │ │ └── pin-project-lite v0.2.15
78
+
│ │ └── tracing-attributes feature "default"
79
+
│ │ └── tracing-attributes v0.1.28 (proc-macro)
80
+
```
81
+
82
+
Luckily we know know already what feature we are looking for: `basis-universal`, so lets search for `bevy feature "basis-universal"`:
83
+
84
+
```sh
85
+
├── bevy_libgdx_atlas feature "default"
86
+
│ └── bevy_libgdx_atlas v0.3.0
87
+
│ ├── bevy feature "basis-universal"
88
+
│ │ ├── bevy v0.15.0 (*)
89
+
```
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 in Bevy 0.15, see [issue #16563](https://github.com/bevyengine/bevy/issues/16563). But there is a cleaner workaround by just enabling the `bevy_image` feature.
92
+
93
+
## Improving ergonomics
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:
97
+
98
+
```sh
99
+
├── bevy feature "basis-universal"
100
+
│ └── bevy_libgdx_atlas v0.3.0
101
+
│ └── bevy_libgdx_atlas feature "default"
102
+
│ └── tinytakeoff v0.1.1
103
+
```
104
+
105
+
# Conclusion
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.
108
+
109
+
Since it is close to christmas I want to make a whishlist to improve the situation:
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).
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!
116
+
117
+
---
118
+
119
+
Do you need support building your Bevy or Rust project? Our team of experts can support you! [Contact us.](@/contact.md)
<metaname="description" content="Rustunit offers software development consulting with a focus on rust, game-development and large scale distributed backend services.">
<p>In this short post we look at how to debug a recent build breakage we encountered due to a <em>feature</em> being enabled on one of our dependencies that is not compatible with our build target: <strong>wasm</strong>.</p>
35
+
<h1id="what-happened">What happened</h1>
36
+
<p>After porting our bevy based game <ahref="https://tinytakeoff.com">tinytakeoff</a> to the newest Bevy release: <ahref="https://bevyengine.org/news/bevy-0-15/">0.15</a> our build broke with the following error on <strong>wasm</strong>:</p>
37
+
<predata-lang="sh" style="background-color:#212121;color:#eeffff;" class="language-sh "><codeclass="language-sh" data-lang="sh"><span>cargo:warning</span><spanstyle="color:#89ddff;">=</span><spanstyle="color:#c3e88d;">In </span><spanstyle="color:#82aaff;">file included from vendor/basis_universal/encoder/pvpngreader.cpp:14:
38
+
</span><span>cargo:warning</span><spanstyle="color:#89ddff;">=</span><spanstyle="color:#c3e88d;">vendor/basis_universal/encoder/../transcoder/basisu.h:53:10: </span><spanstyle="color:#82aaff;">fatal error: </span><spanstyle="color:#89ddff;">'</span><spanstyle="color:#c3e88d;">stdlib.h</span><spanstyle="color:#89ddff;">'</span><spanstyle="color:#82aaff;"> file not found
<p>So that looks like some crate tries to build some c code under the hood. That is not a problem on native build targets but wont fly on <strong>wasm</strong>.</p>
44
+
<p>This happens in the <code>basis-universal</code> crate, what could that be good for? Reading up on it's <ahref="https://crates.io/crates/basis-universal">crates.io page</a> we find out that it is:</p>
45
+
<blockquote>
46
+
<p>Bindings for Binomial LLC's basis-universal Supercompressed GPU Texture Codec</p>
47
+
</blockquote>
48
+
<p>Looking into the <ahref="https://bevyengine.org/learn/migration-guides/0-14-to-0-15">Bevy Migration Guide for 0.14 to 0.15</a> we find exactly one <ahref="https://bevyengine.org/learn/migration-guides/0-14-to-0-15/#add-feature-requirement-info-to-image-loading-docs">place</a> of it being mentioned:</p>
<p>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?</p>
51
+
<p>Let's find the cause for this.</p>
52
+
<h1id="how-to-find-the-cause">How to find the cause</h1>
53
+
<p>We first want to find out where in our tree of dependencies this one is used. <code>cargo tree</code> is the tool to help you analyze your dependencies as the graph structure they make up.</p>
54
+
<p>When running <code>cargo tree</code> we get get over 1.000 lines of output where we can search for <code>basis-universal</code>:</p>
</span><spanstyle="color:#82aaff;">│ │ │ │ │ └── cc v1.2.3 (</span><spanstyle="color:#89ddff;">*</span><span>)
60
+
</span></code></pre>
61
+
<p>We got a winner. It is used by <code>bevy_image</code>. The problem is that we do not know why. Based on the changelog linked above we know it is supposed to be behind a <code>feature</code> flag called <code>basis_universal</code>, looking at our <code>Cargo.toml</code> we do not enable it though.</p>
62
+
<blockquote>
63
+
<p>Cargo will enable the minimum subset of <code>features</code> needed so that every dependency using <code>bevy</code> get the features they ask for.</p>
64
+
</blockquote>
65
+
<p>The question therefore is: Which crate asks for this feature?</p>
<p>There is a little known feature in <code>cargo tree</code> that allows us to not only see our dependency tree but also the features that are enabled in each crate.</p>
68
+
<p>Running <code>cargo tree -e features</code> in our repository root we get over 3.000 lines of this:</p>
<p>Luckily we know know already what feature we are looking for: <code>basis-universal</code>, so lets search for <code>bevy feature "basis-universal"</code>:</p>
<p>Here we go. Our own crate <code>bevy_libgdx_atlas</code> enables the feature <code>basis-universal</code> which in turn enables the dependency <code>basis-universal</code> which breaks our build on <strong>wasm</strong>. That makes it easier to fix. Funny enough it was used to enable <code>bevy_image</code> while trying to depend on the smallest subset of features of <code>bevy</code>. This is a known in Bevy 0.15, see <ahref="https://github.com/bevyengine/bevy/issues/16563">issue #16563</a>. But there is a cleaner workaround by just enabling the <code>bevy_image</code> feature.</p>
<p>In case you run into multiple crates doing this and depending on said feature it is more ergonomic to invert the tree using: <code>cargo tree -e features -p bevy --invert</code>.
94
+
With this we limit our root to <code>bevy</code> and we will find <em>one</em> entry for the feature and a subtree of dependencies using it:</p>
<p>The feature option in <code>cargo tree</code> is a very powerful tool in fighting against the subtle way dependencies and features in them can creep into your codebase.</p>
102
+
<p>Since it is close to christmas I want to make a whishlist to improve the situation:</p>
103
+
<ol>
104
+
<li>A <code>cargo deny</code> like tool that allows me to white/blacklist features in dependencies.</li>
105
+
<li><code>cargo tree</code> should generate a computer readable format (ron/json whatever) to facilitate point 1.</li>
106
+
<li>In a perfect world there would be a <code>cargo tree-tui</code> allowing to interactively inspect dependencies, their features and fan in (who uses it) and fan out (what it is using).</li>
107
+
</ol>
108
+
<p>That being said <code>cargo tree</code> 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!</p>
109
+
<hr/>
110
+
<p>Do you need support building your Bevy or Rust project? Our team of experts can support you! <ahref="https://rustunit.com/contact/">Contact us.</a></p>
0 commit comments