Exports from some public mods aren't included in headers
Closed this issue · 2 comments
Check the attachments for a complete reproduction Cargo project.
I have a lib.rs file that re-exports some crate modules. Like this:
use ::safer_ffi::prelude::*;
pub mod my_mod;
#[ffi_export]
pub fn init() {
}
Within the exported mod (my_mod.rs), I have an item called tokenizer
, which does not end up in the generated header, in spite of it being #[ffi_export]
. This is my primary complaint.
However, the plot thickens because, if I then uncomment useless_enum
from the same file, both items are now included in the generated header.
Here is a complete repro case, just as described. It follows the same structure as the QuickStart example, so you can generate the header by running:
cargo build
cargo run --features headers --bin generate-headers
Thank you
This seems to be dtolnay/inventory#52
-
(
safer-ffi
usesinventory
under the hood to handle the list/collection of#[ffi_export]
ed items for which to generate headers; the followingstatic
is probably being removed by the linker):#[used] #[doc(hidden)] #[link_section = "__DATA,__mod_init_func"] static __init6873130405561783045___rust_ctor___ctor
Full
inventory
output#[allow(non_upper_case_globals)] extern fn __init6873130405561783045() { ::safer_ffi::inventory::submit({ ::safer_ffi::FfiExport({ #[allow(unused_parens, clippy::all)] fn typedef( definer: &'_ mut dyn ::safer_ffi::headers::Definer, ) -> ::safer_ffi::std::io::Result<()> { <<tokenizer as ::safer_ffi::layout::ReprC>::CLayout as ::safer_ffi::layout::CType>::c_define_self( definer, ) } typedef }) }); } #[used] #[allow(non_upper_case_globals)] #[doc(hidden)] #[link_section = "__DATA,__mod_init_func"] static __init6873130405561783045___rust_ctor___ctor: unsafe extern "C" fn() = { unsafe extern "C" fn __init6873130405561783045___rust_ctor___ctor() { __init6873130405561783045() } __init6873130405561783045___rust_ctor___ctor };
From that issue, and https://github.com/dtolnay/inventory/pull/57/files, it is mentioned that using codegen-units = 1
, at least when on macOS, may work around the issue. I've tested just that, and it seems to work:
# On macOS
CARGO_PROFILE_DEV_CODEGEN_UNITS=1 cargo r --features=headers
-
or:
# Cargo.toml [profile.dev] codegen-units = 1
Alas, I don't know of a reliable way to handle this; in order for the header generation of #[ffi_export]
to work, a way to globally collect header generation snippets is necessary, and at the moment, there are only two crates that offer this: ::inventory
and ::linkme
, and both rely on linker shenanigans, which can be brittle to certain linkers agressively removing stuff. It's thus kind of beyond my capacity to properly fix this 😔
So I'll have to close this issue, but feel free to post any further questions you may have, or ideas related to this 🙂