Macro enable

Source
macro_rules! enable {
    () => { ... };
    ($krate:path) => { ... };
}
Expand description

Enable the sym!(...) macro in the calling crate.

Put a call to this macro somewhere in the root of each crate that uses the sym!(...) macro.

§Details

This creates a “distributed slice” containing all symbols in this crate, as well as a static constructor that deduplicates all symbols on startup, or when a dynamic library is loaded when the target binary is a dylib or a cdylib.

This macro may also be invoked with a module path to another crate, which causes symbols in this crate to be registered as part of symbols in the other crate.

CAUTION: Using the second variant is discouraged, because it will not work when the other crate is being loaded as a dynamic library. However, it is very slightly more efficient.

§Why?

The reason that this macro is necessary is dynamic linking. Under “normal” circumstances where all dependencies are statically linked, all crates could share a single symbol table. But dynamic libraries are linked independently of their host binary, so they have no access to the host’s symbol table, if it even has one.

On Unix-like platforms, there is likely a solution for this based on “weak” linkage, but:

  1. Weak linkage is not a thing in Windows (DLLs need to explicitly request functions from the host binary using GetModuleHandle(), which is more brittle).
  2. The #[linkage] attribute is unstable in Rust.