Currrently I do have a library that uses Rust stdlib only, NO dependancies.
Reading about the no-std feature I think its a good idea to use no-std instead.
So I added #![no_std] at the top and tried to build and test it. This works
Now suppose in the future I need to a function that cannot be build without using stdlib.
Question:
How do I make this library future proof for now regardless of the future changes?
Sub-questions:
Is there some idiomatic concept to accomplish this?
Do I need features? If so, which one should be the default?
Also I would like a reason why if possible, so i can understand it better.
I think you should go #![no_std] now (the embedded guys will thank you) and add a std feature (or however else you want to call it) later when you ever need to add functionality that requires the standard library. That's also what the Cargo devs recommend. As to whether to enable the feature by default or not I'd probably decide on a crate-to-crate basis, though I believe (from my experience using the ecosystem) it is more common to explicitly disable standard-library-based functionality, rather than explicitly enabling it. OTOH, I think the more future proof thing to do in such a scenario would be to not modify the default features. The latter requires only a minor new release, the former a new mayor release IIRC—not too sure about the exact SemVer-related rules for default-features; but it would definitely be the nice thing not to break the dependents that don't disable your default features to continue to get your crate with #![no_std] support by default.
In addition to what @jofas said also notice, that if your library doesn't need OS, but could benefit from dynamic allocation, then you can just add alloc feature, that will enable the alloc crate. And then in your code you can import collections, smart pointers, etc. from alloc instead of std.
In both cases you can also benefit from enabling following clippy lints:
Which will warn you, when you are importing items from "more restricted" crates and thus limiting your library's functionality, when you could import them from the "less restricted" ones.
This is true, but I think largely because no_std support is often retrofitted, or because the library wants to implement a trait for std's types. If neither of those cases apply, then it would be reasonable and possibly beneficial to make the relevant feature non-default.
The disadvantage of default features is that it's easy to forget to disable them, and you can end up with a situation where every package in the dependency graph intends to allow no_std, but one of them has a spurious dependency on a default feature that ends up using std.
I decided to go for the no_std support only and new funtionality must comply to no-std too.
If there is a need for new functionality that can't live without std I will just create a new crate.
Reading you replies I think mixing std and no-std using features makes live more complicated.