@@ -8,7 +8,9 @@ use anyhow::Result;
88use  cargo:: { Cargo ,  CargoAction ,  Feature ,  Package } ; 
99use  clap:: Parser ; 
1010use  opt:: { Action ,  BuildOpt ,  ClippyOpt ,  DocOpt ,  Opt ,  QemuOpt } ; 
11- use  util:: run_cmd; 
11+ use  std:: process:: Command ; 
12+ use  tempfile:: TempDir ; 
13+ use  util:: { command_to_string,  run_cmd} ; 
1214
1315fn  build ( opt :  & BuildOpt )  -> Result < ( ) >  { 
1416 let  cargo = Cargo  { 
@@ -105,6 +107,45 @@ fn run_host_tests() -> Result<()> {
105107 run_cmd ( cargo. command ( ) ?) 
106108} 
107109
110+ /// Test that the template app builds successfully with the released 
111+ /// versions of the libraries on crates.io. 
112+ /// 
113+ /// The `build` action also builds the template app, but due to the 
114+ /// `patch.crates-io` of the top-level Cargo.toml the app is built using 
115+ /// the current versions of the libraries in this repo. To give warning 
116+ /// when the latest crates.io releases of the libraries are broken (due 
117+ /// to changes in the nightly toolchain), this action copies the 
118+ /// template to a temporary directory and builds it in isolation. 
119+ /// 
120+ /// The build command is also checked against the contents of 
121+ /// `BUILDING.md` to ensure that the doc correctly describes how to 
122+ /// build an app. 
123+ fn  test_latest_release ( )  -> Result < ( ) >  { 
124+  // Recursively copy the template app to a temporary directory. This 
125+  // isolates the app from the full git repo so that the 
126+  // `patch.crates-io` section of the root Cargo.toml doesn't apply. 
127+  let  tmp_dir = TempDir :: new ( ) ?; 
128+  let  tmp_dir = tmp_dir. path ( ) ; 
129+  let  mut  cp_cmd = Command :: new ( "cp" ) ; 
130+  cp_cmd
131+  . args ( & [ "--recursive" ,  "--verbose" ,  "template" ] ) 
132+  . arg ( tmp_dir) ; 
133+  run_cmd ( cp_cmd) ?; 
134+ 
135+  // Create cargo build command, not using the `cargo` module to make 
136+  // it explicit that it matches the command in `BUILDING.md`. 
137+  let  mut  build_cmd = Command :: new ( "cargo" ) ; 
138+  build_cmd
139+  . args ( & [ "+nightly" ,  "build" ,  "--target" ,  "x86_64-unknown-uefi" ] ) 
140+  . current_dir ( tmp_dir. join ( "template" ) ) ; 
141+ 
142+  // Check that the command is indeed in BUILDING.md, then verify the 
143+  // build succeeds. 
144+  let  building_md = include_str ! ( "../../BUILDING.md" ) ; 
145+  assert ! ( building_md. contains( & command_to_string( & build_cmd) ) ) ; 
146+  run_cmd ( build_cmd) 
147+ } 
148+ 
108149fn  main ( )  -> Result < ( ) >  { 
109150 let  opt = Opt :: parse ( ) ; 
110151
@@ -114,5 +155,6 @@ fn main() -> Result<()> {
114155 Action :: Doc ( doc_opt)  => doc ( doc_opt) , 
115156 Action :: Run ( qemu_opt)  => run_vm_tests ( qemu_opt) , 
116157 Action :: Test ( _)  => run_host_tests ( ) , 
158+  Action :: TestLatestRelease ( _)  => test_latest_release ( ) , 
117159 } 
118160} 
0 commit comments