From 2e09e97189f6acb5adc79a3ae7131077d7da6047 Mon Sep 17 00:00:00 2001 From: Evgeny Shirykalov Date: Tue, 15 Jul 2025 15:29:38 -0700 Subject: [PATCH] fix: use CFLAGS from Makefile --- Cargo.lock | 1 + nginx-sys/Cargo.toml | 1 + nginx-sys/build/main.rs | 137 ++++++++++++++++++++++++++++------------ 3 files changed, 100 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40161e1b..60136339 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -576,6 +576,7 @@ dependencies = [ "errno", "nginx-src", "regex", + "shlex", ] [[package]] diff --git a/nginx-sys/Cargo.toml b/nginx-sys/Cargo.toml index 8780749a..b04c496f 100644 --- a/nginx-sys/Cargo.toml +++ b/nginx-sys/Cargo.toml @@ -30,6 +30,7 @@ cc = "1.2.0" dunce = "1.0.5" regex = "1.11.1" nginx-src = { version = "~1.28.0", optional = true, path = "../nginx-src" } +shlex = "1.3" [features] vendored = ["dep:nginx-src"] diff --git a/nginx-sys/build/main.rs b/nginx-sys/build/main.rs index a206dee9..8f85bd0c 100644 --- a/nginx-sys/build/main.rs +++ b/nginx-sys/build/main.rs @@ -192,7 +192,8 @@ impl NginxSource { /// Generates Rust bindings for NGINX fn generate_binding(nginx: &NginxSource) { let autoconf_makefile_path = nginx.build_dir.join("Makefile"); - let includes: Vec<_> = parse_includes_from_makefile(&autoconf_makefile_path) + let (includes, defines) = parse_makefile(&autoconf_makefile_path); + let includes: Vec<_> = includes .into_iter() .map(|path| { if path.is_absolute() { @@ -202,12 +203,20 @@ fn generate_binding(nginx: &NginxSource) { } }) .collect(); - let clang_args: Vec = includes + let mut clang_args: Vec = includes .iter() .map(|path| format!("-I{}", path.to_string_lossy())) .collect(); - print_cargo_metadata(nginx, &includes).expect("cargo dependency metadata"); + clang_args.extend(defines.iter().map(|(n, ov)| { + if let Some(v) = ov { + format!("-D{n}={v}") + } else { + format!("-D{n}") + } + })); + + print_cargo_metadata(nginx, &includes, &defines).expect("cargo dependency metadata"); // bindgen targets the latest known stable by default let rust_target: bindgen::RustTarget = env::var("CARGO_PKG_RUST_VERSION") @@ -241,22 +250,47 @@ fn generate_binding(nginx: &NginxSource) { } /// Reads through the makefile generated by autoconf and finds all of the includes -/// used to compile nginx. This is used to generate the correct bindings for the -/// nginx source code. -fn parse_includes_from_makefile(nginx_autoconf_makefile_path: &PathBuf) -> Vec { - fn extract_include_part(line: &str) -> &str { - line.strip_suffix('\\').map_or(line, |s| s.trim()) - } - /// Extracts the include path from a line of the autoconf generated makefile. - fn extract_after_i_flag(line: &str) -> Option<&str> { - let mut parts = line.split("-I "); - match parts.next() { - Some(_) => parts.next().map(extract_include_part), - None => None, +/// and definitions used to compile nginx. This is used to generate the correct bindings +/// for the nginx source code. +pub fn parse_makefile( + nginx_autoconf_makefile_path: &PathBuf, +) -> (Vec, Vec<(String, Option)>) { + fn parse_line( + includes: &mut Vec, + defines: &mut Vec<(String, Option)>, + line: &str, + ) { + let mut words = shlex::Shlex::new(line); + + while let Some(word) = words.next() { + if let Some(inc) = word.strip_prefix("-I") { + let value = if inc.is_empty() { + words.next().expect("-I argument") + } else { + inc.to_string() + }; + includes.push(value); + } else if let Some(def) = word.strip_prefix("-D") { + let def = if def.is_empty() { + words.next().expect("-D argument") + } else { + def.to_string() + }; + + if let Some((name, value)) = def.split_once("=") { + defines.push((name.to_string(), Some(value.to_string()))); + } else { + defines.push((def.to_string(), None)); + } + } } } - let mut includes = vec![]; + let mut all_incs = vec![]; + let mut cflags_includes = vec![]; + + let mut defines = vec![]; + let makefile_contents = match read_to_string(nginx_autoconf_makefile_path) { Ok(path) => path, Err(e) => { @@ -268,28 +302,31 @@ fn parse_includes_from_makefile(nginx_autoconf_makefile_path: &PathBuf) -> Vec

Vec

>( nginx: &NginxSource, includes: &[T], + defines: &[(String, Option)], ) -> Result<(), Box> { // Unquote and merge C string constants let unquote_re = regex::Regex::new(r#""(.*?[^\\])"\s*"#).unwrap(); @@ -311,7 +349,7 @@ pub fn print_cargo_metadata>( let mut ngx_features: Vec = vec![]; let mut ngx_os = String::new(); - let expanded = expand_definitions(includes)?; + let expanded = expand_definitions(includes, defines)?; for line in String::from_utf8(expanded)?.lines() { let Some((name, value)) = line .trim() @@ -350,6 +388,19 @@ pub fn print_cargo_metadata>( .expect("Unicode include paths") ); + println!( + "cargo:metadata=cflags={}", + defines + .iter() + .map(|(n, ov)| if let Some(v) = ov { + format!("-D{n}={v}") + } else { + format!("-D{n}") + }) + .collect::>() + .join(" ") + ); + // A quoted list of all recognized features to be passed to rustc-check-cfg. let values = NGX_CONF_FEATURES.join("\",\""); println!("cargo::metadata=features_check=\"{values}\""); @@ -372,7 +423,10 @@ pub fn print_cargo_metadata>( Ok(()) } -fn expand_definitions>(includes: &[T]) -> Result, Box> { +fn expand_definitions>( + includes: &[T], + defines: &[(String, Option)], +) -> Result, Box> { let path = PathBuf::from(env::var("OUT_DIR")?).join("expand.c"); let mut writer = std::io::BufWriter::new(File::create(&path)?); @@ -418,8 +472,13 @@ RUST_CONF_{flag}=NGX_{flag} writer.flush()?; drop(writer); - Ok(cc::Build::new() - .includes(includes) - .file(path) - .try_expand()?) + let mut builder = cc::Build::new(); + + builder.includes(includes).file(path); + + for def in defines { + builder.define(&def.0, def.1.as_deref()); + } + + Ok(builder.try_expand()?) }