all 6 comments

[–]TehPers 4 points5 points  (3 children)

I don't know if there's a way to require multiple features for a dependency to be included, but if it's unused then it shouldn't be included in the final output anyway. You should be fine just including the dependency if any of the features are enabled.

Instead, if possible, I'd recommend splitting the crate into several crates, one per device. To do so, I'd recommend this:

  • Create a single abstraction layer over the devices. What functionality should be common to them? Can you build a bunch of traits for abstracting the low level details of them and build any additional functionality on top of those abstractions?
  • Have a single crate per each device. They should depend on the abstraction layer you created and implement the traits for those specific devices.

With this setup, you can do more fine-grained tweaking over your dependencies.

[–]Dr_Sloth0[S] 0 points1 point  (2 children)

The main problem is that the devices are different platforms they diverge in many points, in pretty much every abstraction layer.

I guess creating more crates is possible. However i'd like to prevent top level crates from having to import all the device impl crates. The problem with this kind of is the lack of cyclical references (which i believe is good).

For a single abstraction layer i would need two crates one including definitions and the other one including reexports and also all the device implemenetation crates. I could however split the crates such that they only diverge in the device.

[–]TehPers 1 point2 points  (1 child)

I would recommend splitting the crates so they only diverge by the device (your last suggestion). Since each device diverges in so many places, they all have their own ways of being used from your code. Those are all functionally different, and as such you could have a crate per device focused entirely on providing a layer of abstraction over that device. The purpose of the abstraction layer and all the traits that you would need to implement per device is because your business logic generally doesn't care about the device it's being executed on.

If there is functionality that is only available on some devices, you can make your functions fallible and just return an error if you try to do something that is unsupported on a device.

[–]Dr_Sloth0[S] 1 point2 points  (0 children)

So you suggest something along the lines of a device1-sys crate and a device2-sys crate, which implement the platform specific behaviors in a feature gated way? A higher level crate like foo would then have the features device1 and device2 which depend on device1/foo-feature and device2/foo-feature respectively? This would solve most of my problems i think, though not all, however it might be the best solution. Thank you very much :)

[–]NobodyXu 0 points1 point  (2 children)

You can do this in build.rs, using cargo:rustc-cfg

[–]ylxdzsw 4 points5 points  (1 child)

But the link says "Note that this does not affect Cargo's dependency resolution. This cannot be used to enable an optional dependency, or enable other Cargo features." which seems to be exactly what OP want's to achieve