Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 1 addition & 14 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,7 @@ We have two automated tests running on

## Breaking change policy

Sometimes an upstream adds a breaking change to their API e.g. removing outdated
items, changing the type signature, etc. And we probably should follow that
change to build the `libc` crate successfully. It's annoying to do the
equivalent of semver-major versioning for each such change. Instead, we mark the
item as deprecated and do the actual change after a certain period. The steps
are:

1. Add `#[deprecated(since = "", note="")]` attribute to the item.
- The `since` field should have a next version of `libc` (e.g., if the current
version is `0.2.1`, it should be `0.2.2`).
- The `note` field should have a reason to deprecate and a tracking issue to
call for comments (e.g., "We consider removing this as the upstream removed
it. If you're using it, please comment on #XXX").
2. If we don't see any concerns for a while, do the change actually.
See `src/lib.rs` for details.

## Supported target policy

Expand Down
8 changes: 0 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,6 @@ Add the following to your `Cargo.toml`:
libc = "0.2"
```

## Features

* `std`: by default `libc` links to the standard library. Disable this feature
to remove this dependency and be able to use `libc` in `#![no_std]` crates.

* `extra_traits`: all `struct`s implemented in `libc` are `Copy` and `Clone`.
This feature derives `Debug`, `Eq`, `Hash`, and `PartialEq`.

## Rust version support

The minimum supported Rust toolchain version is currently **Rust 1.65**.
Expand Down
129 changes: 128 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,131 @@
//! libc - Raw FFI bindings to platforms' system libraries
//! Raw FFI bindings to platforms' system libraries.
//!
//! # Usage Recommendations
//!
//! `libc` takes a differe

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems incomplete.

//!
//! - *Never* construct a `libc` struct with `MaybeUninit::uninit()`, initialize it, then call
//! `assume_init`. Many structures have padding fields or may gain fields in the future, and
//! it is far too easy to end up calling `assume_init` on partially initialized data.
//!
//! Instead, use `MaybeUninit::zeroed()` or the `Default` implementations that are slowly being
//! added. Alternatively, access fields only via raw pointer without ever using `assume_init`.
//!
//! - Avoid relying on the exact value of constants or the exact length of arrays, as they may
//! change across `libc` versions. That is, if `libc` contains code like:
//!
//! <!-- relevant for how rustdoc displays these structs:
//! https://github.com/rust-lang/rust/issues/102456 -->
//! ```ignore
//! const IFNAMSIZ: usize = 16;
//!
//! pub struct ifreq {
//! pub ifr_name: [c_char; IFNAMSIZ],
//! // ...
//! }
//! ```
//!
//! Then avoid writing code like:
//!
//! ```ignore
//! // Bad assumption that `IFNAMSIZ` will be 16 forever
//! fn foo(ifr_name: [c_char; 16]) { /* ... */ }
//!
//! fn bar(ifr: ifreq) {
//! foo(ifr.ifr_name);
//! }
//! ```
//!
//! Instead, use `[c_char; IFNAMSIZ]` to specify the type, or just `&[c_char]`.
//!
//! Along the same lines, if you write code along the lines of `assert_eq!(libc::ELAST, 97)`,
//! expect that there may be a release where this starts to fail.
//!
//! - Do not name `__c_anonymous_*` types anywhere, which exist to represent anonymous fields in
//! C. For example, FreeBSD defines:
//!
//! ```c
//! struct filestat {
//! int fs_type;
//! // ...
//! struct { struct filestat stqe_next; } next;
//! };
//! ```
//!
//! Which is represented in `libc` as:
//!
//! ```ignore
//! struct filestat {
//! fs_type: c_int,
//! // ...
//! next: __c_anonymous_filestat,
//! }
//!
//! struct __c_anonymous_filestat { stqe_next: *mut filestat }
//! ```
//!
//! Accessing `some_filestat.next.stqe_next` is completely fine, but `__c_anonymous_filestat`
//! should not be used anywhere (e.g. in a function signature). This is done to permit `libc` to
//! switch to anonymous fields if the feature is ever added to Rust.
//!
//! - Be aware of deprecation warnings. These are used as a way to migrate necessary API changes.
//!
//! # Cargo Features
//!
//! - `std`: by default `libc` assumes that the standard library contains link directives necessary
//! to use the APIs in this crate. If `std` is disabled, `libc` will emit directives necessary to
//! link the necessary C libraries.
//!
//! This feature is slated for removal in `libc` 1.0. The intention is that no-std users of
//! `libc` should use their own `#[link]` attributes, `rustc-link-lib` build script directives,
//! or `-l` arguments for only the system libraries they need to link, rather than `libc`
//! possibly linking more than is needed or available. If you are using `libc` without the `std`
//! feature, consider starting to add link directives now for a smoother 1.0 transition.
//!
//! - `extra_traits`: all types in `libc` implement `Clone`, `Copy`, and `Debug`. The
//! `extra_traits` feature adds `Eq`, `Hash`, and `PartialEq`.
//!
//! This feature is expected to be removed in libc 1.0. Libraries should instead hash or check
//! equality of only needed fields.
//!
//! - The features `const-extern-function`, `align`, and `use_std` are all deprecated.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//! - The features `const-extern-function`, `align`, and `use_std` are all deprecated.
//! - The features `const-extern-fn`, `align`, and `use_std` are all deprecated.

//!
//! # Stability Expectations
//!
//! Due to `libc`'s position in the ecosystem, it can effectively never publish semver-breaking
//! releases. However, the API that `libc` binds changes _all the time_; sometimes in ways that
//! are harmless, sometimes in ways that are technically API-breaking for C users but unlikely
//! to be noticed (e.g. removing deprecated API), and sometimes in ways that are nonbreaking in
//! C but translate to breaking changes in Rust (e.g. changing integer size). `libc` tries to
//! strike a balance but all of this means that unfortunately, `libc` must occasionally ship
//! changes within a semver-compatible release that are technically semver-breaking.
//!
//! The following are examples of changes that fall into this category:
//!
//! - Fields are added to a struct that is currently exhaustive.
//! - Fields with names such as `padding` or `reserved` change type or are removed.
//! - The length of an array type changes.
//! - A struct field (with available padding) is changed from `int` to `long`.
//!
//! In general, `libc` aims to follow platform API changes, even when this means changes that are
//! user-visible in Rust. There are a few guidelines used here:
//!
//! - Adding struct fields is not considered breaking, nor is changing fields named `reserved`,
//! `padding`, or similar. This is because users are expected to use field-by-field
//! initialization.
//! - Changing type aliases, values of constants, or array lengths is not considered breaking.
//! - If the platform libc has accepted breakage on the C side (typically in the form of removing
//! old API), the `libc` crate will follow suit.
//! - Where possible, `#[deprecated(...)]` will be used to warn about changes before applying them.
//! Alternative mitigations may be considered.
//! - Potentially breaking changes will be well-identified in release notes.
//! - Beyond this, public API is not expected to change on Tier 1 targets. Tier 2 targets have
//! relaxed API stability requirements, and API stability is not enforced on tier 3 targets.
//!
//! While this section seems scary, keep in mind that it is meant to cover worst-case scenarios. In
//! practice, breakage is rare and following the above-discussed [Best Practices](#best-practices)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be missing something but I don't see this section.

//! means that most `libc` users will never encounter a problem.

#![crate_name = "libc"]
#![crate_type = "rlib"]
#![allow(
Expand Down
3 changes: 3 additions & 0 deletions src/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,9 @@ extern "C" {
pub static in6addr_any: in6_addr;
}

// FIXME(1.0): We want to remove these directives and instead expect that no-std users add their
// own link configuration when required, rather than unconditionally linking everything that may
// possibly be needed.
cfg_if! {
if #[cfg(any(
target_os = "l4re",
Expand Down