use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; use rustc_target::spec::abi::Abi; crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { tcx, args: Vec::new() }; tcx.hir().krate().visit_all_item_likes(&mut collector); for attr in tcx.hir().krate().item.attrs.iter() { if attr.has_name(sym::link_args) { if let Some(linkarg) = attr.value_str() { collector.add_link_args(linkarg); } } } collector.args } struct Collector<'tcx> { tcx: TyCtxt<'tcx>, args: Vec, } impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { let abi = match it.kind { hir::ItemKind::ForeignMod { abi, .. } => abi, _ => return, }; if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { return; } // First, add all of the custom #[link_args] attributes let sess = &self.tcx.sess; for m in it.attrs.iter().filter(|a| sess.check_name(a, sym::link_args)) { if let Some(linkarg) = m.value_str() { self.add_link_args(linkarg); } } } fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {} fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {} fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {} } impl<'tcx> Collector<'tcx> { fn add_link_args(&mut self, args: Symbol) { self.args.extend(args.as_str().split(' ').filter(|s| !s.is_empty()).map(|s| s.to_string())) } }