use std::process::Command;
use std::sync::LazyLock;
use proc_macro::TokenStream;
use quote::quote;
use syn::parse_macro_input;
static NVCC_AVAILABLE: LazyLock<bool> = LazyLock::new(|| {
Command::new("nvcc")
.arg("--version")
.output()
.is_ok_and(|o| o.status.success())
});
#[proc_macro_attribute]
pub fn cuda_available(_attr: TokenStream, item: TokenStream) -> TokenStream {
if *NVCC_AVAILABLE {
item
} else {
TokenStream::new()
}
}
#[proc_macro_attribute]
pub fn cuda_not_available(_attr: TokenStream, item: TokenStream) -> TokenStream {
if *NVCC_AVAILABLE {
TokenStream::new()
} else {
item
}
}
#[proc_macro_attribute]
pub fn test(_attr: TokenStream, item: TokenStream) -> TokenStream {
let item = parse_macro_input!(item as syn::ItemFn);
if *NVCC_AVAILABLE {
if item.sig.asyncness.is_some() {
quote! {
#[tokio::test]
#item
}
} else {
quote! {
#[test]
#item
}
}
.into()
} else {
if item.sig.asyncness.is_some() {
quote! {
#[tokio::test]
#[ignore]
#item
}
} else {
quote! {
#[test]
#[ignore]
#item
}
}
.into()
}
}