1 //! This crate defines macros to easily define and use functions with a 2 //! versioned suffix, to facilitate using multiple versions of the same 3 //! crate that generate assembly. 4 5 use quote::ToTokens; 6 7 const VERSION: &str = env!("CARGO_PKG_VERSION"); 8 9 fn version(value: impl std::fmt::Display) -> String { 10 format!("{}_{}", value, VERSION.replace('.', "_")) 11 } 12 13 fn versioned_lit_str(value: impl std::fmt::Display) -> syn::LitStr { 14 syn::LitStr::new(version(value).as_str(), proc_macro2::Span::call_site()) 15 } 16 17 #[proc_macro_attribute] 18 pub fn versioned_export( 19 _attr: proc_macro::TokenStream, 20 item: proc_macro::TokenStream, 21 ) -> proc_macro::TokenStream { 22 let mut function = syn::parse_macro_input!(item as syn::ItemFn); 23 24 let export_name = versioned_lit_str(&function.sig.ident); 25 function 26 .attrs 27 .push(syn::parse_quote! { #[export_name = #export_name] }); 28 29 function.to_token_stream().into() 30 } 31 32 #[proc_macro_attribute] 33 pub fn versioned_link( 34 _attr: proc_macro::TokenStream, 35 item: proc_macro::TokenStream, 36 ) -> proc_macro::TokenStream { 37 let mut function = syn::parse_macro_input!(item as syn::ForeignItemFn); 38 39 let link_name = versioned_lit_str(&function.sig.ident); 40 function 41 .attrs 42 .push(syn::parse_quote! { #[link_name = #link_name] }); 43 44 function.to_token_stream().into() 45 } 46 47 #[proc_macro] 48 pub fn versioned_stringify_ident(item: proc_macro::TokenStream) -> proc_macro::TokenStream { 49 let ident = syn::parse_macro_input!(item as syn::Ident); 50 51 versioned_lit_str(ident).to_token_stream().into() 52 } 53 54 #[proc_macro] 55 pub fn versioned_suffix(item: proc_macro::TokenStream) -> proc_macro::TokenStream { 56 if !item.is_empty() { 57 return syn::Error::new( 58 proc_macro2::Span::call_site(), 59 "`versioned_suffix!` accepts no input", 60 ) 61 .to_compile_error() 62 .into(); 63 }; 64 65 versioned_lit_str("").to_token_stream().into() 66 } 67