1- use std:: path:: PathBuf ;
1+ use std:: fs;
2+ use std:: path:: { Path , PathBuf } ;
23
34use anyhow:: Result ;
45use clap:: { Args , Subcommand } ;
6+ use hermit_entry:: config;
57
68use crate :: cargo_build:: CargoBuild ;
79
@@ -58,6 +60,7 @@ impl Rs {
5860 }
5961
6062 let mut cargo = crate :: cargo ( ) ;
63+ let parent_root = super :: parent_root ( ) ;
6164
6265 if self . package . contains ( "rftrace" ) {
6366 cargo. env (
@@ -67,7 +70,7 @@ impl Rs {
6770 } ;
6871
6972 cargo
70- . current_dir ( super :: parent_root ( ) )
73+ . current_dir ( parent_root)
7174 . arg ( "build" )
7275 . args ( self . cargo_build . artifact . arch . ci_cargo_args ( ) )
7376 . args ( self . cargo_build . cargo_build_args ( ) )
@@ -77,10 +80,88 @@ impl Rs {
7780 let status = cargo. status ( ) ?;
7881 assert ! ( status. success( ) ) ;
7982
83+ // discover possible initramfs seed
84+ let manifest_dir = {
85+ let cur_package = cargo_metadata:: PackageName :: new ( self . package . clone ( ) ) ;
86+ let mut cargo = cargo_metadata:: MetadataCommand :: new ( ) ;
87+ cargo
88+ . current_dir ( parent_root)
89+ . no_deps ( )
90+ . verbose ( true )
91+ . exec ( ) ?
92+ . packages
93+ . iter ( )
94+ . find ( |i| i. name == cur_package)
95+ . expect ( "unable to find current package in `cargo metadata` output" )
96+ // this path points to `Cargo.toml`
97+ . manifest_path
98+ . parent ( )
99+ . unwrap ( )
100+ . to_path_buf ( )
101+ } ;
102+ eprintln ! ( "MANIFEST_DIR = {manifest_dir}" ) ;
103+ let maybe_initramfs = {
104+ let initramfs = manifest_dir. join ( "initramfs" ) ;
105+ if initramfs. is_dir ( ) {
106+ Some ( initramfs)
107+ } else {
108+ None
109+ }
110+ } ;
111+
112+ let mut build_artifact = self . cargo_build . artifact . ci_image ( & self . package ) ;
113+
114+ // handle possible initramfs
115+ if let Some ( initramfs) = maybe_initramfs {
116+ eprintln ! ( "discovered initramfs seed, creating initramfs." ) ;
117+ // find kernel name
118+ let konfig = fs:: read_to_string ( initramfs. join ( config:: Config :: DEFAULT_PATH ) ) ?;
119+ let konfig: config:: Config < ' _ > = toml:: from_str ( & konfig) ?;
120+ let kernel_name: & str = match & konfig {
121+ config:: Config :: V1 { kernel, .. } => kernel,
122+ } ;
123+
124+ let tar_artifact_path = build_artifact. with_extension ( "tar.gz" ) ;
125+ let mut tar_artifact = tar:: Builder :: new ( flate2:: write:: GzEncoder :: new (
126+ fs:: File :: create ( & tar_artifact_path) ?,
127+ flate2:: Compression :: default ( ) ,
128+ ) ) ;
129+ tar_artifact. mode ( tar:: HeaderMode :: Deterministic ) ;
130+
131+ // NOTE: use tar ustar to create the image.
132+
133+ // add kernel
134+ eprintln ! ( "- {kernel_name}" ) ;
135+ {
136+ let mut header = tar:: Header :: new_ustar ( ) ;
137+ let kernel_meta = fs:: metadata ( & build_artifact) ?;
138+ header. set_path ( kernel_name) . unwrap ( ) ;
139+ header. set_size ( kernel_meta. len ( ) ) ;
140+ header. set_cksum ( ) ;
141+
142+ tar_artifact. append ( & header, fs:: File :: open ( & build_artifact) ?) ?;
143+ }
144+
145+ // add rest
146+ for entry in walkdir:: WalkDir :: new ( & initramfs) {
147+ let entry = entry?;
148+ let entry_rel_path = entry. path ( ) . strip_prefix ( & initramfs) ?;
149+ eprintln ! ( "- {}" , entry_rel_path. display( ) ) ;
150+ if entry_rel_path == Path :: new ( kernel_name) || entry. metadata ( ) ?. is_dir ( ) {
151+ continue ;
152+ }
153+
154+ tar_artifact. append_path_with_name ( entry. path ( ) , entry_rel_path) ?;
155+ }
156+
157+ tar_artifact. into_inner ( ) ?. finish ( ) ?. sync_all ( ) ?;
158+ build_artifact = tar_artifact_path;
159+ }
160+
80161 if super :: in_ci ( ) {
81162 eprintln ! ( "::endgroup::" ) ;
82163 }
83164
84- Ok ( self . cargo_build . artifact . ci_image ( & self . package ) )
165+ Ok ( build_artifact )
85166 }
86167}
0 commit comments