Skip to content

Figure out how to manage future getrandom upgrades #792

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
KodrAus opened this issue Jan 29, 2025 · 27 comments
Open

Figure out how to manage future getrandom upgrades #792

KodrAus opened this issue Jan 29, 2025 · 27 comments

Comments

@KodrAus
Copy link
Member

KodrAus commented Jan 29, 2025

It looks like getrandom's 0.3.x release treats wasm targets a bit differently than 0.2.x. In uuid, we just require a js feature to support RNG in wasm32-unknown-unknown via getrandom, which sniffs out web crypto APIs. In 0.3.x, it looks like you need to set RUSTFLAGS to make this work. If we upgrade our version of getrandom, we'll break existing users of it via the js feature.

We may just need to vendor in the old getrandom impl, so long as we can still compile getrandom 0.3.x on wasm32-unknown-unknown without setting RUSTFLAGS.

@ChrisDenton
Copy link

Why not vendor in the new getrandom impl? That would allow skipping the environment variable check?

As far as I can see this crate only uses getrandom::getrandom (aka getrandom::fill in 0.3) so it seems like it'd be simple enough?

@KodrAus
Copy link
Member Author

KodrAus commented Feb 2, 2025

That looks like it could work 👍 If getrandom won’t compile for the wasm target without the RUSTFLAGS (I haven’t tried it yet) then we might be able to cfg it out for that target. It would depend on how that interacts with optional feature enablement.

So, I think we just have to try something and see how it works out.

@ChrisDenton
Copy link

Ok, so to sum up, the official way to do this in getrandom 0.3 is to simply change from the js feature to the wasm_js feature in Cargo.toml:

- js = ["dep:wasm-bindgen", "getrandom?/js"]
+ js = ["dep:wasm-bindgen", "getrandom?/wasm_js"]

But then to actually use it the end user targetting wasm32-unknown-unknown has to have a config.toml containing:

[target.wasm32-unknown-unknown]
rustflags = ['--cfg', 'getrandom_backend="wasm_js"']

Otherwise no getrandom backend will be found and a compile_error! message explaining the issue will be emitted with a link to the getrandom docs:

error: The wasm32-unknown-unknown targets are not supported by default; you may need to enable the "wasm_js" configuration flag. Note that enabling the wasm_js feature flag alone is insufficient. For more information see: https://docs.rs/getrandom/#webassembly-support


So one option would be for uuid to add a target.cfg to the getrandom dependency and then vendor the wasm-js file for wasm32-unknown-unknown specifically. I think this will work with optional features.

The other option would of course be to not do anything special because people will probably need to add the --cfg in any case as they update other dependencies that rely on getrandom (either directly or indirectly). This is less desirable but maybe inevitable?

@KodrAus
Copy link
Member Author

KodrAus commented Feb 2, 2025

I think it was a bit of a lazy mistake on my part for us to rely so directly on getrandom to support WASM, so I'm keen to disentangle uuid from it. While getrandom is unstable there's no guarantee the mechanism it uses won't change again in the future, which they're fully entitled to do.

So one option would be for uuid to add a target.cfg to the getrandom dependency and then vendor the wasm-js file for wasm32-unknown-unknown specifically. I think this will work with optional features.

This sounds like it should work 👍 We can then also call out in our docs that uuid doesn't guarantee getrandom will be used as a source of randomness, so configuring its backend is not guaranteed to affect UUID generation.

@ChrisDenton
Copy link

One other issue I just noticed is that the fast-rng feature uses rand::random which will suffer from the same issue.

@KodrAus
Copy link
Member Author

KodrAus commented Feb 4, 2025

On WASM I think we can make that feature a no-op and continue to use our vendored code instead. It's mostly useful on Windows where the system crypto APIs are surprisingly slow

@ianthetechie
Copy link

That seems logical... I ended up accidentally stumbling on this after going down a bit of a rabbit hole to upgrade some dependencies today 😅 (Unfortunately, I do currently have to maintain a direct dependency on getrandom for a wasm build of a library, but I also depend on UUID, and upgrading with feature changes broke my cargo config as there are now 2 getrandom deps in my tree; one from uuid and one explicit).

