@@ -5,6 +5,7 @@ use std::{
55 fs:: DirBuilder ,
66 io:: { Cursor , Seek , Write } ,
77 mem:: take,
8+ str:: FromStr ,
89 time:: Instant ,
910} ;
1011
@@ -36,7 +37,7 @@ use crate::{
3637 } ,
3738 util:: {
3839 asm:: write_asm,
39- bin2c:: bin2c,
40+ bin2c:: { bin2c, HeaderKind } ,
4041 comment:: MWComment ,
4142 config:: {
4243 apply_splits_file, apply_symbols_file, is_auto_symbol, signed_hex_serde,
@@ -303,6 +304,20 @@ pub struct ExtractConfig {
303304 /// Path is relative to `out_dir/include`.
304305 #[ serde( with = "unix_path_serde_option" , default , skip_serializing_if = "Option::is_none" ) ]
305306 pub header : Option < Utf8UnixPathBuf > ,
307+ /// The type for the extracted symbol in the header file. By default, the header will emit
308+ /// a full symbol declaration (a.k.a. `symbol`), but this can be set to `raw` to emit the raw
309+ /// data as a byte array. `none` avoids emitting a header entirely, in which case the `header`
310+ /// field can be used by external asset processing.
311+ #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
312+ pub header_type : Option < String > ,
313+ /// A user-defined type for use with external asset processing. This value is simply passed
314+ /// through to the `custom_type` field in the output config.
315+ #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
316+ pub custom_type : Option < String > ,
317+ /// User-defined data for use with external asset processing. This value is simply passed
318+ /// through to the `custom_data` field in the output config.
319+ #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
320+ pub custom_data : Option < serde_json:: Value > ,
306321}
307322
308323/// A relocation that should be blocked.
@@ -364,6 +379,19 @@ pub struct OutputModule {
364379 pub ldscript : Utf8UnixPathBuf ,
365380 pub entry : Option < String > ,
366381 pub units : Vec < OutputUnit > ,
382+ pub extract : Vec < OutputExtract > ,
383+ }
384+
385+ #[ derive( Serialize , Deserialize , Debug , Clone , Default ) ]
386+ pub struct OutputExtract {
387+ pub symbol : String ,
388+ #[ serde( with = "unix_path_serde_option" ) ]
389+ pub binary : Option < Utf8UnixPathBuf > ,
390+ #[ serde( with = "unix_path_serde_option" ) ]
391+ pub header : Option < Utf8UnixPathBuf > ,
392+ pub header_type : String ,
393+ pub custom_type : Option < String > ,
394+ pub custom_data : Option < serde_json:: Value > ,
367395}
368396
369397#[ derive( Serialize , Deserialize , Debug , Clone , Default , PartialEq , Eq , Hash ) ]
@@ -938,6 +966,7 @@ fn split_write_obj(
938966 ldscript : out_dir. join ( "ldscript.lcf" ) . with_unix_encoding ( ) ,
939967 units : Vec :: with_capacity ( split_objs. len ( ) ) ,
940968 entry,
969+ extract : Vec :: with_capacity ( module. config . extract . len ( ) ) ,
941970 } ;
942971 for ( unit, split_obj) in module. obj . link_order . iter ( ) . zip ( & split_objs) {
943972 let out_obj = write_elf ( split_obj, config. export_all ) ?;
@@ -975,14 +1004,34 @@ fn split_write_obj(
9751004 write_if_changed ( & out_path, data) ?;
9761005 }
9771006
978- if let Some ( header) = & extract. header {
979- let header_string = bin2c ( symbol, section, data) ;
980- let out_path = base_dir. join ( "include" ) . join ( header. with_encoding ( ) ) ;
981- if let Some ( parent) = out_path. parent ( ) {
982- DirBuilder :: new ( ) . recursive ( true ) . create ( parent) ?;
1007+ let header_kind = match extract. header_type . as_deref ( ) {
1008+ Some ( value) => match HeaderKind :: from_str ( value) {
1009+ Ok ( kind) => kind,
1010+ Err ( ( ) ) => bail ! ( "Invalid header type '{}'" , value) ,
1011+ } ,
1012+ _ => HeaderKind :: Symbol ,
1013+ } ;
1014+
1015+ if header_kind != HeaderKind :: None {
1016+ if let Some ( header) = & extract. header {
1017+ let header_string = bin2c ( symbol, section, data, header_kind) ;
1018+ let out_path = base_dir. join ( "include" ) . join ( header. with_encoding ( ) ) ;
1019+ if let Some ( parent) = out_path. parent ( ) {
1020+ DirBuilder :: new ( ) . recursive ( true ) . create ( parent) ?;
1021+ }
1022+ write_if_changed ( & out_path, header_string. as_bytes ( ) ) ?;
9831023 }
984- write_if_changed ( & out_path, header_string. as_bytes ( ) ) ?;
9851024 }
1025+
1026+ // Copy to output config
1027+ out_config. extract . push ( OutputExtract {
1028+ symbol : symbol. name . clone ( ) ,
1029+ binary : extract. binary . clone ( ) ,
1030+ header : extract. header . clone ( ) ,
1031+ header_type : header_kind. to_string ( ) ,
1032+ custom_type : extract. custom_type . clone ( ) ,
1033+ custom_data : extract. custom_data . clone ( ) ,
1034+ } ) ;
9861035 }
9871036
9881037 // Generate ldscript.lcf
0 commit comments