Skip to content

Commit eb36542

Browse files
committed
fix: use CFLAGS from Makefile
1 parent a129a2e commit eb36542

File tree

3 files changed

+87
-35
lines changed

3 files changed

+87
-35
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nginx-sys/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ cc = "1.2.0"
3030
dunce = "1.0.5"
3131
regex = "1.11.1"
3232
nginx-src = { version = "~1.28.0", optional = true, path = "../nginx-src" }
33+
shlex = "1.3"
3334

3435
[features]
3536
vendored = ["dep:nginx-src"]

nginx-sys/build/main.rs

Lines changed: 85 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ impl NginxSource {
192192
/// Generates Rust bindings for NGINX
193193
fn 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,47 @@ 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 parse_line(
251+
includes: &mut Vec<String>,
252+
mut defines: Option<&mut Vec<(String, Option<String>)>>,
253+
line: &str,
254+
) {
255+
let mut words = shlex::Shlex::new(line);
256+
257+
while let Some(word) = words.next() {
258+
if let Some(inc) = word.strip_prefix("-I") {
259+
let value = if inc.is_empty() {
260+
words.next().expect("-I argument")
261+
} else {
262+
inc.to_string()
263+
};
264+
includes.push(value);
265+
} else if let Some(defs) = defines.as_mut() {
266+
if let Some(def) = word.strip_prefix("-D") {
267+
let def = if def.is_empty() {
268+
words.next().expect("-D argument")
269+
} else {
270+
def.to_string()
271+
};
272+
273+
if let Some((name, value)) = def.split_once("=") {
274+
defs.push((name.to_string(), Some(value.to_string())));
275+
} else {
276+
defs.push((def.to_string(), None));
277+
}
278+
}
279+
}
256280
}
257281
}
258282

259283
let mut includes = vec![];
284+
let mut cflags_includes = vec![];
285+
286+
let mut defines = vec![];
287+
260288
let makefile_contents = match read_to_string(nginx_autoconf_makefile_path) {
261289
Ok(path) => path,
262290
Err(e) => {
@@ -268,35 +296,36 @@ fn parse_includes_from_makefile(nginx_autoconf_makefile_path: &PathBuf) -> Vec<P
268296
}
269297
};
270298

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-
}
299+
let lines = makefile_contents.lines();
300+
let mut line: String = "".to_string();
301+
for l in lines {
302+
if let Some(part) = l.strip_suffix("\\") {
303+
line += part;
304+
continue;
281305
}
282306

283-
if includes_lines {
284-
if let Some(part) = extract_after_i_flag(line) {
285-
includes.push(part);
286-
} else {
287-
break;
288-
}
307+
line += l;
308+
309+
if let Some(tail) = line.strip_prefix("ALL_INCS") {
310+
parse_line(&mut includes, None, tail);
311+
} else if let Some(tail) = line.strip_prefix("CFLAGS") {
312+
parse_line(&mut cflags_includes, Some(&mut defines), tail);
289313
}
314+
315+
line.clear();
290316
}
291317

292-
includes.into_iter().map(PathBuf::from).collect()
318+
includes.append(&mut cflags_includes);
319+
320+
(includes.into_iter().map(PathBuf::from).collect(), defines)
293321
}
294322

295323
/// Collect info about the nginx configuration and expose it to the dependents via
296324
/// `DEP_NGINX_...` variables.
297325
pub fn print_cargo_metadata<T: AsRef<Path>>(
298326
nginx: &NginxSource,
299327
includes: &[T],
328+
defines: &[(String, Option<String>)],
300329
) -> Result<(), Box<dyn StdError>> {
301330
// Unquote and merge C string constants
302331
let unquote_re = regex::Regex::new(r#""(.*?[^\\])"\s*"#).unwrap();
@@ -311,7 +340,7 @@ pub fn print_cargo_metadata<T: AsRef<Path>>(
311340
let mut ngx_features: Vec<String> = vec![];
312341
let mut ngx_os = String::new();
313342

314-
let expanded = expand_definitions(includes)?;
343+
let expanded = expand_definitions(includes, defines)?;
315344
for line in String::from_utf8(expanded)?.lines() {
316345
let Some((name, value)) = line
317346
.trim()
@@ -350,6 +379,19 @@ pub fn print_cargo_metadata<T: AsRef<Path>>(
350379
.expect("Unicode include paths")
351380
);
352381

382+
println!(
383+
"cargo:metadata=cflags={}",
384+
defines
385+
.iter()
386+
.map(|(n, ov)| if let Some(v) = ov {
387+
format!("-D{n}={v}")
388+
} else {
389+
format!("-D{n}")
390+
})
391+
.collect::<Vec<_>>()
392+
.join(" ")
393+
);
394+
353395
// A quoted list of all recognized features to be passed to rustc-check-cfg.
354396
let values = NGX_CONF_FEATURES.join("\",\"");
355397
println!("cargo::metadata=features_check=\"{values}\"");
@@ -372,7 +414,10 @@ pub fn print_cargo_metadata<T: AsRef<Path>>(
372414
Ok(())
373415
}
374416

375-
fn expand_definitions<T: AsRef<Path>>(includes: &[T]) -> Result<Vec<u8>, Box<dyn StdError>> {
417+
fn expand_definitions<T: AsRef<Path>>(
418+
includes: &[T],
419+
defines: &[(String, Option<String>)],
420+
) -> Result<Vec<u8>, Box<dyn StdError>> {
376421
let path = PathBuf::from(env::var("OUT_DIR")?).join("expand.c");
377422
let mut writer = std::io::BufWriter::new(File::create(&path)?);
378423

@@ -418,8 +463,13 @@ RUST_CONF_{flag}=NGX_{flag}
418463
writer.flush()?;
419464
drop(writer);
420465

421-
Ok(cc::Build::new()
422-
.includes(includes)
423-
.file(path)
424-
.try_expand()?)
466+
let mut builder = cc::Build::new();
467+
468+
builder.includes(includes).file(path);
469+
470+
for def in defines {
471+
builder.define(&def.0, def.1.as_deref());
472+
}
473+
474+
Ok(builder.try_expand()?)
425475
}

0 commit comments

Comments
 (0)