@KodrAus
Copy link
Member Author

KodrAus commented Feb 4, 2025

I'm working through this now 👍 I think the scenarios we're still likely to break are those using getrandom on wasm32-unknown-unknown that are actually setting a source for getrandom. If we hit any of those I think we should be able to find a workaround.

@VorpalBlade
Copy link

Won't this still break it for no-std that isn't wasm? E.g microcontrollers. We sometimes have to deal with UUIDs in network protocols still. I don't personally need the rng, but I see no reason you couldn't hook it up to a simple shift register or a true hardware rng on a microcontroller if your project needs that.

Perhaps you should simply consider bumping your own major version instead? That seems like the only right way to do this.

@KodrAus
Copy link
Member Author

KodrAus commented Feb 4, 2025

uuid is a widely used public dependency so bumping our major version and forking the Uuid type would be a much worse state of affairs for everyone.

Users in other no-std environments can still upgrade getrandom too and follow its new docs, since we do technically still use it, but I’d also be interested to explore an API in uuid itself to configure its source of randomness, and possibly time too so we don’t rely on a common unstable dependency to wire this up.

@mitsuhiko
Copy link

So I ran into the same problem outside of uuid and I'm not sure how to progress here. It surely can't be the solution that everybody implements their own version of getrandom. Maybe this is the point where some folks could go together and build a more aligned getrandom replacement with clearly defined goals so that it can become a foundation to uuid and other crates?

@KodrAus
Copy link
Member Author

KodrAus commented Feb 4, 2025

@mitsuhiko The piece that’s missing here is a stable interface to configure randomness on platforms that don’t have an obvious source. That seems like something we could all solve in a way that’s independent of getrandom’s own semver releases.

Yeh it would be a terrible midpoint for everyone to go and define their own interface. It would make trying to configure a project of any meaningful size on a non-standard platform a total pain.

@KodrAus
Copy link
Member Author

KodrAus commented Feb 4, 2025

For this release and getrandom 0.3, we're going to kick the can down the road. If you're using getrandom in a no-std environment, you can update your version of it and things will continue to work as they did before. Independently, we should look at what a stable interface for configuring randomness may look like, which might involve enshrining how getrandom does it, something in the standard library, or something entirely different. We'll try figure that out before we catch up to the can.

If you're specifically in wasm32-unknown-unknown, but not in an environment with JS to use the js feature, and want to use v4/v7 features of uuid, then we can use some Cargo trickery to make that possible via getrandom too, without breaking the existing js feature. We'd basically create a shim crate that re-exports getrandom, and depend on that in wasm32-unknown-unknown when some rng-getrandom feature of uuid is enabled.

@KodrAus KodrAus changed the title Figure out how to upgrade getrandom to 0.3 Figure out how to manage future getrandom upgrades Feb 5, 2025
@ChrisDenton
Copy link

Perhaps it would be useful to have UUID functions that take a random source? So people can use uuid v4/v7 without the rng feature. It's not a full solution and would come at the cost of people needing to thread an rng through their code but for those with bespoke needs it might be the most versatile design.

@KodrAus
Copy link
Member Author

KodrAus commented Feb 5, 2025

@ChrisDenton, this actually is supported via a type called Builder. In hindsight, I think we would’ve been better off not having any high-level constuctors on the Uuid type itself, and instead just exposed ways to extract and manipulate its fields. That would’ve made versioning it a lot simpler so we could do major version bumps of uuid that all used the same Uuid type, or relegated those constructors to other crates that could be unstable, like uuidv4 etc.

@Andrepuel
Copy link

uuid is a widely used public dependency so bumping our major version and forking the Uuid type would be a much worse state of affairs for everyone.

Just food for though. IMHO it seems that the root of the issue is that generating the Uuid and it's representation reside in the same crate. Representing Uuid is very static and unlikely to change, but generating v4 and v7 may vary widely.

