22compile_error ! ( "One of the features `pio` or `native` must be selected." ) ;
33use std:: iter:: once;
44
5+ use crate :: native:: cargo_driver:: chip:: Chip ;
56use anyhow:: * ;
67use bindgen:: callbacks:: { IntKind , ParseCallbacks } ;
78use common:: * ;
89use embuild:: bindgen:: BindgenExt ;
910use embuild:: utils:: OsStrExt ;
1011use embuild:: { bindgen as bindgen_utils, build, cargo, kconfig, path_buf} ;
12+ use std:: io:: Write ;
13+ use std:: str:: FromStr ;
1114
1215mod common;
1316mod 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+
51133fn 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