11use std:: cell:: RefCell ;
2- use std:: collections:: HashSet ;
2+ use std:: collections:: { HashMap , HashSet } ;
33use std:: ops:: ControlFlow ;
44use std:: path:: { Path , PathBuf } ;
5+ use std:: rc:: Rc ;
56use std:: { env, fmt} ;
67
78use clang:: { Entity , EntityKind } ;
89use opencv_binding_generator:: {
9- opencv_module_from_path, settings, Class , EntityExt , EntityWalkerExt , EntityWalkerVisitor , Func , Generator , GeneratorEnv ,
10+ opencv_module_from_path, settings, Class , Constness , EntityExt , EntityWalkerExt , EntityWalkerVisitor , Func , Generator ,
11+ GeneratorEnv , Pred ,
1012} ;
1113
1214struct FunctionFinder < ' tu , ' f > {
@@ -18,14 +20,22 @@ struct FunctionFinder<'tu, 'f> {
1820
1921impl < ' tu , ' f > FunctionFinder < ' tu , ' f > {
2022 pub fn update_used_func ( & self , f : & Func ) {
23+ let mut matcher = f. matcher ( ) ;
24+ self . gen_env . settings . arg_override . get ( & mut matcher) ;
25+ self . gen_env . settings . return_override . get ( & mut matcher) ;
26+ self . gen_env . settings . force_infallible . get ( & mut matcher) ;
27+ self . gen_env . settings . func_replace . get ( & mut matcher) ;
28+ self . gen_env . settings . func_specialize . get ( & mut matcher) ;
29+ self . gen_env . settings . func_unsafe . get ( & mut matcher) ;
30+
2131 let identifier = f. identifier ( ) ;
2232
2333 self . func_exclude_unused . borrow_mut ( ) . remove ( identifier. as_str ( ) ) ;
2434 self . func_cfg_attr_unused . borrow_mut ( ) . remove ( identifier. as_str ( ) ) ;
2535 }
2636}
2737
28- impl < ' tu > EntityWalkerVisitor < ' tu > for FunctionFinder < ' tu , ' _ > {
38+ impl < ' tu > EntityWalkerVisitor < ' tu > for & mut FunctionFinder < ' tu , ' _ > {
2939 fn wants_file ( & mut self , path : & Path ) -> bool {
3040 opencv_module_from_path ( path) . map_or ( false , |m| m == self . module )
3141 }
@@ -78,6 +88,11 @@ fn main() {
7888 let opencv_header_dirs = args. map ( PathBuf :: from) ;
7989 let mut func_exclude_unused = settings:: FUNC_EXCLUDE . clone ( ) ;
8090 let mut func_cfg_attr_unused = settings:: FUNC_CFG_ATTR . keys ( ) . copied ( ) . collect :: < HashSet < _ > > ( ) ;
91+ // module -> usage_section -> (name, preds)
92+ let global_usage_tracking = Rc :: new ( RefCell :: new ( HashMap :: <
93+ String ,
94+ HashMap < & ' static str , HashSet < UsageTrackerOwned > > ,
95+ > :: new ( ) ) ) ;
8196 for opencv_header_dir in opencv_header_dirs {
8297 println ! ( "Processing header dir: {}" , opencv_header_dir. display( ) ) ;
8398 let modules = opencv_header_dir
@@ -93,19 +108,84 @@ fn main() {
93108 let gen = Generator :: new ( & opencv_header_dir, & [ ] , & src_cpp_dir) ;
94109 for module in modules {
95110 println ! ( " {module}" ) ;
96- gen. pre_process ( & module, false , |root_entity| {
97- let gen_env = GeneratorEnv :: global ( & module, root_entity) ;
98- root_entity. walk_opencv_entities ( FunctionFinder {
99- module : & module,
100- gen_env,
101- func_exclude_unused : RefCell :: new ( & mut func_exclude_unused) ,
102- func_cfg_attr_unused : RefCell :: new ( & mut func_cfg_attr_unused) ,
103- } ) ;
111+ gen. pre_process ( & module, false , {
112+ let global_usage_tracking = Rc :: clone ( & global_usage_tracking) ;
113+ |root_entity| {
114+ let global_usage_tracking = global_usage_tracking; // force move
115+ let mut gen_env = GeneratorEnv :: global ( & module, root_entity) ;
116+ gen_env. settings . start_usage_tracking ( ) ;
117+ let mut function_finder = FunctionFinder {
118+ module : & module,
119+ gen_env,
120+ func_exclude_unused : RefCell :: new ( & mut func_exclude_unused) ,
121+ func_cfg_attr_unused : RefCell :: new ( & mut func_cfg_attr_unused) ,
122+ } ;
123+ root_entity. walk_opencv_entities ( & mut function_finder) ;
124+
125+ let usage_tracking = function_finder. gen_env . settings . finish_usage_tracking ( ) ;
126+ let mut global_usage_tracking = global_usage_tracking. borrow_mut ( ) ;
127+ let module_usage_tracking = global_usage_tracking. entry ( module. to_string ( ) ) . or_default ( ) ;
128+ for ( usage_section, new_usage_tracking) in usage_tracking {
129+ let new_usage_tracking: HashSet < UsageTrackerOwned > = new_usage_tracking
130+ . into_iter ( )
131+ . map ( |( name, preds) | ( name. to_string ( ) , preds. iter ( ) . map ( PredOwned :: from_pred) . collect ( ) ) )
132+ . collect ( ) ;
133+ if let Some ( prev_usage_tracking) = module_usage_tracking. get_mut ( usage_section) {
134+ * prev_usage_tracking = new_usage_tracking. intersection ( prev_usage_tracking) . cloned ( ) . collect ( ) ;
135+ } else {
136+ module_usage_tracking. insert ( usage_section, new_usage_tracking) ;
137+ }
138+ }
139+ }
104140 } ) ;
105141 }
106142 }
143+
144+ let global_usage_tracking = Rc :: try_unwrap ( global_usage_tracking) . expect ( "Not owned" ) . into_inner ( ) ;
145+ let mut usage_per_section = HashMap :: new ( ) ;
146+ for ( _module, module_usage) in global_usage_tracking {
147+ for ( section, preds) in module_usage {
148+ let section_usage = usage_per_section. entry ( section) . or_insert_with ( Vec :: new) ;
149+ for ( name, preds) in preds {
150+ section_usage. push ( ( name, preds) ) ;
151+ }
152+ }
153+ }
154+ for ( section, mut usage_tracking) in usage_per_section {
155+ if usage_tracking. is_empty ( ) {
156+ println ! ( "No unused entries in {section}" ) ;
157+ } else {
158+ println ! ( "Unused entries in {section} ({}):" , usage_tracking. len( ) ) ;
159+ usage_tracking. sort_unstable ( ) ;
160+ for ( name, mut preds) in usage_tracking {
161+ preds. sort_unstable ( ) ;
162+ println ! ( " {name}: {preds:?}" ) ;
163+ }
164+ }
165+ }
107166 println ! ( "Unused entries in settings::FUNC_EXCLUDE ({}):" , func_exclude_unused. len( ) ) ;
108167 show ( func_exclude_unused) ;
109168 println ! ( "Unused entries in settings::FUNC_CFG_ATTR ({}):" , func_cfg_attr_unused. len( ) ) ;
110169 show ( func_cfg_attr_unused) ;
111170}
171+
172+ type UsageTrackerOwned = ( String , Vec < PredOwned > ) ;
173+
174+ #[ derive( Clone , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
175+ enum PredOwned {
176+ Constness ( Constness ) ,
177+ Return ( String ) ,
178+ ArgNames ( Vec < String > ) ,
179+ ArgTypes ( Vec < String > ) ,
180+ }
181+
182+ impl PredOwned {
183+ fn from_pred ( pred : & Pred ) -> Self {
184+ match pred {
185+ Pred :: Constness ( c) => Self :: Constness ( * c) ,
186+ Pred :: Return ( r) => Self :: Return ( r. to_string ( ) ) ,
187+ Pred :: ArgNames ( a) => Self :: ArgNames ( a. iter ( ) . map ( |s| s. to_string ( ) ) . collect ( ) ) ,
188+ Pred :: ArgTypes ( a) => Self :: ArgTypes ( a. iter ( ) . map ( |s| s. to_string ( ) ) . collect ( ) ) ,
189+ }
190+ }
191+ }
0 commit comments