1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use crate::linker;
use proc_macro2::{TokenStream, TokenTree};
use quote::quote;
use syn::parse::{Parse, ParseStream, Result};
use syn::{braced, parenthesized, token, Ident, LitStr};
pub struct Enum {
linkme_ident: Ident,
linkme_macro: Ident,
}
impl Parse for Enum {
fn parse(input: ParseStream) -> Result<Self> {
while !input.peek(token::Brace) {
input.parse::<TokenTree>()?;
}
let variants;
braced!(variants in input);
while !variants.peek(token::Paren) {
variants.parse::<TokenTree>()?;
}
let discriminant;
parenthesized!(discriminant in variants);
let linkme_ident = discriminant.parse::<LitStr>()?.parse::<Ident>()?;
discriminant.parse::<TokenStream>()?;
while !variants.peek(token::Paren) {
variants.parse::<TokenTree>()?;
}
let discriminant;
parenthesized!(discriminant in variants);
let linkme_macro = discriminant.parse::<LitStr>()?.parse::<Ident>()?;
discriminant.parse::<TokenStream>()?;
variants.parse::<TokenStream>()?;
Ok(Enum {
linkme_ident,
linkme_macro,
})
}
}
pub fn expand(input: Enum) -> TokenStream {
let ident = input.linkme_ident;
let ident_macro = input.linkme_macro;
let linux_section = linker::linux::section(&ident);
let macos_section = linker::macos::section(&ident);
let windows_section = linker::windows::section(&ident);
let illumos_section = linker::illumos::section(&ident);
quote! {
#[doc(hidden)]
#[macro_export]
macro_rules! #ident_macro {
(
#![linkme_macro = $macro:path]
#![linkme_sort_key = $key:tt]
$item:item
) => {
$macro ! {
#![linkme_linux_section = concat!(#linux_section, $key)]
#![linkme_macos_section = concat!(#macos_section, $key)]
#![linkme_windows_section = concat!(#windows_section, $key)]
#![linkme_illumos_section = concat!(#illumos_section, $key)]
$item
}
};
(
#![linkme_linux_section = $linux_section:expr]
#![linkme_macos_section = $macos_section:expr]
#![linkme_windows_section = $windows_section:expr]
#![linkme_illumos_section = $illumos_section:expr]
$item:item
) => {
#[used]
#[cfg_attr(any(target_os = "none", target_os = "linux"), link_section = $linux_section)]
#[cfg_attr(target_os = "macos", link_section = $macos_section)]
#[cfg_attr(target_os = "windows", link_section = $windows_section)]
#[cfg_attr(target_os = "illumos", link_section = $illumos_section)]
$item
};
($item:item) => {
#[used]
#[cfg_attr(any(target_os = "none", target_os = "linux"), link_section = #linux_section)]
#[cfg_attr(target_os = "macos", link_section = #macos_section)]
#[cfg_attr(target_os = "windows", link_section = #windows_section)]
#[cfg_attr(target_os = "illumos", link_section = #illumos_section)]
$item
};
}
}
}