diff --git a/rs/ic_os/config/BUILD.bazel b/rs/ic_os/config/BUILD.bazel index 351104a88153..2e8e69c0c3be 100644 --- a/rs/ic_os/config/BUILD.bazel +++ b/rs/ic_os/config/BUILD.bazel @@ -1,9 +1,17 @@ +load("@rules_rust//cargo:defs.bzl", "cargo_build_script") load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library", "rust_test") package(default_visibility = ["//rs:ic-os-pkg"]) +cargo_build_script( + name = "build_script", + srcs = ["build.rs"], + data = ["templates/guestos_vm_template.xml"], +) + DEPENDENCIES = [ # Keep sorted. + ":build_script", "//rs/ic_os/config_types", "//rs/ic_os/deterministic_ips", "//rs/ic_os/metrics_tool", @@ -79,7 +87,6 @@ rust_binary( name = "config", srcs = BIN_SOURCES, aliases = ALIASES, - compile_data = ["templates/guestos_vm_template.xml"], crate_name = "config", proc_macro_deps = MACRO_DEPENDENCIES, deps = [ @@ -91,7 +98,6 @@ rust_binary( name = "config_dev", srcs = BIN_SOURCES, aliases = ALIASES, - compile_data = ["templates/guestos_vm_template.xml"], crate_name = "config", proc_macro_deps = MACRO_DEPENDENCIES, deps = [ diff --git a/rs/ic_os/config/build.rs b/rs/ic_os/config/build.rs new file mode 100644 index 000000000000..3909106fda5c --- /dev/null +++ b/rs/ic_os/config/build.rs @@ -0,0 +1,37 @@ +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +// Build reproducibility. askama adds a include_bytes! call when it's generating +// a template impl so that rustc will recompile the module when the file changes +// on disk. See https://github.com/djc/askama/blob/180696053833147a61b3348646a953e7d92ae582/askama_shared/src/generator.rs#L141 +// The stringified output of every proc-macro is added to the metadata hash for +// a crate. That output includes the full filepath to include_bytes!. It may be +// different on two machines, if they use different tempdir paths for the build. +// However, if we include the html source directly in the output, no +// inconsistency is introduced. +fn main() { + println!("cargo:rerun-if-changed=templates/guestos_vm_template.xml"); + let mut f = File::create( + PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("guestos_vm_template.rs"), + ) + .unwrap(); + f.write_all( + format!( + r#" +#[derive(Template)] +#[template(escape = "xml", source = {:?}, ext = "xml")] +pub struct GuestOSTemplateProps<'a> {{ + pub cpu_domain: &'a str, + pub vm_memory: u32, + pub nr_of_vcpus: u32, + pub mac_address: MacAddr6, + pub config_media: &'a str, +}} + "#, + std::fs::read_to_string("templates/guestos_vm_template.xml").unwrap() + ) + .as_bytes(), + ) + .unwrap(); +} diff --git a/rs/ic_os/config/src/guest_vm_config.rs b/rs/ic_os/config/src/guest_vm_config.rs index 013b1edb1501..2a6933736dd6 100644 --- a/rs/ic_os/config/src/guest_vm_config.rs +++ b/rs/ic_os/config/src/guest_vm_config.rs @@ -14,6 +14,9 @@ use std::io::Write; use std::path::{Path, PathBuf}; use std::process::Command; +// See build.rs +include!(concat!(env!("OUT_DIR"), "/guestos_vm_template.rs")); + /// Generate the GuestOS VM configuration #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] @@ -194,18 +197,6 @@ fn make_bootstrap_options( Ok(bootstrap_options) } -// If you get a compile error pointing at #[derive(Template)], there is likely a syntax error in -// the template. -#[derive(Template)] -#[template(path = "guestos_vm_template.xml")] -pub struct GuestOSTemplateProps<'a> { - pub cpu_domain: &'a str, - pub vm_memory: u32, - pub nr_of_vcpus: u32, - pub mac_address: MacAddr6, - pub config_media: &'a str, -} - /// Generate the GuestOS VM libvirt XML configuration and return it as String. fn generate_vm_config(config: &HostOSConfig, media_path: &Path) -> Result { let mac_address = calculate_deterministic_mac(