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);