@@ -19,6 +19,7 @@ use std::env;
1919use std:: fs;
2020use std:: io:: { Read , Write } ;
2121use std:: path:: Path ;
22+ use toml:: value:: Table ;
2223
2324fn main ( ) {
2425 let out_dir = env:: var ( "OUT_DIR" ) . unwrap ( ) ;
@@ -34,10 +35,13 @@ fn main() {
3435
3536 // Read Cargo.toml to check dependencies
3637 let cargo_toml_path = Path :: new ( & core_crate_dir) . join ( "Cargo.toml" ) ;
37- let mut cargo_toml_content = String :: new ( ) ;
38- if let Ok ( mut file) = fs:: File :: open ( & cargo_toml_path) {
39- file. read_to_string ( & mut cargo_toml_content) . unwrap ( ) ;
40- }
38+ let cargo_toml_content =
39+ fs:: read_to_string ( & cargo_toml_path) . expect ( "core Cargo.toml must be readable" ) ;
40+ let cargo_manifest: toml:: Value =
41+ toml:: from_str ( & cargo_toml_content) . expect ( "core Cargo.toml must be valid TOML" ) ;
42+ let dependencies = manifest_table ( & cargo_manifest, "dependencies" ) ;
43+ let dev_dependencies = manifest_table ( & cargo_manifest, "dev-dependencies" ) ;
44+ let features = manifest_table ( & cargo_manifest, "features" ) ;
4145
4246 if let Ok ( entries) = fs:: read_dir ( datafusion_dir) {
4347 for entry in entries. flatten ( ) {
@@ -53,11 +57,9 @@ fn main() {
5357 continue ;
5458 }
5559
56- // Skip if not a dependency in Cargo.toml
57- // This is a rough check
58- if !cargo_toml_content. contains ( & format ! ( "{crate_name} =" ) )
59- && !cargo_toml_content. contains ( & format ! ( "\" {crate_name}\" " ) )
60- {
60+ let is_dependency = dependencies. contains_key ( & crate_name)
61+ || dev_dependencies. contains_key ( & crate_name) ;
62+ if !is_dependency {
6163 continue ;
6264 }
6365
@@ -81,12 +83,9 @@ fn main() {
8183 for krate in crates_with_metrics {
8284 let krate_snake = krate. replace ( "-" , "_" ) ;
8385
84- let is_optional = cargo_toml_content
85- . lines ( )
86- . any ( |line| line. contains ( & krate) && line. contains ( "optional = true" ) ) ;
87-
88- if is_optional {
89- writeln ! ( f, " #[cfg(feature = \" {krate_snake}\" )]" ) . unwrap ( ) ;
86+ if is_optional_dependency ( & dependencies, & krate) {
87+ let feature = dependency_feature ( & features, & krate) ;
88+ writeln ! ( f, " #[cfg(feature = \" {feature}\" )]" ) . unwrap ( ) ;
9089 }
9190
9291 writeln ! ( f, " {{" ) . unwrap ( ) ;
@@ -100,6 +99,39 @@ fn main() {
10099 println ! ( "cargo:rerun-if-changed=Cargo.toml" ) ;
101100}
102101
102+ fn manifest_table ( manifest : & toml:: Value , key : & str ) -> Table {
103+ manifest
104+ . get ( key)
105+ . and_then ( |value| value. as_table ( ) )
106+ . cloned ( )
107+ . unwrap_or_default ( )
108+ }
109+
110+ fn is_optional_dependency ( dependencies : & Table , crate_name : & str ) -> bool {
111+ dependencies
112+ . get ( crate_name)
113+ . and_then ( |dep| dep. as_table ( ) )
114+ . and_then ( |dep| dep. get ( "optional" ) )
115+ . and_then ( |value| value. as_bool ( ) )
116+ . unwrap_or ( false )
117+ }
118+
119+ fn dependency_feature ( features : & Table , crate_name : & str ) -> String {
120+ let dep_feature = format ! ( "dep:{crate_name}" ) ;
121+ for ( feature, deps) in features {
122+ if let Some ( array) = deps. as_array ( ) {
123+ for dep in array {
124+ if let Some ( dep_str) = dep. as_str ( ) {
125+ if dep_str == crate_name || dep_str == dep_feature {
126+ return feature. clone ( ) ;
127+ }
128+ }
129+ }
130+ }
131+ }
132+ crate_name. to_string ( )
133+ }
134+
103135fn has_metric_doc ( dir : & Path ) -> bool {
104136 if let Ok ( entries) = fs:: read_dir ( dir) {
105137 for entry in entries. flatten ( ) {
0 commit comments