-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove
syn
and all other dependencies (#311)
Use a codegen tool to inline declarative macros, removing the need for syn at compile-time and for all consumers of this crate.
- Loading branch information
Showing
12 changed files
with
2,146 additions
and
288 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
[workspace] | ||
members = [ "ctor", "dtor", "tests" ] | ||
members = [ "ctor", "codegen", "dtor", "tests" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "ctor-codegen" | ||
version = "0.1.0" | ||
authors = ["Matt Mastracci <matthew@mastracci.com>"] | ||
edition = "2018" | ||
publish = false | ||
|
||
[dependencies] | ||
libc-print = "0.1.20" | ||
syn = "2" | ||
quote = "1" | ||
proc-macro2 = "1" | ||
paste = "1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# ctor codegen | ||
|
||
This project does the codegen to ensure that ctor builds without dependencies. We use | ||
the `quote!` macro to generate a `TokenStream`, and then dump that into a source file. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
crate::declare_macro!( | ||
macro_rules! ctor_raw { | ||
($used:meta $($block:tt)+) => { | ||
#[cfg(not(any( | ||
target_os = "linux", | ||
target_os = "android", | ||
target_os = "freebsd", | ||
target_os = "netbsd", | ||
target_os = "openbsd", | ||
target_os = "dragonfly", | ||
target_os = "illumos", | ||
target_os = "haiku", | ||
target_vendor = "apple", | ||
windows)))] | ||
compile_error!("#[ctor] is not supported on the current target"); | ||
|
||
#[$used] | ||
#[cfg_attr(any(target_os = "linux", target_os = "android"), link_section = ".init_array")] | ||
#[cfg_attr(target_os = "freebsd", link_section = ".init_array")] | ||
#[cfg_attr(target_os = "netbsd", link_section = ".init_array")] | ||
#[cfg_attr(target_os = "openbsd", link_section = ".init_array")] | ||
#[cfg_attr(target_os = "dragonfly", link_section = ".init_array")] | ||
#[cfg_attr(target_os = "illumos", link_section = ".init_array")] | ||
#[cfg_attr(target_os = "haiku", link_section = ".init_array")] | ||
#[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func")] | ||
#[cfg_attr(windows, link_section = ".CRT$XCU")] | ||
$($block)+ | ||
} | ||
} | ||
); | ||
|
||
crate::declare_macro!( | ||
macro_rules! ctor_impl { | ||
( | ||
fn | ||
macros=$macros:ident | ||
name=$name:ident | ||
used=$used:meta | ||
$(extra={ $($extra:item)+ })? | ||
item={ | ||
$( | ||
#[$meta:meta] | ||
)* | ||
$vis:vis $(unsafe)? fn $ident:ident () $(-> $ret:ty)? $block:block | ||
} | ||
) => { | ||
$(#[$meta])* | ||
#[allow(unused)] | ||
$vis unsafe extern "C" fn $ident() $block | ||
|
||
#[doc(hidden)] | ||
#[allow(unused, non_snake_case)] | ||
mod $name { | ||
super::$macros::ctor_raw!($used | ||
#[allow(non_upper_case_globals, non_snake_case)] | ||
#[doc(hidden)] | ||
static $name: unsafe extern "C" fn() -> usize = | ||
{ | ||
#[allow(non_snake_case)] | ||
#[cfg_attr(any(target_os = "linux", target_os = "android"), link_section = ".text.startup")] | ||
unsafe extern "C" fn $name() -> usize { super::$ident(); 0 } | ||
|
||
$name | ||
}; | ||
); | ||
|
||
$( $($extra)+ )? | ||
} | ||
}; | ||
|
||
( | ||
static | ||
macros=$macros:ident | ||
name=$name:ident | ||
used=$used:meta | ||
item={ | ||
$( | ||
#[$meta:meta] | ||
)* | ||
$vis:vis static $ident:ident: $ty:ty = $expr:expr; | ||
} | ||
) => { | ||
|
||
$(#[$meta])* | ||
$vis static $ident: $name::Static<$ty> = $name::Static::<$ty> { | ||
_storage: ::std::cell::UnsafeCell::new(None) | ||
}; | ||
|
||
impl ::core::ops::Deref for $name::Static<$ty> { | ||
type Target = $ty; | ||
fn deref(&self) -> &'static $ty { | ||
unsafe { | ||
let ptr = self._storage.get(); | ||
let val = (&*ptr).as_ref().unwrap(); | ||
val | ||
} | ||
} | ||
} | ||
|
||
$macros::ctor_impl!( | ||
fn | ||
macros=$macros | ||
name=$name | ||
used=$used | ||
extra={ | ||
#[doc(hidden)] | ||
#[derive(Default)] | ||
#[allow(non_camel_case_types)] | ||
pub struct Static<T> { | ||
pub _storage: ::std::cell::UnsafeCell<::std::option::Option<T>> | ||
} | ||
|
||
unsafe impl <T> std::marker::Sync for Static<T> {} | ||
} | ||
item={ | ||
#[allow(non_snake_case)] | ||
fn $name() { | ||
let val = Some($expr); | ||
// Only write the value to `storage_ident` on startup | ||
unsafe { | ||
let ptr = $ident._storage.get(); | ||
::std::ptr::write(ptr, val); | ||
} | ||
} | ||
} | ||
); | ||
}; | ||
|
||
( | ||
dtor | ||
macros=$macros:ident | ||
name=$name:ident | ||
used=$used:meta | ||
item={ | ||
$( | ||
#[$meta:meta] | ||
)* | ||
$vis:vis $(unsafe)? fn $ident:ident () $(-> $ret:ty)? $block:block | ||
} | ||
) => { | ||
$(#[$meta])* | ||
#[allow(unused)] | ||
$vis unsafe extern "C" fn $ident() $block | ||
|
||
#[doc(hidden)] | ||
#[allow(unused, non_snake_case)] | ||
mod $name { | ||
super::$macros::ctor_raw!($used | ||
#[allow(non_upper_case_globals, non_snake_case)] | ||
#[doc(hidden)] | ||
static $name: unsafe extern "C" fn() -> usize = | ||
{ | ||
#[allow(non_snake_case)] | ||
#[cfg_attr(any(target_os = "linux", target_os = "android"), link_section = ".text.startup")] | ||
unsafe extern "C" fn $name() -> usize { do_atexit(__dtor); 0 } | ||
|
||
$name | ||
}; | ||
); | ||
|
||
#[cfg(not(target_vendor = "apple"))] | ||
#[cfg_attr(any(target_os = "linux", target_os = "android"), link_section = ".text.exit")] | ||
unsafe extern "C" fn __dtor() { super::$ident() } | ||
#[cfg(target_vendor = "apple")] | ||
unsafe extern "C" fn __dtor(_: *const u8) { super::$ident() } | ||
|
||
#[cfg(not(target_vendor = "apple"))] | ||
#[inline(always)] | ||
pub(super) unsafe fn do_atexit(cb: unsafe extern fn()) { | ||
extern "C" { | ||
fn atexit(cb: unsafe extern fn()); | ||
} | ||
atexit(cb); | ||
} | ||
|
||
// For platforms that have __cxa_atexit, we register the dtor as scoped to dso_handle | ||
#[cfg(target_vendor = "apple")] | ||
#[inline(always)] | ||
pub(super) unsafe fn do_atexit(cb: unsafe extern fn(_: *const u8)) { | ||
extern "C" { | ||
static __dso_handle: *const u8; | ||
fn __cxa_atexit(cb: unsafe extern fn(_: *const u8), arg: *const u8, dso_handle: *const u8); | ||
} | ||
__cxa_atexit(cb, core::ptr::null(), __dso_handle); | ||
} | ||
|
||
} | ||
}; | ||
} | ||
); |
Oops, something went wrong.