In fact, if I recall correctly, v7 generator has to rely on thread local (or global) state. That seems too much for a crate that is so basic (as in, being tue base for a lot of other things).

@KodrAus
Copy link
Member Author

KodrAus commented Feb 9, 2025

@Andrepuel This is basically the problem, specifically that all this functionality lives on the Uuid type itself. We could still maintain a single Uuid type if we had free-functions for construction, like uuid::new_v4() by re-exporting the same Uuid type on each version.

At this stage though the ship has sailed on those kinds of changes. I'm not planning any major version of uuid anytime in the foreseeable future.

@heaths
Copy link

heaths commented Feb 11, 2025

We hit this problem and the changes to depend instead on the wasm_js feature almost work, except that we have other dependencies in our workspace that depend on older getrandom versions that actually err when you have:

[target.wasm32-unknown-unknown]
rustflags = ['--cfg', 'getrandom_backend="wasm_js"']

Yields,

error: the wasm*-unknown-unknown targets are not supported by default, you may need to enable the "js" feature. For more information see: https://docs.rs/getrandom/#webassembly-support
   --> /home/heaths/.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.2.15/src/lib.rs:342:9
    |
342 | /         compile_error!("the wasm*-unknown-unknown targets are not supported by \
343 | |                         default, you may need to enable the \"js\" feature. \
344 | |                         For more information see: \
345 | |                         https://docs.rs/getrandom/#webassembly-support");
    | |________________________________________________________________________^

error[E0433]: failed to resolve: could not find `RngImp` in `imp`
   --> /home/heaths/.cargo/registry/src/index.crates.io-6f17d22bba15001f/uuid-1.13.1/src/rng.rs:10:10
    |
10  |     imp::RngImp::u128()
    |          ^^^^^^ could not find `RngImp` in `imp`

There are a few crates with getrandom 0.1 and 0.2 that I can file bugs on, but any way to otherwise work around this? I think we can also kick the can down the road if I roll back the updates to Cargo.lock, but it's only a matter of time.

Found some discussion getrandom at rust-random/getrandom#438. At least, gets into it a bit. Seems decisions were spread across several issues.

@KodrAus
Copy link
Member Author

KodrAus commented Feb 12, 2025

@heaths Ah, on wasm32-unknown-unknown the uuid library doesn’t actually depend on getrandom anymore, and without the js feature enabled it doesn’t have a fallback to use and fails to compile.

You should be able to fix the uuid issue by adding the js feature, which is a no-op on non-wasm platforms. Alternatively, you can add the rng-getrandom feature to uuid to force it to use getrandom, but this will mean you then have multiple versions of getrandom in your tree again. I think you could possibly make this work:

[dependencies.uuid]
version = “1.13”
features = [“v4”, “rng-getrandom”]

[dependencies.getrandom_v03]
package = “getrandom”
version = “0.3”
features = [“wasm-js”]

[dependencies.getrandom_v02]
package = “getrandom”
version = “0.2”
features = [“js”]

@heaths
Copy link

heaths commented Feb 12, 2025

Thanks. That gives me some options to try. I did add multiple versions similar to what you have above, but the RUSTFLAGS passed broken 0.2. That was when the error in my comment above was displayed. Seemed to fix the 0.3.0 issue.

Fortunately, I was able to roll back the updates to Cargo.lock and will, like you said above, kick the can down the road. I want to try to remove a few dependencies from our default feature sets anyway, so maybe that will help at least in those cases.

@KodrAus
Copy link
Member Author

KodrAus commented Feb 12, 2025

When I tested a wasm build using both 0.2 and 0.3 of getrandom using that method it did work 🤔 Did you have the js feature of getrandom 0.2 enabled when you tried it?

@heaths
Copy link

heaths commented Feb 12, 2025

Yeah, but we also have a ton of dependencies in a monorepo/workspace that may factor in somehow. I can create a simple little scratch workspace and try it when I catch up to the can I kicked down the road.

@anhelinakruk
Copy link

anhelinakruk commented Feb 14, 2025

