Skip to content

Commit 3a666d7

Browse files
author
Gopa Kumar
committed
Add new bindgen options to generate wrappers for inline functions
1 parent 63b8713 commit 3a666d7

File tree

2 files changed

+93
-4
lines changed

2 files changed

+93
-4
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ build-time = "0.1" # For esp_app_desc!()
3535
const_format = "0.2" # For esp_app_desc!()
3636

3737
[build-dependencies]
38-
embuild = { version = "0.31.2", features = ["glob", "kconfig"] }
38+
embuild = { git = "https://github.com/gopakumarce/embuild.git", branch = "gopa-inline_fns", features = ["glob", "kconfig"] }
3939
anyhow = "1"
4040
regex = "1.5"
41-
bindgen = "0.63"
41+
bindgen = { version = "0.65.1", features = ["experimental"] }
4242
cargo_metadata = "0.15"
4343
serde = { version = "1.0", features = ["derive"] }
4444
strum = { version = "0.24", features = ["derive"] }

build/build.rs

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
compile_error!("One of the features `pio` or `native` must be selected.");
33
use std::iter::once;
44

5+
use crate::native::cargo_driver::chip::Chip;
56
use anyhow::*;
67
use bindgen::callbacks::{IntKind, ParseCallbacks};
78
use common::*;
89
use embuild::bindgen::BindgenExt;
910
use embuild::utils::OsStrExt;
1011
use embuild::{bindgen as bindgen_utils, build, cargo, kconfig, path_buf};
12+
use std::io::Write;
13+
use std::str::FromStr;
1114

1215
mod common;
1316
mod config;
@@ -48,6 +51,85 @@ impl ParseCallbacks for BindgenCallbacks {
4851
}
4952
}
5053

54+
fn strip_quotes(args: &str) -> Vec<String> {
55+
let mut out = vec![];
56+
for arg in args.split_whitespace() {
57+
let mut chars = arg.chars();
58+
let first = chars.next();
59+
chars.next_back();
60+
let trim = if first == Some('\"') {
61+
chars.as_str()
62+
} else {
63+
arg
64+
};
65+
out.push(trim.to_string());
66+
}
67+
out
68+
}
69+
70+
fn process_static_inlines(
71+
build_output_args: &str,
72+
clang_args: Vec<String>,
73+
mcu: &str,
74+
headers: Vec<std::path::PathBuf>,
75+
) -> anyhow::Result<()> {
76+
let chip = Chip::from_str(mcu)?;
77+
let gcc = format!("{}-gcc", chip.gcc_toolchain());
78+
let ar = format!("{}-gcc-ar", chip.gcc_toolchain());
79+
80+
let out_dir_path = cargo::out_dir();
81+
82+
let mut gcc_cmd = std::process::Command::new(gcc);
83+
let mut gcc_args = gcc_cmd
84+
.arg("-mlongcalls")
85+
.arg("-O")
86+
.arg("-c")
87+
.arg("-o")
88+
.arg(out_dir_path.join("static_inlines.o"))
89+
.arg(out_dir_path.join("static_inlines.c"));
90+
for hdr in headers.iter() {
91+
gcc_args = gcc_args.arg("-include").arg(hdr);
92+
}
93+
gcc_args = gcc_args.args(strip_quotes(build_output_args));
94+
gcc_args = gcc_args.args(clang_args);
95+
96+
let gcc_output = gcc_args.output().unwrap();
97+
if !gcc_output.status.success() {
98+
panic!(
99+
"Could not compile object file:\n{}",
100+
String::from_utf8_lossy(&gcc_output.stderr)
101+
);
102+
}
103+
104+
#[cfg(not(target_os = "windows"))]
105+
let lib_output = std::process::Command::new(ar)
106+
.arg("rcs")
107+
.arg(out_dir_path.join("libstatic_inlines.a"))
108+
.arg(out_dir_path.join("static_inlines.o"))
109+
.output()
110+
.unwrap();
111+
#[cfg(target_os = "windows")]
112+
let lib_output = std::process::Command::new("lib")
113+
.arg(&obj_path)
114+
.output()
115+
.unwrap();
116+
117+
if !lib_output.status.success() {
118+
panic!(
119+
"Could not emit library file:\n{}",
120+
String::from_utf8_lossy(&lib_output.stderr)
121+
);
122+
}
123+
124+
println!(
125+
"cargo:rustc-link-search=native={}",
126+
out_dir_path.to_string_lossy()
127+
);
128+
println!("cargo:rustc-link-lib=static=static_inlines");
129+
130+
Ok(())
131+
}
132+
51133
fn main() -> anyhow::Result<()> {
52134
let build_output = build_driver::build()?;
53135

@@ -97,9 +179,13 @@ fn main() -> anyhow::Result<()> {
97179
// Because we have multiple bindgen invocations and we can't clone a bindgen::Builder,
98180
// we have to set the options every time.
99181
let configure_bindgen = |bindgen: bindgen::Builder| {
182+
let mut outdir = cargo::out_dir();
183+
outdir.push("static_inlines");
100184
Ok(bindgen
101185
.parse_callbacks(Box::new(BindgenCallbacks))
102186
.use_core()
187+
.wrap_static_fns(true)
188+
.wrap_static_fns_path(outdir)
103189
.enable_function_attribute_detection()
104190
.clang_arg("-DESP_PLATFORM")
105191
.blocklist_function("strtold")
@@ -145,7 +231,7 @@ fn main() -> anyhow::Result<()> {
145231
);
146232

147233
configure_bindgen(build_output.bindgen.clone().builder()?)?
148-
.headers(headers)?
234+
.headers(headers.clone())?
149235
.generate()
150236
.with_context(bindgen_err)?
151237
.write_to_file(&bindings_file)
@@ -185,7 +271,7 @@ fn main() -> anyhow::Result<()> {
185271
.into_iter()
186272
.chain(EspIdfVersion::parse(bindings_file)?.cfg_args())
187273
.chain(build_output.components.cfg_args())
188-
.chain(once(mcu))
274+
.chain(once(mcu.clone()))
189275
.collect(),
190276
};
191277
cfg_args.propagate();
@@ -211,5 +297,8 @@ fn main() -> anyhow::Result<()> {
211297
link_args.propagate();
212298
}
213299

300+
let clang_args: Vec<String> = build_output.components.clang_args().collect();
301+
process_static_inlines(&build_output.cincl_args.args, clang_args, &mcu, headers)?;
302+
214303
Ok(())
215304
}

0 commit comments

Comments
 (0)