-
Notifications
You must be signed in to change notification settings - Fork 673
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
Figure out the future of nix #190
Comments
cc @alexcrichton (possibly relevant for liblibc plans?) |
I’m not sure what the best approach is here but here are few thoughts I had:
This is possible within a single crate if you wanted to give others ability to merge pull requests. Multiple crates would give finer control e.g. someone can have permission to merge ioctl changes but not fcntl changes.
Awesome.
This is something to discuss in terms of developing nix but I think single crate or multiple crates this still imposes multiple styles on users of the crate. |
@joekain My proposal would be to keep all the code in the same git repository, but to release individual crates to |
@alexcrichton also mentioned that he had a goal of generating all the constants / unsafe FFI definitions needed for nix in the the |
Ah and to clarify, I'm not sure we'll be generating the |
Thanks for bringing this up @carllerche. I am in favor of your proposal to retain a single git repository for the "official" nix libraries in order to provide consistency but breaking out subsystems into discrete crates that are largely independent (with the exception of nix_core). The level of abstraction question is one that I have been thinking about more as changes have been made with the
I think all layers up to 3 could have a good spot within nix, especially with discrete crates but that designing in terms of layers and exposing each layer to users probably makes sense in most cases as well. The higher level the abstraction, the more likely it is that a use case might be prevented. I believe Nix should aim to expose the highest level (most safe) API that presents an unlimited (a user can do everything needed), zero-cost abstraction as a start. To benefit users, nix crates may also expose APIs that sacrifice flexibility in favor of safety for select use cases. |
My vote (as a user who is only starting to use nix) would be to keep nix as a monolithic crate, and just let users bump their version dependencies. They shouldn't be forced to bump the version that frequently, right? i.e. it should be safe for them to continue using an older version for some time. I also think that developing a rusty (and complete) API would be ideal. e.g. the ptrace signature is currently unsafe (although not marked so?!), and could productively be replaced with multiple helper functions that are actually safe, since the types of the later arguments depend on the flag. |
FYI I filed #214 about exporting all functions / types at the crate root as is now done in the libc crate. It's probably relevant to this discussion. |
@droundy the main driver around splitting up the crate is that a breaking change in a less thought out part of the API isn't a breaking change in other parts... @kamalmarhubi Yep, thanks for filing it. In general, this issue is on hold until libc stabilizes a bit and pulls in the required symbols. |
I think the most important thing is to have a consistent style for APIs. Putting the low-level bindings in libc is a good idea and then nix could just wrap them so no unsafe stuff is necessary for the user of nix. And we could add convenience functions on top of the low-level bindings (e.g. the mq_set_nonblock/mq_remove_nonblock I've added to mqueue.rs) that makes using the APIs easier (but avoiding any serious overhead!) I am happy to remove all the low-level mqueue stuff once it is in libc. |
I like the idea of moving as much of the current
I don't have enough experience in any of the areas where nix has fancier bindings, so I can't comment on that at all. I can say I do like things mapping directly to man pages for what I'm trying to do at the moment. |
I mostly agree with @posborne's four layers, although I do not quite see the need for the distinction between two and three (or rather the existance of level two). That leaves me with three levels:
In commit 142045f in my dev branch, I changed the signals module toward that goal.
In addition to these changes I would also liked to have removed the type alias The commit would not bring signals all the way to where it should be according to 2. above. We do not have 100% functionality, e.g. the results do not distinguish error types. There is almost no documentation. |
I don't have a proper understanding of how multiple versions of a crate play together. According to #226, tying nix's types to libc could result in downstream users having weird effects due to multiple libc versions being around. @fiveop do you have any insight, since this seems to go against what you're suggesting / working towards with signals. |
We can start this discussion up again, as I think libc is pretty stable now. There have been 8 releases in the 0.2 series: https://crates.io/crates/libc/versions Goals of nix
I like this as a lowest level aim for nix. Use system APIs without
(I copied in @posborne's level 4.) I agree with @posborne that "all layers up to 3 could have a good spot within nix", ie that levels 1-2 in @fiveop's summary work well in Nix. Crate / repo structureI'm in favour of single repo / multiple crates. I think this pattern has been used pretty well in a few crates in the ecosystem. Single repo keeps the development cohesive and in one place. Multiple crates gets rid of unnecessary version coupling. There are APIs where the best way to handle them in nix is pretty clear. We've got the |
A comment regarding usage of |
For the record: I wrote
I am now certain that there are some system calls that nix cannot provide a safe interface for. For example, we as a library can never ensure that a handler installed using the function |
Could you elaborate a little, or give an example? I haven't used the signal stuff, but this sounds important to understand. |
One more thing I'd love to see is reorganizing modules/subcrates more similarly to Having both ways, one being facade of the other is also fine. Maybe also eventually getting some well-tested things to |
tl;dr Should nix be split up into multiple crates named
nix-*
and what should the API style be?The situation
Nix originated as a posix binding dumping ground for various crates that I had been working on. I tended to need the same bindings over and over again, so I just moved them into Nix. I thought this would be useful for other people, so I accepted PRs for various system APIs as they have been submitted.
Everything has been fine so far, but a few issues have arisen.
As the API coverage has increased, whenever a breaking change is made, the semver must be incremented. So, if the
ioctl
module changes an API as it figures out the best way to expose functionality, the version must be bumped and downstream crates must change their dependencies. For example, Mio depends on nix, but not on anyioctl
features, so bumping the dependency is pretty annoying.Secondly, the API style has been somewhat ad hoc, especially with more complicated system APIs like
fcntl
.Crate structure
There is value in having a single place (nix) to find system APIs that have a coherent API style and a single documentation site. I think that each specific API silo, like sockets, ioctl, mqueue, signals, etc... could be in their own crate named
nix_*
. Common features like errors,NixPath
, etc... would live innix_core
. Thenix
crate would be a facade depending on all the sub crates with liberal dependencies (probably"*"
) which would allow the consumer to optionally be able to pin each sub crate to whatever.Libraries like Mio could then depend only on the features that are needed.
Also, it would allow delegating responsibility better. I, for one, know nothing about
ioctl
. I would like to stop being the blocker.API style
This is still something that I haven't figured out. I do know that the goal of nix is *comprehensive, safe, zero cost bindings to system APIs on nix OSes.
So, what does that mean for nix? As of now, there are currently a variety of styles. For example, most APIs are 1-1 bindings to the equivalent OS api. This leads to APIs like
fcntl
which uses a convolutedFcntlArg
strategy.ioctl
on the other hand uses a (fairly impressive) macro...The question is, would it be better to expand beyond the 1-1 rule. For example, in the
fnctl
case, the API would most likely be much cleaner and more "rusty" if each "fcntl arg" was moved to an individual function. There could, for example, be a publicfcntl
mod with adupfd
function. Using it would be:Then, should it go further? Should there be an
Fd
type that wrapsstd::os::unix::RawFd
and implement functions likedup
directly on that type?These are all open questions that I pose to the users of
nix
.cc @posborne @cmr @geofft @utkarshkukreti @MarkusJais and whoever else :)
The text was updated successfully, but these errors were encountered: