Skip to main content

ctor/
lib.rs

1#![cfg_attr(feature = "used_linker", feature(used_with_arg))]
2#![recursion_limit = "256"]
3#![no_std]
4#![doc = include_str!("../docs/BUILD.md")]
5//! # ctor
6#![doc = include_str!("../docs/PREAMBLE.md")]
7#![doc = include_str!("../docs/GENERATED.md")]
8
9#[cfg(feature = "std")]
10extern crate std;
11
12mod macros;
13mod parse;
14mod priority;
15pub mod statics;
16
17#[doc(hidden)]
18#[allow(unused)]
19pub mod __support {
20    #[deprecated(since = "0.12.0", note = "Use the dtor crate directly")]
21    #[cfg(feature = "dtor")]
22    pub use dtor::declarative::dtor as dtor_parse;
23
24    // Required for proc_macro.
25    pub use crate::__ctor_parse as ctor_parse;
26
27    // Re-export link_section::TypedSection and declarative::{section, in_section}
28    #[cfg(all(feature = "priority", target_vendor = "apple"))]
29    pub use link_section::declarative::in_section;
30}
31
32#[cfg(all(feature = "priority", target_vendor = "apple"))]
33crate::__ctor_parse_internal!(
34    __ctor_features,
35    /// Define a link section when using the priority parameter on Apple
36    /// targets. This is awkwardly placed in the root module because it needs to
37    /// use a generated macro. (see
38    /// <https://github.com/rust-lang/rust/issues/52234>)
39    #[ctor(unsafe)]
40    fn priority_ctor() {
41        link_section::declarative::section!(
42            #[section(no_macro)]
43            pub static CTOR: link_section::TypedSection<(fn(), u16)>;
44        );
45
46        // SAFETY: The CTOR section is only accessed in this function, and
47        // this function is only ever called once.
48        #[allow(unsafe_code)]
49        unsafe {
50            CTOR.as_mut_slice()
51                .sort_unstable_by_key(|(_, priority)| *priority);
52        }
53        for (ctor, _) in CTOR {
54            ctor();
55        }
56    }
57);
58
59///Declarative form of the `#[ctor]` macro.
60pub mod declarative {
61    /// Declarative form of the [`#[ctor]`](crate::ctor) macro.
62    ///
63    /// The declarative forms wrap and parse a proc_macro-like syntax like so, and
64    /// are identical in expansion to the undecorated procedural macros. The
65    /// declarative forms support the same attribute parameters as the procedural
66    /// macros.
67    ///
68    /// ```rust
69    /// # #[cfg(not(miri))] mod test { use ctor::*; use libc_print::*;
70    /// ctor::declarative::ctor! {
71    ///   #[ctor]
72    ///   fn foo() {
73    ///     libc_println!("Hello, world!");
74    ///   }
75    /// }
76    /// # }
77    ///
78    /// // ... the above is identical to:
79    ///
80    /// # #[cfg(not(miri))] mod test_2 { use ctor::*; use libc_print::*;
81    /// #[ctor]
82    /// fn foo() {
83    ///   libc_println!("Hello, world!");
84    /// }
85    /// # }
86    /// ```
87    #[doc(inline)]
88    pub use crate::__support::ctor_parse as ctor;
89
90    /// Declarative form of the
91    /// [`#[dtor]`](https://docs.rs/dtor/latest/dtor/attr.dtor.html) macro.
92    ///
93    /// See
94    /// [`::dtor::declarative::dtor!`](https://docs.rs/dtor/latest/dtor/declarative/macro.dtor.html)
95    /// for more details.
96    ///
97    /// This macro is deprecated. It is recommended to import and use the `dtor`
98    /// crate directly.
99    #[deprecated(since = "0.12.0", note = "Use the dtor crate directly")]
100    #[cfg(feature = "dtor")]
101    #[doc(inline)]
102    pub use crate::__support::dtor_parse as dtor;
103}
104
105/// Marks a function or static variable as a library/executable constructor.
106/// This uses OS-specific linker sections to call a specific function at load
107/// time.
108///
109/// # Important notes
110///
111/// Rust does not make any guarantees about stdlib support for life-before or
112/// life-after main. This means that the `ctor` crate may not work as expected
113/// in some cases, such as when used in an `async` runtime or making use of
114/// stdlib services.
115///
116/// Multiple startup functions/statics are supported, but the invocation order
117/// is not guaranteed.
118///
119/// The `ctor` crate assumes it is available as a direct dependency, If you
120/// re-export `ctor` items as part of your crate, you can use the `crate_path`
121/// parameter to redirect the macro's output to the correct crate, or use the
122/// [`declarative::ctor`] form.
123///
124/// # Examples
125///
126/// Print a startup message (using `libc_print` for safety):
127///
128/// ```rust
129/// # #![cfg_attr(feature="used_linker", feature(used_with_arg))]
130/// # #[cfg(not(miri))] mod test {
131/// # use ctor::ctor;
132/// use libc_print::std_name::println;
133///
134/// #[ctor(unsafe)]
135/// fn foo() {
136///   // Using libc_print which is safe in `#[ctor]`
137///   println!("Hello, world!");
138/// }
139///
140/// # fn main() {
141/// println!("main()");
142/// # }}
143/// ```
144///
145/// Make changes to `static` variables:
146///
147/// ```rust
148/// # #![cfg_attr(feature="used_linker", feature(used_with_arg))]
149/// # mod test {
150/// use ctor::*;
151/// use std::sync::atomic::{AtomicBool, Ordering};
152/// static INITED: AtomicBool = AtomicBool::new(false);
153///
154/// #[ctor(unsafe)]
155/// fn set_inited() {
156///   INITED.store(true, Ordering::SeqCst);
157/// }
158/// # }
159/// ```
160///
161/// Initialize a `HashMap` at startup time:
162///
163/// ```rust
164/// # #![cfg_attr(feature="used_linker", feature(used_with_arg))]
165/// # mod test {
166/// # use std::collections::HashMap;
167/// # use ctor::*;
168/// #[ctor(unsafe)]
169/// pub static STATIC_CTOR: HashMap<u32, String> = {
170///   let mut m = HashMap::new();
171///   for i in 0..100 {
172///     m.insert(i, format!("x*100={}", i*100));
173///   }
174///   m
175/// };
176/// # }
177/// # pub fn main() {
178/// #   assert_eq!(test::STATIC_CTOR.len(), 100);
179/// #   assert_eq!(test::STATIC_CTOR[&20], "x*100=2000");
180/// # }
181/// ```
182///
183/// # Details
184///
185/// The `#[ctor]` macro makes use of linker sections to ensure that a function
186/// is run at startup time.
187///
188/// ```rust
189/// # #![cfg_attr(feature="used_linker", feature(used_with_arg))]
190/// # mod test {
191/// # use ctor::*;
192/// #[ctor(unsafe)]
193/// fn my_init_fn() {
194///   /* ... */
195/// }
196/// # }
197/// ```
198///
199/// The above example translates into the following Rust code (approximately):
200///
201/// ```rust
202/// # fn my_init_fn() {}
203/// #[used]
204/// #[cfg_attr(target_os = "linux", link_section = ".init_array")]
205/// #[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func,mod_init_funcs")]
206/// #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
207/// /* ... other platforms elided ... */
208/// static INIT_FN: extern fn() = {
209///     extern fn init_fn() { my_init_fn(); };
210///     init_fn
211/// };
212/// ```
213///
214/// For `static` items, the macro generates a `std::sync::OnceLock` that is
215/// initialized at startup time. `#[ctor]` on `static` items requires the
216/// default `std` feature.
217///
218/// ```rust
219/// # mod test {
220/// # use ctor::*;
221/// # use std::collections::HashMap;
222/// #[ctor]
223/// static FOO: HashMap<u32, String> = unsafe {
224///   let mut m = HashMap::new();
225///   for i in 0..100 {
226///     m.insert(i, format!("x*100={}", i*100));
227///   }
228///   m
229/// };
230/// # }
231/// ```
232///
233/// The above example translates into the following Rust code (approximately),
234/// which eagerly initializes the `HashMap` inside a `OnceLock` at startup time:
235///
236/// ```rust
237/// # mod test {
238/// # use ctor::ctor;
239/// # use std::collections::HashMap;
240/// static FOO: FooStatic = FooStatic { value: ::std::sync::OnceLock::new() };
241/// struct FooStatic {
242///   value: ::std::sync::OnceLock<HashMap<u32, String>>,
243/// }
244///
245/// impl ::core::ops::Deref for FooStatic {
246///   type Target = HashMap<u32, String>;
247///   fn deref(&self) -> &Self::Target {
248///     self.value.get_or_init(|| unsafe {
249///       let mut m = HashMap::new();
250///       for i in 0..100 {
251///         m.insert(i, format!("x*100={}", i*100));
252///       }
253///       m
254///     })
255///   }
256/// }
257///
258/// #[ctor]
259/// unsafe fn init_foo_ctor() {
260///   _ = &*FOO;
261/// }
262/// # }
263/// ```
264#[doc(inline)]
265#[cfg(feature = "proc_macro")]
266pub use ctor_proc_macro::ctor;
267
268/// Re-exported `#[dtor]` proc-macro from `dtor` crate.
269///
270/// See [`::dtor`] for more details.
271#[deprecated(since = "0.12.0", note = "Use the dtor crate directly")]
272#[doc(inline)]
273#[cfg(all(feature = "dtor", feature = "proc_macro"))]
274pub use dtor::__dtor_from_ctor as dtor; // note: this is the dtor proc macro that looks in ctor
275
276__declare_features!(
277    ctor: __ctor_features;
278
279    /// Do not give the constructor a name in the generated code (allows for
280    /// multiple constructors with the same name). Equivalent to wrapping the
281    /// constructor in an anonymous const (i.e.: `const _ = { ... };`).
282    anonymous {
283        attr: [(anonymous) => (anonymous)];
284    };
285    /// The path to the `ctor` crate containing the support macros. If you
286    /// re-export `ctor` items as part of your crate, you can use this to
287    /// redirect the macro’s output to the correct crate.
288    ///
289    /// Using the declarative [`ctor!`][c] form is
290    /// preferred over this parameter.
291    ///
292    /// [c]: crate::declarative::ctor!
293    crate_path {
294        attr: [(crate_path = $path:pat) => (($path))];
295        example: "crate_path = ::path::to::ctor::crate";
296    };
297    /// Enable support for the `#[dtor]` attribute. Deprecated: use the `dtor` crate directly instead.
298    dtor {
299        feature: "dtor";
300    };
301    /// Specify a custom export name prefix for the constructor function.
302    ///
303    /// If specified, an export with the given prefix will be generated in the form:
304    ///
305    /// `<prefix><priority>_<unique_id>`
306    export_name_prefix {
307        attr: [(export_name_prefix = $export_name_prefix_str:literal) => ($export_name_prefix_str)];
308        example: "export_name_prefix = \"ctor_\"";
309        default {
310            (target_os = "aix") => "__sinit",
311            _ => (),
312        }
313    };
314    /// Place the constructor function pointer in a custom link section. By
315    /// default, this uses the appropriate platform-specific link section.
316    // NOTE: Keep in sync w/dtor::ctor_link_section!
317    link_section {
318        attr: [(link_section = $section:literal) => ($section)];
319        example: "link_section = \".ctors\"";
320        default {
321            // This is no longer supported by Apple
322            (target_vendor = "apple") => "__DATA,__mod_init_func,mod_init_funcs",
323            // Most LLVM/GCC targets can use .init_array
324            (any(
325                target_os = "linux",
326                target_os = "android",
327                target_os = "freebsd",
328                target_os = "netbsd",
329                target_os = "openbsd",
330                target_os = "dragonfly",
331                target_os = "illumos",
332                target_os = "haiku",
333                target_os = "vxworks",
334                target_os = "nto",
335                target_family = "wasm"
336            )) => ".init_array",
337            // No OS
338            (target_os = "none") => ".init_array",
339            // xtensa targets: .ctors
340            (target_arch = "xtensa") => ".ctors",
341            // Windows targets: .CRT$XCU
342            (all(target_vendor = "pc", any(target_env = "gnu", target_env = "msvc"))) => ".CRT$XCU",
343            // ... except GNU
344            (all(target_vendor = "pc", not(any(target_env = "gnu", target_env = "msvc")))) => ".ctors",
345            (all(target_os = "aix")) => (), // AIX uses export_name_prefix
346            _ => (compile_error!("Unsupported target for #[ctor]"))
347        }
348    };
349    no_warn_on_missing_unsafe {
350        /// crate
351        /// Do not warn when a ctor is missing the `unsafe` keyword.
352        feature: "no_warn_on_missing_unsafe";
353        /// attr
354        /// Marks a ctor as unsafe. Recommended.
355        attr: [(unsafe) => (no_warn_on_missing_unsafe)];
356    };
357    /// The priority of the constructor. Higher-`N`-priority constructors are
358    /// run last. `N` must be between 0 and 999 for ordering guarantees (`N` >=
359    /// 1000 ordering is platform-defined).
360    ///
361    /// Ordering with respect to constructors without a priority is
362    /// platform-defined.
363    priority {
364        attr: [(priority = $priority_value:tt) => ($priority_value)];
365        validate: [(priority = $priority:literal), (priority = early), (priority = late)];
366    };
367    /// Enable support for the priority parameter.
368    priority_enabled {
369        feature: "priority";
370    };
371    /// Enable support for the proc-macro `#[ctor]` attribute. The declarative
372    /// form (`ctor!(...)`) is always available. It is recommended that crates
373    /// re-exporting the `ctor` macro disable this feature and only use the
374    /// declarative form.
375    proc_macro {
376        feature: "proc_macro";
377    };
378    /// Enable support for the standard library.
379    std {
380        feature: "std";
381    };
382    used_linker {
383        /// crate
384        /// Applies `used(linker)` to all `ctor`-generated functions. Requires nightly and `feature(used_with_arg)`.
385        feature: "used_linker";
386        /// attr
387        /// Mark generated functions for this `ctor` as `used(linker)`. Requires nightly and `feature(used_with_arg)`.
388        attr: [(used(linker)) => (used_linker)];
389    };
390);
391
392#[cfg(doc)]
393__generate_docs!(__ctor_features);