Skip to main content

dtor/
lib.rs

1#![recursion_limit = "256"]
2#![no_std]
3#![doc = include_str!("../docs/BUILD.md")]
4//! # dtor
5#![doc = include_str!("../docs/PREAMBLE.md")]
6#![doc = include_str!("../docs/GENERATED.md")]
7
8#[cfg(feature = "std")]
9extern crate std;
10
11mod macros;
12mod native;
13mod parse;
14
15#[doc = include_str!("../docs/LIFE_BEFORE_MAIN.md")]
16pub mod life_before_main {}
17
18pub use native::*;
19
20/// Marks a function as a library/executable destructor. This uses OS-specific
21/// linker sections to call a specific function at termination time.
22///
23/// Multiple shutdown functions are supported, but the invocation order is not
24/// guaranteed.
25///
26/// ```rust,ignore
27/// # #![cfg_attr(feature="used_linker", feature(used_with_arg))]
28/// # use dtor::dtor;
29/// # fn main() {}
30///
31/// #[dtor]
32/// fn shutdown() {
33///   /* ... */
34/// }
35/// ```
36#[doc(inline)]
37#[cfg(feature = "proc_macro")]
38pub use linktime_proc_macro::dtor;
39
40/// Declarative forms of the `#[dtor]` macro.
41///
42/// The declarative forms wrap and parse a proc_macro-like syntax like so, and
43/// are identical in expansion to the undecorated procedural macros. The
44/// declarative forms support the same attribute parameters as the procedural
45/// macros.
46///
47/// ```rust
48/// # #[cfg(any())] mod test { use dtor::*; use libc_print::*;
49/// dtor::declarative::dtor! {
50///   #[dtor]
51///   fn foo() {
52///     libc_println!("Goodbye, world!");
53///   }
54/// }
55/// # }
56///
57/// // ... the above is identical to:
58///
59/// # #[cfg(any())] mod test_2 { use dtor::*; use libc_print::*;
60/// #[dtor]
61/// fn foo() {
62///   libc_println!("Goodbye, world!");
63/// }
64/// # }
65/// ```
66pub mod declarative {
67    #[doc(inline)]
68    pub use crate::__dtor_parse as dtor;
69}
70
71#[doc(hidden)]
72#[allow(unused)]
73pub mod __support {
74    use crate::macros::*;
75
76    // Required for proc_macro.
77    pub use crate::__dtor_parse as dtor_parse;
78
79    pub use crate::native::*;
80}
81
82__declare_features!(
83    dtor: __dtor_features;
84
85    /// Make the ctor function anonymous.
86    anonymous {
87        attr: [(anonymous) => (anonymous)];
88    };
89    /// Specify a custom crate path for the `dtor` crate. Used when re-exporting the dtor macro.
90    crate_path {
91        attr: [(crate_path = $path:pat) => (($path))];
92        example: "crate_path = ::path::to::dtor::crate";
93    };
94    /// Specify a custom export name prefix for the constructor function.
95    ///
96    /// If specified, an export with the given prefix will be generated in the form:
97    ///
98    /// `<prefix>_<unique_id>`
99    ctor_export_name_prefix {
100        attr: [(ctor(export_name_prefix = $ctor_export_name_prefix_str:literal)) => ($ctor_export_name_prefix_str)];
101        example: "ctor(export_name_prefix = \"ctor_\")";
102        default {
103            (target_os = "aix") => "__sinit80000000",
104            _ => (),
105        }
106    };
107    /// Place the initialization function pointer in a custom link section.
108    ctor_link_section {
109        attr: [(ctor(link_section = $ctor_link_section_name:literal)) => ($ctor_link_section_name)];
110        example: "ctor(link_section = \".ctors\")";
111        default {
112            // This is no longer supported by Apple
113            (target_vendor = "apple") => "__DATA,__mod_init_func,mod_init_funcs",
114            // Most LLVM/GCC targets can use .fini_array
115            (any(
116                target_os = "linux",
117                target_os = "android",
118                target_os = "freebsd",
119                target_os = "netbsd",
120                target_os = "openbsd",
121                target_os = "dragonfly",
122                target_os = "illumos",
123                target_os = "haiku",
124                target_os = "vxworks",
125                target_os = "nto",
126                target_family = "wasm"
127            )) => ".init_array",
128            // No OS
129            (target_os = "none") => ".init_array",
130            // xtensa targets: .dtors
131            (target_arch = "xtensa") => ".ctors",
132            // Windows targets: .CRT$XCU
133            (all(target_vendor = "pc", any(target_env = "gnu", target_env = "msvc"))) => ".CRT$XCU",
134            // ... except GNU
135            (all(target_vendor = "pc", not(any(target_env = "gnu", target_env = "msvc")))) => ".ctors",
136            (all(target_os = "aix")) => (), // AIX uses export_name_prefix
137            _ => (compile_error!("Unsupported target for #[ctor]"))
138        }
139    };
140    /// The default method used for running a `dtor` on termination. This is
141    /// generally not recommended as code may be unloaded before the dtor is
142    /// called.
143    ///
144    /// This is only used if the specified `dtor` method is `term`.
145    ///
146    /// All platforms use `at_binary_exit` except Windows, which uses
147    /// `at_module_exit`.
148    default_term_method {
149        default {
150            (target_vendor = "pc") => at_module_exit,
151            _ => at_binary_exit,
152        }
153    };
154    /// The default method used for running a `dtor` on module unload.
155    ///
156    /// This is only used if the `method` attribute is not specified, or if the
157    /// method is `unload`.
158    default_unload_method {
159        default {
160            _ => at_module_exit,
161        }
162    };
163    /// Specify a custom export name prefix for the destructor function.
164    ///
165    /// If specified, an export with the given prefix will be generated in the form:
166    ///
167    /// `<prefix>_<unique_id>`
168    export_name_prefix {
169        attr: [(export_name_prefix = $export_name_prefix_str:literal) => ($export_name_prefix_str)];
170        example: "export_name_prefix = \"ctor_\"";
171        default {
172            (target_os = "aix") => "__sterm80000000",
173            _ => (),
174        }
175    };
176    /// Place the destructor function pointer in a custom link section.
177    link_section {
178        attr: [(link_section = $section:literal) => ($section)];
179        example: "link_section = \".dtors\"";
180        default {
181            // This is no longer supported by Apple
182            (target_vendor = "apple") => "__DATA,__mod_term_func,mod_term_funcs",
183            // Most LLVM/GCC targets can use .fini_array
184            (any(
185                target_os = "linux",
186                target_os = "android",
187                target_os = "freebsd",
188                target_os = "netbsd",
189                target_os = "openbsd",
190                target_os = "dragonfly",
191                target_os = "illumos",
192                target_os = "haiku",
193                target_os = "vxworks",
194                target_os = "nto",
195                target_family = "wasm"
196            )) => ".fini_array",
197            // No OS
198            (target_os = "none") => ".fini_array",
199            // xtensa targets: .dtors
200            (target_arch = "xtensa") => ".dtors",
201            // Windows targets: .CRT$XPU (requires static CRT)
202            (all(target_vendor = "pc", any(target_env = "gnu", target_env = "msvc"))) => ".CRT$XPU",
203            // ... except GNU
204            (all(target_vendor = "pc", not(any(target_env = "gnu", target_env = "msvc")))) => ".dtors",
205            (all(target_os = "aix")) => (), // AIX uses export_name_prefix
206            _ => (compile_error!("Unsupported target for #[dtor]"))
207        }
208    };
209    /// Specify the dtor method.
210    ///
211    ///  - `term`: Run the dtor on binary termination using the platform's
212    ///    [default_term_method](#default_term_method). Not recommended as code
213    ///    may be unloaded before the dtor is called.
214    ///  - `unload`: Run the dtor on module unload (library or binary) using the
215    ///    platform's [default_unload_method](#default_unload_method).
216    ///  - `at_module_exit`: Run the dtor using the platform's
217    ///    [`at_module_exit`][at_module_exit] (`__cxa_atexit` on all platforms
218    ///    other than Windows, `atexit` on Windows).
219    ///  - `at_binary_exit`: Run the dtor using the platform's
220    ///    [`at_binary_exit`][at_binary_exit] (unsupported on Windows
221    ///    platforms).
222    ///  - `linker`: Register the dtor using the platform's
223    ///    [link_section](#link_section) or
224    ///    [export_name_prefix](#export_name_prefix) (unsupported on Apple
225    ///    platforms).
226    ///
227    /// [at_module_exit]: crate::native::at_module_exit
228    /// [at_binary_exit]: crate::native::at_binary_exit
229    method {
230        attr: [(method = $method_id:ident) => ($method_id)];
231        example: "method = term|unload|at_module_exit|at_binary_exit|linker";
232        validate: [(method = term), (method = unload), (method = at_module_exit), (method = at_binary_exit), (method = linker)];
233        default {
234            (target_vendor = "apple") => at_module_exit,
235            (target_vendor = "pc") => at_module_exit,
236            _ => linker,
237        }
238    };
239    no_warn_on_missing_unsafe {
240        /// crate
241        /// Do not warn when a ctor or dtor is missing the `unsafe` keyword.
242        feature: "no_warn_on_missing_unsafe";
243        /// attr
244        /// Marks a ctor/dtor as unsafe.
245        attr: [(unsafe) => (no_warn_on_missing_unsafe)];
246    };
247    /// Enable support for the proc-macro `#[dtor]` attribute. The declarative
248    /// form (`dtor!(...)`) is always available. It is recommended that crates
249    /// re-exporting the `dtor` macro disable this feature and only use the
250    /// declarative form.
251    proc_macro {
252        feature: "proc_macro";
253    };
254    /// Enable support for the standard library.
255    std {
256        feature: "std";
257    };
258    used_linker {
259        /// crate
260        /// Applies `used(linker)` to all `dtor`-generated functions. Requires nightly and `feature(used_with_arg)`.
261        feature: "used_linker";
262        /// attr
263        /// Mark generated functions for this `dtor` as `used(linker)`. Requires nightly and `feature(used_with_arg)`.
264        attr: [(used(linker)) => (used_linker)];
265    };
266);
267
268#[cfg(doc)]
269__generate_docs!(__dtor_features);