#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn main() {
use std::time::{Duration, Instant};
use supermachine::{builder, VmConfig};
let dockerfile = "FROM alpine\n\
ENV GREETING=hello-kvm\n\
RUN echo built-via-build_dockerfile > /built\n\
RUN mkdir -p /app && echo v2 > /app/version\n";
let df = builder::parse(dockerfile).expect("parse");
let ctx = std::env::temp_dir().join("sm-bd-ctx");
let _ = std::fs::create_dir_all(&ctx);
let cache = std::env::temp_dir().join("sm-bd-cache");
let _ = std::fs::remove_dir_all(&cache);
let b = builder::Builder::new(&cache);
eprintln!("=== build #1 (cold cache, FROM alpine via from_oci) ===");
let t0 = Instant::now();
let out = b.build_dockerfile(&df, &ctx).expect("build_dockerfile #1");
let build1 = t0.elapsed();
eprintln!("build #1 took {build1:?}");
eprintln!("=== boot built image, verify RUN effects ===");
let vm = out.image.start(&VmConfig::new()).expect("start built");
std::thread::sleep(Duration::from_millis(4000));
let o = vm
.exec_builder()
.argv(["/bin/sh", "-c", "cat /built; cat /app/version"])
.output()
.expect("exec verify");
let got = String::from_utf8_lossy(&o.stdout).trim_end().to_string();
eprintln!("built contents: {got:?}");
drop(vm);
eprintln!("=== build #2 (warm cache, same Dockerfile) ===");
let t1 = Instant::now();
let _out2 = b.build_dockerfile(&df, &ctx).expect("build_dockerfile #2");
let build2 = t1.elapsed();
eprintln!("build #2 took {build2:?} (should be ≪ build #1 — fully cached)");
let pass =
got.contains("built-via-build_dockerfile") && got.contains("v2") && build2 * 3 < build1; eprintln!(
"=== BUILD_DOCKERFILE ON KVM: {} (build1={build1:?} build2={build2:?}) ===",
if pass { "PASS" } else { "FAIL" }
);
}
#[cfg(not(all(target_os = "linux", target_arch = "x86_64")))]
fn main() {
eprintln!("kvm_build_dockerfile is Linux/x86_64 only");
}