Expand description
A dependency free library that declares functions to be automatically
executed before main
is invoked.
This crate implements the exact same behavior as the
ctor
crate with the following
differences:
- It has no dependencies other than
proc_macro
itself. - It requires that functions are marked with
unsafe
. - It can only be used with functions, not static items.
- It only supports
#[ctor]
§Example
This is a motivating example that registers a struct as a plugin in a hypothetical global plugins registry:
struct MyPlugin;
#[small_ctor::ctor]
unsafe fn register_plugin() {
PLUGINS.register(MyPlugin);
}
§Safety
This library involves “life before main” which is explicitly not permitted
in Rust which is why this library is anything but safe. In fact, it’s a
really bad idea to do what this crate is promoting. For instance at
present code that runs in #[ctor]
will run before lang_start
managed to
execute. Some of the effects of this are that the main thread does not have
a name yet, the stack protection is not enabled and code must not panic.
It’s recommended that the only thing you do in a #[ctor]
function is to
append to a vector, insert into a hashmap or similar.
§Recommended Usage
It’s recommended to perform basic operations which are unlikely to panic
and to defer most work to when the actual main
happens. So for
instead instead of initializing plugins in the ctor
, just push them
to a plugin registry and then trigger callbacks registered that way
regularly in main
.
§Compiler and Linker Bugs
Currently this library is prone to break due to compiler bugs in subtle
ways. The core issue is rust #47384.
You can reduze the likelihood of it happening by disabling incremental
compilation or setting codegen-units
to 1
in your profile in the
Cargo.toml
.
§Destructors
This crate intentionally does not support an at-exit mechanism. The reason
for this is that those are running so late that even more Rust code is
unable to properly run. Not only does panicking not work, the entire standard
IO system is already unusable. More importantly on many platforms these
do not run properly. For instance on macOS destructors do not run when
thread local storage is in use. If you do want to use something like this
you can do something like invoke libc::atexit
from within a #[ctor]
function.
Attribute Macros§
- ctor
- Marks a function or static variable as a library/executable constructor. This uses OS-specific linker sections to call a specific function at load time.