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