Hi! I'm encountering an issue when building my Rust project for wasm32-unknown-unknown. My project does not directly depend on getrandom, uuid, or rand, but it does use surrealdb and many popular crates, which depends on them internally.

I get the same error, during compilation:

error: The wasm32-unknown-unknown targets are not supported by default; you may need to enable the "wasm_js" configuration flag. Note that enabling the 'wasm_js' feature flag alone is insufficient. For more information see: https://docs.rs/getrandom/#webassembly-support
   --> /Users/anhelinakruk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.3.1/src/backends.rs:159:9
    |
159 | /         compile_error!(
160 | |             "The wasm32-unknown-unknown targets are not supported by default; \
161 | |             you may need to enable the \"wasm_js\" configuration flag. Note \
162 | |             that enabling the 'wasm_js' feature flag alone is insufficient. \
163 | |             For more information see: \
164 | |             https://docs.rs/getrandom/#webassembly-support"
165 | |         );
    | |_________^

error[E0425]: cannot find function 'fill_inner' in module 'backends'
  --> /Users/anhelinakruk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.3.1/src/lib.rs:98:19
   |
98 |         backends::fill_inner(dest)?;
   |                   ^^^^^^^^^^ not found in 'backends'

I have already attempted the fixes you suggest, but none resolved the issue in my case. What would be the best way to resolve this problem?

@jareksgit
Copy link

@anhelinakruk

I have a running leptos 0.7.7 surrealdb 2.2.0 application. Try this both things as described before:

In your global .cargo add a config.toml (if not already present) with the following content. Maybe it also could be placed locally in your application.

[target.wasm32-unknown-unknown]
rustflags = ['--cfg', 'getrandom_backend="wasm_js"']

Then update your local Cargo.toml with this dependencies:

[dependencies.uuid]
version = “1.13”
features = [“v4”, “rng-getrandom”]

[dependencies.getrandom_v03]
package = “getrandom”
version = “0.3”
features = [“wasm-js”]

[dependencies.getrandom_v02]
package = “getrandom”
version = “0.2”
features = [“js”]

@whois-marvin-42
Copy link

(...) Maybe it also could be placed locally in your application (...)

Per Rust docs: just create a .cargo (sub)folder (with your config.toml inside) in your app root folder (aka same level as your Cargo.toml)

= clean (per project/app) workaround for the issues affecting (for now) contexts like Leptos, Dioxus, ... (and also quite useful for a few other crates faking data).

@anhelinakruk
Copy link

anhelinakruk commented Feb 14, 2025

@jareksgit

I've just created new leptos project and added to dependencies only surrealdb. Then I did everything as you suggest and am getting this warning by rust-analyzer:

Error: at '/Users/anhelinakruk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cargo-leptos-0.2.27/src/lib.rs:44:76'

Caused by:
    'cargo metadata' exited with an error: error: failed to select a version for 'getrandom'.
        ... required by package 'leptos-axum-workspace v0.1.0 (/Users/anhelinakruk/Desktop/visoft/leptos-axum-workspace)'
    versions that meet the requirements `^0.3` (locked to 0.3.1) are: 0.3.1
    
    the package 'leptos-axum-workspace' depends on 'getrandom', with features: 'wasm-js' but 'getrandom' does not have these features.
    
    
    failed to select a version for 'getrandom' which could resolve this conflict

Did you have the same?

@anhelinakruk
Copy link

Okey, I figured out that it should be wasm_js feature, not wasm-js. Now it works, thanks @jareksgit !

elebihan added a commit to elebihan/artifex that referenced this issue Mar 16, 2025
Executing 'cargo update' will fetch new versions of uuid and getrandom
which will cause artifex-batch to fail to build for the target
wasm32-unknown-unknown:

```sh
cargo build -p artifex-batch --target wasm32-unknown-unknown
```

So update the crates and the build options. See [1], [2].

[1] uuid-rs/uuid#792
[2] https://docs.rs/getrandom/latest/getrandom/#webassembly-support
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants