Skip to content

Commit 5bc5605

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

File tree

3 files changed

+101
-38
lines changed

3 files changed

+101
-38
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: 99 additions & 38 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() {
@@ -202,12 +203,25 @@ fn generate_binding(nginx: &NginxSource) {
202203
}
203204
})
204205
.collect();
205-
let clang_args: Vec<String> = includes
206+
let mut clang_args: Vec<String> = includes
206207
.iter()
207208
.map(|path| format!("-I{}", path.to_string_lossy()))
208209
.collect();
209210

210-
print_cargo_metadata(nginx, &includes).expect("cargo dependency metadata");
211+
clang_args.append(
212+
&mut defines
213+
.iter()
214+
.map(|(n, ov)| {
215+
if let Some(v) = ov {
216+
format!("-D{n}={v}")
217+
} else {
218+
format!("-D{n}")
219+
}
220+
})
221+
.collect(),
222+
);
223+
224+
print_cargo_metadata(nginx, &includes, &defines).expect("cargo dependency metadata");
211225

212226
// bindgen targets the latest known stable by default
213227
let rust_target: bindgen::RustTarget = env::var("CARGO_PKG_RUST_VERSION")
@@ -241,22 +255,47 @@ fn generate_binding(nginx: &NginxSource) {
241255
}
242256

243257
/// Reads through the makefile generated by autoconf and finds all of the includes
244-
/// used to compile nginx. This is used to generate the correct bindings for the
245-
/// 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,
258+
/// and definitions used to compile nginx. This is used to generate the correct bindings
259+
/// for the nginx source code.
260+
pub fn parse_makefile(
261+
nginx_autoconf_makefile_path: &PathBuf,
262+
) -> (Vec<PathBuf>, Vec<(String, Option<String>)>) {
263+
fn parse_line(
264+
includes: &mut Vec<String>,
265+
defines: &mut Vec<(String, Option<String>)>,
266+
line: &str,
267+
) {
268+
let mut words = shlex::Shlex::new(line);
269+
270+
while let Some(word) = words.next() {
271+
if let Some(inc) = word.strip_prefix("-I") {
272+
let value = if inc.is_empty() {
273+
words.next().expect("-I argument")
274+
} else {
275+
inc.to_string()
276+
};
277+
includes.push(value);
278+
} else if let Some(def) = word.strip_prefix("-D") {
279+
let def = if def.is_empty() {
280+
words.next().expect("-D argument")
281+
} else {
282+
def.to_string()
283+
};
284+
285+
if let Some((name, value)) = def.split_once("=") {
286+
defines.push((name.to_string(), Some(value.to_string())));
287+
} else {
288+
defines.push((def.to_string(), None));
289+
}
290+
}
256291
}
257292
}
258293

259294
let mut includes = vec![];
295+
let mut cflags_includes = vec![];
296+
297+
let mut defines = vec![];
298+
260299
let makefile_contents = match read_to_string(nginx_autoconf_makefile_path) {
261300
Ok(path) => path,
262301
Err(e) => {
@@ -268,35 +307,36 @@ fn parse_includes_from_makefile(nginx_autoconf_makefile_path: &PathBuf) -> Vec<P
268307
}
269308
};
270309

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-
}
310+
let lines = makefile_contents.lines();
311+
let mut line: String = "".to_string();
312+
for l in lines {
313+
if let Some(part) = l.strip_suffix("\\") {
314+
line += part;
315+
continue;
281316
}
282317

283-
if includes_lines {
284-
if let Some(part) = extract_after_i_flag(line) {
285-
includes.push(part);
286-
} else {
287-
break;
288-
}
318+
line += l;
319+
320+
if let Some(tail) = line.strip_prefix("ALL_INCS") {
321+
parse_line(&mut includes, &mut defines, tail);
322+
} else if let Some(tail) = line.strip_prefix("CFLAGS") {
323+
parse_line(&mut cflags_includes, &mut defines, tail);
289324
}
325+
326+
line.clear();
290327
}
291328

292-
includes.into_iter().map(PathBuf::from).collect()
329+
includes.append(&mut cflags_includes);
330+
331+
(includes.into_iter().map(PathBuf::from).collect(), defines)
293332
}
294333

295334
/// Collect info about the nginx configuration and expose it to the dependents via
296335
/// `DEP_NGINX_...` variables.
297336
pub fn print_cargo_metadata<T: AsRef<Path>>(
298337
nginx: &NginxSource,
299338
includes: &[T],
339+
defines: &[(String, Option<String>)],
300340
) -> Result<(), Box<dyn StdError>> {
301341
// Unquote and merge C string constants
302342
let unquote_re = regex::Regex::new(r#""(.*?[^\\])"\s*"#).unwrap();
@@ -311,7 +351,7 @@ pub fn print_cargo_metadata<T: AsRef<Path>>(
311351
let mut ngx_features: Vec<String> = vec![];
312352
let mut ngx_os = String::new();
313353

314-
let expanded = expand_definitions(includes)?;
354+
let expanded = expand_definitions(includes, defines)?;
315355
for line in String::from_utf8(expanded)?.lines() {
316356
let Some((name, value)) = line
317357
.trim()
@@ -350,6 +390,19 @@ pub fn print_cargo_metadata<T: AsRef<Path>>(
350390
.expect("Unicode include paths")
351391
);
352392

393+
println!(
394+
"cargo:metadata=cflags={}",
395+
defines
396+
.iter()
397+
.map(|(n, ov)| if let Some(v) = ov {
398+
format!("-D{n}={v}")
399+
} else {
400+
format!("-D{n}")
401+
})
402+
.collect::<Vec<_>>()
403+
.join(" ")
404+
);
405+
353406
// A quoted list of all recognized features to be passed to rustc-check-cfg.
354407
let values = NGX_CONF_FEATURES.join("\",\"");
355408
println!("cargo::metadata=features_check=\"{values}\"");
@@ -372,7 +425,10 @@ pub fn print_cargo_metadata<T: AsRef<Path>>(
372425
Ok(())
373426
}
374427

375-
fn expand_definitions<T: AsRef<Path>>(includes: &[T]) -> Result<Vec<u8>, Box<dyn StdError>> {
428+
fn expand_definitions<T: AsRef<Path>>(
429+
includes: &[T],
430+
defines: &[(String, Option<String>)],
431+
) -> Result<Vec<u8>, Box<dyn StdError>> {
376432
let path = PathBuf::from(env::var("OUT_DIR")?).join("expand.c");
377433
let mut writer = std::io::BufWriter::new(File::create(&path)?);
378434

@@ -418,8 +474,13 @@ RUST_CONF_{flag}=NGX_{flag}
418474
writer.flush()?;
419475
drop(writer);
420476

421-
Ok(cc::Build::new()
422-
.includes(includes)
423-
.file(path)
424-
.try_expand()?)
477+
let mut builder = cc::Build::new();
478+
479+
builder.includes(includes).file(path);
480+
481+
for def in defines {
482+
builder.define(&def.0, def.1.as_deref());
483+
}
484+
485+
Ok(builder.try_expand()?)
425486
}

0 commit comments

Comments
 (0)