diff --git a/src/headers/_mod.rs b/src/headers/_mod.rs index 4de818acfa..243cd41e00 100644 --- a/src/headers/_mod.rs +++ b/src/headers/_mod.rs @@ -306,6 +306,12 @@ with_optional_fields! { /// /// It defaults to [`Language::C`]. language: Language, + + /// Whether to yield a stable header or not (order of defined items guaranteed + /// not to change provided the source code doesn't change either). + /// + /// It defaults to `true`. + stable_header: bool, } impl Builder<'_, WhereTo> { @@ -394,20 +400,33 @@ impl Builder<'_, WhereTo> { )?, } /* User-provided defs! */ - // Sort the definitions for a reliable header generation. - let sorted_definitions = - crate::inventory::iter - .into_iter() - .map(|crate::FfiExport { name, gen_def }| (name, gen_def)) - .collect::<::std::collections::BTreeMap<_, _>>() - ; - sorted_definitions - .values() - // Iterate in reverse fashion to more closely match - // the Rust definition order. - .try_for_each(|gen_def| gen_def(&mut definer, lang)) - ? - ; + let stable_header = config.stable_header.unwrap_or(true); + let (mut storage0, mut storage1) = (None, None); + let gen_defs: &mut dyn Iterator = if stable_header { + // Sort the definitions for a reliable header generation. + let sorted_definitions = + crate::inventory::iter + .into_iter() + .map(|crate::FfiExport { name, gen_def }| (name, gen_def)) + .collect::<::std::collections::BTreeMap<_, _>>() + ; + storage0.get_or_insert( + sorted_definitions + .into_iter() + .map(|(_, gen_def)| gen_def) + ) + } else { + storage1.get_or_insert( + crate::inventory::iter + .into_iter() + // Iterate in reverse fashion to more closely match + // the Rust definition order. + .collect::>().into_iter().rev() + .map(|crate::FfiExport { gen_def, .. }| gen_def) + ) + }; + (&mut { gen_defs }).try_for_each(|gen_def| gen_def(&mut definer, lang))?; + // Epilogue match lang { | Language::C => write!(definer.out(),