Skip to content

Commit 8a88b7f

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

File tree

3 files changed

+99
-38
lines changed

3 files changed

+99
-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: 97 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,20 @@ 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.extend(defines.iter().map(|(n, ov)| {
212+
if let Some(v) = ov {
213+
format!("-D{n}={v}")
214+
} else {
215+
format!("-D{n}")
216+
}
217+
}));
218+
219+
print_cargo_metadata(nginx, &includes, &defines).expect("cargo dependency metadata");
211220

212221
// bindgen targets the latest known stable by default
213222
let rust_target: bindgen::RustTarget = env::var("CARGO_PKG_RUST_VERSION")
@@ -241,22 +250,47 @@ fn generate_binding(nginx: &NginxSource) {
241250
}
242251

243252
/// 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,
253+
/// and definitions used to compile nginx. This is used to generate the correct bindings
254+
/// for the nginx source code.
255+
pub fn parse_makefile(
256+
nginx_autoconf_makefile_path: &PathBuf,
257+
) -> (Vec<PathBuf>, Vec<(String, Option<String>)>) {
258+
fn parse_line(
259+
includes: &mut Vec<String>,
260+
defines: &mut Vec<(String, Option<String>)>,
261+
line: &str,
262+
) {
263+
let mut words = shlex::Shlex::new(line);
264+
265+
while let Some(word) = words.next() {
266+
if let Some(inc) = word.strip_prefix("-I") {
267+
let value = if inc.is_empty() {
268+
words.next().expect("-I argument")
269+
} else {
270+
inc.to_string()
271+
};
272+
includes.push(value);
273+
} else if let Some(def) = word.strip_prefix("-D") {
274+
let def = if def.is_empty() {
275+
words.next().expect("-D argument")
276+
} else {
277+
def.to_string()
278+
};
279+
280+
if let Some((name, value)) = def.split_once("=") {
281+
defines.push((name.to_string(), Some(value.to_string())));
282+
} else {
283+
defines.push((def.to_string(), None));
284+
}
285+
}
256286
}
257287
}
258288

259289
let mut includes = vec![];
290+
let mut cflags_includes = vec![];
291+
292+
let mut defines = vec![];
293+
260294
let makefile_contents = match read_to_string(nginx_autoconf_makefile_path) {
261295
Ok(path) => path,
262296
Err(e) => {
@@ -268,35 +302,39 @@ fn parse_includes_from_makefile(nginx_autoconf_makefile_path: &PathBuf) -> Vec<P
268302
}
269303
};
270304

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-
}
305+
let lines = makefile_contents.lines();
306+
let mut line: String = "".to_string();
307+
for l in lines {
308+
if let Some(part) = l.strip_suffix("\\") {
309+
line += part;
310+
continue;
281311
}
282312

283-
if includes_lines {
284-
if let Some(part) = extract_after_i_flag(line) {
285-
includes.push(part);
286-
} else {
287-
break;
288-
}
313+
line += l;
314+
315+
if let Some(tail) = line.strip_prefix("ALL_INCS") {
316+
parse_line(&mut includes, &mut defines, tail);
317+
} else if let Some(tail) = line.strip_prefix("CFLAGS") {
318+
parse_line(&mut cflags_includes, &mut defines, tail);
289319
}
320+
321+
line.clear();
290322
}
291323

292-
includes.into_iter().map(PathBuf::from).collect()
324+
cflags_includes.append(&mut includes);
325+
326+
(
327+
cflags_includes.into_iter().map(PathBuf::from).collect(),
328+
defines,
329+
)
293330
}
294331

295332
/// Collect info about the nginx configuration and expose it to the dependents via
296333
/// `DEP_NGINX_...` variables.
297334
pub fn print_cargo_metadata<T: AsRef<Path>>(
298335
nginx: &NginxSource,
299336
includes: &[T],
337+
defines: &[(String, Option<String>)],
300338
) -> Result<(), Box<dyn StdError>> {
301339
// Unquote and merge C string constants
302340
let unquote_re = regex::Regex::new(r#""(.*?[^\\])"\s*"#).unwrap();
@@ -311,7 +349,7 @@ pub fn print_cargo_metadata<T: AsRef<Path>>(
311349
let mut ngx_features: Vec<String> = vec![];
312350
let mut ngx_os = String::new();
313351

314-
let expanded = expand_definitions(includes)?;
352+
let expanded = expand_definitions(includes, defines)?;
315353
for line in String::from_utf8(expanded)?.lines() {
316354
let Some((name, value)) = line
317355
.trim()
@@ -350,6 +388,19 @@ pub fn print_cargo_metadata<T: AsRef<Path>>(
350388
.expect("Unicode include paths")
351389
);
352390

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

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

@@ -418,8 +472,13 @@ RUST_CONF_{flag}=NGX_{flag}
418472
writer.flush()?;
419473
drop(writer);
420474

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

0 commit comments

Comments
 (0)