[go: up one dir, main page]

linkme/
lib.rs

1//! [![github]](https://github.com/dtolnay/linkme) [![crates-io]](https://crates.io/crates/linkme) [![docs-rs]](https://docs.rs/linkme)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6//!
7//! <br>
8//!
9//! **A library for safe cross-platform linker shenanigans.**
10//!
11//! <br>
12//!
13//! # Platform support
14//!
15//! | Component | Linux | macOS | Windows | FreeBSD | OpenBSD | illumos | Other...<sup>†</sup> |
16//! |:---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
17//! | Distributed slice | 💚 | 💚 | 💚 | 💚 | 💚 | 💚 | |
18//!
19//! <br>***<sup>†</sup>*** We welcome PRs adding support for any platforms not
20//! listed here.
21//!
22//! <br>
23//!
24//! # Distributed slice
25//!
26//! A distributed slice is a collection of static elements that are gathered
27//! into a contiguous section of the binary by the linker. Slice elements may be
28//! defined individually from anywhere in the dependency graph of the final
29//! binary.
30//!
31//! Refer to [`linkme::DistributedSlice`][DistributedSlice] for complete details
32//! of the API. The basic idea is as follows.
33//!
34//! A static distributed slice is declared by writing `#[distributed_slice]` on
35//! a static item whose type is `[T]` for some type `T`.
36//!
37//! ```
38//! # #![cfg_attr(feature = "used_linker", feature(used_with_arg))]
39//! #
40//! # struct Bencher;
41//! #
42//! use linkme::distributed_slice;
43//!
44//! #[distributed_slice]
45//! pub static BENCHMARKS: [fn(&mut Bencher)];
46//! ```
47//!
48//! Slice elements may be registered into a distributed slice by a
49//! `#[distributed_slice(...)]` attribute in which the path to the distributed
50//! slice is given in the parentheses. The initializer is required to be a const
51//! expression.
52//!
53//! ```
54//! # #![cfg_attr(feature = "used_linker", feature(used_with_arg))]
55//! #
56//! # mod other_crate {
57//! #     use linkme::distributed_slice;
58//! #
59//! #     pub struct Bencher;
60//! #
61//! #     #[distributed_slice]
62//! #     pub static BENCHMARKS: [fn(&mut Bencher)];
63//! # }
64//! #
65//! # use other_crate::Bencher;
66//! #
67//! use linkme::distributed_slice;
68//! use other_crate::BENCHMARKS;
69//!
70//! #[distributed_slice(BENCHMARKS)]
71//! static BENCH_DESERIALIZE: fn(&mut Bencher) = bench_deserialize;
72//!
73//! fn bench_deserialize(b: &mut Bencher) {
74//!     /* ... */
75//! }
76//! ```
77//!
78//! The distributed slice behaves in all ways like `&'static [T]`.
79//!
80//! ```no_run
81//! # #![cfg_attr(feature = "used_linker", feature(used_with_arg))]
82//! #
83//! # use linkme::distributed_slice;
84//! #
85//! # struct Bencher;
86//! #
87//! # #[distributed_slice]
88//! # static BENCHMARKS: [fn(&mut Bencher)];
89//! #
90//! fn main() {
91//!     // Iterate the elements.
92//!     for bench in BENCHMARKS {
93//!         /* ... */
94//!     }
95//!
96//!     // Index into the elements.
97//!     let first = BENCHMARKS[0];
98//!
99//!     // Slice the elements.
100//!     let except_first = &BENCHMARKS[1..];
101//!
102//!     // Invoke methods on the underlying slice.
103//!     let len = BENCHMARKS.len();
104//! }
105//! ```
106//!
107//! <br>
108//!
109//! <details>
110//! <summary>Workaround for buggy IDEs</summary>
111//!
112//! JetBrains's Rust IDE uses an outdated Rust parser that treats distributed
113//! slice declarations as invalid syntax, despite being supported in stable
114//! rustc for over 3.5 years.
115//! See <https://youtrack.jetbrains.com/issue/RUST-12953>.
116//!
117//! If you hit this, you can work around it by adding a dummy initializer
118//! expression to the slice.
119//!
120//! ```
121//! # #![cfg_attr(feature = "used_linker", feature(used_with_arg))]
122//! #
123//! # use linkme::distributed_slice;
124//! #
125//! # struct Bencher;
126//! #
127//! #[distributed_slice]
128//! pub static BENCHMARKS: [fn(&mut Bencher)] = [..];
129//! #
130//! # const _: &str = stringify! {
131//!                                           ^^^^^^
132//! # };
133//! ```
134//! </details>
135
136#![no_std]
137#![doc(html_root_url = "https://docs.rs/linkme/0.3.35")]
138#![deny(unsafe_op_in_unsafe_fn)]
139#![allow(
140    clippy::doc_markdown,
141    clippy::empty_enum,
142    clippy::expl_impl_clone_on_copy,
143    clippy::manual_assert,
144    clippy::missing_panics_doc,
145    clippy::missing_safety_doc,
146    clippy::must_use_candidate,
147    clippy::unused_self
148)]
149
150mod distributed_slice;
151mod private;
152
153include!(concat!(env!("OUT_DIR"), "/private.rs"));
154
155pub use linkme_impl::*;
156
157pub use crate::distributed_slice::DistributedSlice;