@@ -192,7 +192,8 @@ impl NginxSource {
192192/// Generates Rust bindings for NGINX
193193fn generate_binding ( nginx : & NginxSource ) {
194194 let autoconf_makefile_path = nginx. build_dir . join ( "Makefile" ) ;
195- let includes: Vec < _ > = parse_includes_from_makefile ( & autoconf_makefile_path)
195+ let ( includes, defines) = parse_makefile ( & autoconf_makefile_path) ;
196+ let includes: Vec < _ > = includes
196197 . into_iter ( )
197198 . map ( |path| {
198199 if path. is_absolute ( ) {
@@ -207,7 +208,7 @@ fn generate_binding(nginx: &NginxSource) {
207208 . map ( |path| format ! ( "-I{}" , path. to_string_lossy( ) ) )
208209 . collect ( ) ;
209210
210- print_cargo_metadata ( nginx, & includes) . expect ( "cargo dependency metadata" ) ;
211+ print_cargo_metadata ( nginx, & includes, & defines ) . expect ( "cargo dependency metadata" ) ;
211212
212213 // bindgen targets the latest known stable by default
213214 let rust_target: bindgen:: RustTarget = env:: var ( "CARGO_PKG_RUST_VERSION" )
@@ -243,20 +244,27 @@ fn generate_binding(nginx: &NginxSource) {
243244/// Reads through the makefile generated by autoconf and finds all of the includes
244245/// used to compile nginx. This is used to generate the correct bindings for the
245246/// nginx source code.
246- fn parse_includes_from_makefile ( nginx_autoconf_makefile_path : & PathBuf ) -> Vec < PathBuf > {
247- fn extract_include_part ( line : & str ) -> & str {
248- line. strip_suffix ( '\\' ) . map_or ( line, |s| s. trim ( ) )
249- }
250- /// Extracts the include path from a line of the autoconf generated makefile.
251- fn extract_after_i_flag ( line : & str ) -> Option < & str > {
252- let mut parts = line. split ( "-I " ) ;
253- match parts. next ( ) {
254- Some ( _) => parts. next ( ) . map ( extract_include_part) ,
255- None => None ,
247+ pub fn parse_makefile (
248+ nginx_autoconf_makefile_path : & PathBuf ,
249+ ) -> ( Vec < PathBuf > , Vec < ( String , Option < String > ) > ) {
250+ fn add_includes ( includes : & mut Vec < String > , line : & str ) {
251+ let mut words = line. split_ascii_whitespace ( ) ;
252+ while let Some ( word) = words. next ( ) {
253+ if word == "-I" {
254+ if let Some ( inc) = words. next ( ) {
255+ includes. push ( inc. to_string ( ) ) ;
256+ }
257+ } else if let Some ( inc) = word. strip_prefix ( "-I" ) {
258+ includes. push ( inc. to_string ( ) ) ;
259+ }
256260 }
257261 }
258262
259263 let mut includes = vec ! [ ] ;
264+ let mut cflags_includes = vec ! [ ] ;
265+
266+ let mut defines = vec ! [ ] ;
267+
260268 let makefile_contents = match read_to_string ( nginx_autoconf_makefile_path) {
261269 Ok ( path) => path,
262270 Err ( e) => {
@@ -268,35 +276,47 @@ fn parse_includes_from_makefile(nginx_autoconf_makefile_path: &PathBuf) -> Vec<P
268276 }
269277 } ;
270278
271- let mut includes_lines = false ;
272- for line in makefile_contents. lines ( ) {
273- if !includes_lines {
274- if let Some ( stripped) = line. strip_prefix ( "ALL_INCS" ) {
275- includes_lines = true ;
276- if let Some ( part) = extract_after_i_flag ( stripped) {
277- includes. push ( part) ;
278- }
279- continue ;
280- }
279+ let lines = makefile_contents. lines ( ) ;
280+ let mut line: String = "" . to_string ( ) ;
281+ for l in lines {
282+ if let Some ( part) = l. strip_suffix ( "\\ " ) {
283+ line += part;
284+ continue ;
281285 }
282286
283- if includes_lines {
284- if let Some ( part) = extract_after_i_flag ( line) {
285- includes. push ( part) ;
286- } else {
287- break ;
287+ line += l;
288+
289+ if let Some ( tail) = line. strip_prefix ( "ALL_INCS" ) {
290+ add_includes ( & mut includes, tail) ;
291+ } else if let Some ( tail) = line. strip_prefix ( "CFLAGS" ) {
292+ add_includes ( & mut cflags_includes, tail) ;
293+
294+ let words = line. split_ascii_whitespace ( ) ;
295+ for word in words {
296+ if let Some ( def) = word. strip_prefix ( "-D" ) {
297+ if let Some ( ( name, value) ) = def. split_once ( "=" ) {
298+ defines. push ( ( name. to_string ( ) , Some ( value. to_string ( ) ) ) ) ;
299+ } else {
300+ defines. push ( ( def. to_string ( ) , None ) ) ;
301+ }
302+ }
288303 }
289304 }
305+
306+ line. clear ( ) ;
290307 }
291308
292- includes. into_iter ( ) . map ( PathBuf :: from) . collect ( )
309+ includes. append ( & mut cflags_includes) ;
310+
311+ ( includes. into_iter ( ) . map ( PathBuf :: from) . collect ( ) , defines)
293312}
294313
295314/// Collect info about the nginx configuration and expose it to the dependents via
296315/// `DEP_NGINX_...` variables.
297316pub fn print_cargo_metadata < T : AsRef < Path > > (
298317 nginx : & NginxSource ,
299318 includes : & [ T ] ,
319+ defines : & [ ( String , Option < String > ) ] ,
300320) -> Result < ( ) , Box < dyn StdError > > {
301321 // Unquote and merge C string constants
302322 let unquote_re = regex:: Regex :: new ( r#""(.*?[^\\])"\s*"# ) . unwrap ( ) ;
@@ -311,7 +331,7 @@ pub fn print_cargo_metadata<T: AsRef<Path>>(
311331 let mut ngx_features: Vec < String > = vec ! [ ] ;
312332 let mut ngx_os = String :: new ( ) ;
313333
314- let expanded = expand_definitions ( includes) ?;
334+ let expanded = expand_definitions ( includes, defines ) ?;
315335 for line in String :: from_utf8 ( expanded) ?. lines ( ) {
316336 let Some ( ( name, value) ) = line
317337 . trim ( )
@@ -372,7 +392,10 @@ pub fn print_cargo_metadata<T: AsRef<Path>>(
372392 Ok ( ( ) )
373393}
374394
375- fn expand_definitions < T : AsRef < Path > > ( includes : & [ T ] ) -> Result < Vec < u8 > , Box < dyn StdError > > {
395+ fn expand_definitions < T : AsRef < Path > > (
396+ includes : & [ T ] ,
397+ defines : & [ ( String , Option < String > ) ] ,
398+ ) -> Result < Vec < u8 > , Box < dyn StdError > > {
376399 let path = PathBuf :: from ( env:: var ( "OUT_DIR" ) ?) . join ( "expand.c" ) ;
377400 let mut writer = std:: io:: BufWriter :: new ( File :: create ( & path) ?) ;
378401
@@ -418,8 +441,13 @@ RUST_CONF_{flag}=NGX_{flag}
418441 writer. flush ( ) ?;
419442 drop ( writer) ;
420443
421- Ok ( cc:: Build :: new ( )
422- . includes ( includes)
423- . file ( path)
424- . try_expand ( ) ?)
444+ let mut builder = cc:: Build :: new ( ) ;
445+
446+ builder. includes ( includes) . file ( path) ;
447+
448+ for def in defines {
449+ builder. define ( & def. 0 , def. 1 . as_deref ( ) ) ;
450+ }
451+
452+ Ok ( builder. try_expand ( ) ?)
425453}
0 commit comments