1
1
use std:: cell:: RefCell ;
2
- use std:: collections:: HashSet ;
2
+ use std:: collections:: { HashMap , HashSet } ;
3
3
use std:: ops:: ControlFlow ;
4
4
use std:: path:: { Path , PathBuf } ;
5
+ use std:: rc:: Rc ;
5
6
use std:: { env, fmt} ;
6
7
7
8
use clang:: { Entity , EntityKind } ;
8
9
use 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 ,
10
12
} ;
11
13
12
14
struct FunctionFinder < ' tu , ' f > {
@@ -18,14 +20,22 @@ struct FunctionFinder<'tu, 'f> {
18
20
19
21
impl < ' tu , ' f > FunctionFinder < ' tu , ' f > {
20
22
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
+
21
31
let identifier = f. identifier ( ) ;
22
32
23
33
self . func_exclude_unused . borrow_mut ( ) . remove ( identifier. as_str ( ) ) ;
24
34
self . func_cfg_attr_unused . borrow_mut ( ) . remove ( identifier. as_str ( ) ) ;
25
35
}
26
36
}
27
37
28
- impl < ' tu > EntityWalkerVisitor < ' tu > for FunctionFinder < ' tu , ' _ > {
38
+ impl < ' tu > EntityWalkerVisitor < ' tu > for & mut FunctionFinder < ' tu , ' _ > {
29
39
fn wants_file ( & mut self , path : & Path ) -> bool {
30
40
opencv_module_from_path ( path) . map_or ( false , |m| m == self . module )
31
41
}
@@ -78,6 +88,11 @@ fn main() {
78
88
let opencv_header_dirs = args. map ( PathBuf :: from) ;
79
89
let mut func_exclude_unused = settings:: FUNC_EXCLUDE . clone ( ) ;
80
90
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 ( ) ) ) ;
81
96
for opencv_header_dir in opencv_header_dirs {
82
97
println ! ( "Processing header dir: {}" , opencv_header_dir. display( ) ) ;
83
98
let modules = opencv_header_dir
@@ -93,19 +108,84 @@ fn main() {
93
108
let gen = Generator :: new ( & opencv_header_dir, & [ ] , & src_cpp_dir) ;
94
109
for module in modules {
95
110
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
+ }
104
140
} ) ;
105
141
}
106
142
}
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
+ }
107
166
println ! ( "Unused entries in settings::FUNC_EXCLUDE ({}):" , func_exclude_unused. len( ) ) ;
108
167
show ( func_exclude_unused) ;
109
168
println ! ( "Unused entries in settings::FUNC_CFG_ATTR ({}):" , func_cfg_attr_unused. len( ) ) ;
110
169
show ( func_cfg_attr_unused) ;
111
170
}
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