Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 28 additions & 53 deletions crates/miden-protocol/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,19 @@ use walkdir::WalkDir;
// CONSTANTS
// ================================================================================================

/// Defines whether the build script should generate files in `/src`.
/// The docs.rs build pipeline has a read-only filesystem, so we have to avoid writing to `src`,
/// otherwise the docs will fail to build there. Note that writing to `OUT_DIR` is fine.
const BUILD_GENERATED_FILES_IN_SRC: bool = option_env!("BUILD_GENERATED_FILES_IN_SRC").is_some();

const ASSETS_DIR: &str = "assets";
const ASM_DIR: &str = "asm";
const ASM_PROTOCOL_DIR: &str = "protocol";

const SHARED_UTILS_DIR: &str = "shared_utils";
const SHARED_MODULES_DIR: &str = "shared_modules";
const ASM_TX_KERNEL_DIR: &str = "kernels/transaction";
const KERNEL_PROCEDURES_RS_FILE: &str = "src/transaction/kernel/procedures.rs";

const PROTOCOL_LIB_NAMESPACE: &str = "miden::protocol";

const TX_KERNEL_ERRORS_FILE: &str = "src/errors/tx_kernel.rs";
const PROTOCOL_LIB_ERRORS_FILE: &str = "src/errors/protocol.rs";
const KERNEL_PROCEDURES_RS_FILE: &str = "procedures.rs";
const TX_KERNEL_ERRORS_RS_FILE: &str = "tx_kernel_errors.rs";
const PROTOCOL_LIB_ERRORS_RS_FILE: &str = "protocol_errors.rs";

const TX_KERNEL_ERRORS_ARRAY_NAME: &str = "TX_KERNEL_ERRORS";
const PROTOCOL_LIB_ERRORS_ARRAY_NAME: &str = "PROTOCOL_LIB_ERRORS";
Expand Down Expand Up @@ -61,7 +56,6 @@ const TX_KERNEL_ERROR_CATEGORIES: [&str; 14] = [
fn main() -> Result<()> {
// re-build when the MASM code changes
println!("cargo::rerun-if-changed={ASM_DIR}/");
println!("cargo::rerun-if-env-changed=BUILD_GENERATED_FILES_IN_SRC");

// Copies the MASM code to the build directory
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
Expand All @@ -80,14 +74,17 @@ fn main() -> Result<()> {
let target_dir = Path::new(&build_dir).join(ASSETS_DIR);

// compile transaction kernel
let mut assembler =
compile_tx_kernel(&source_dir.join(ASM_TX_KERNEL_DIR), &target_dir.join("kernels"))?;
let mut assembler = compile_tx_kernel(
&source_dir.join(ASM_TX_KERNEL_DIR),
&target_dir.join("kernels"),
&build_dir,
)?;

// compile protocol library
let protocol_lib = compile_protocol_lib(&source_dir, &target_dir, assembler.clone())?;
assembler.link_dynamic_library(protocol_lib)?;

generate_error_constants(&source_dir)?;
generate_error_constants(&source_dir, &build_dir)?;

generate_event_constants(&source_dir, &target_dir)?;

Expand Down Expand Up @@ -118,7 +115,7 @@ fn main() -> Result<()> {
/// - {target_dir}/tx_script_main.masb -> contains the executable compiled from
/// tx_script_main.masm.
/// - src/transaction/procedures/kernel_v0.rs -> contains the kernel procedures table.
fn compile_tx_kernel(source_dir: &Path, target_dir: &Path) -> Result<Assembler> {
fn compile_tx_kernel(source_dir: &Path, target_dir: &Path, build_dir: &str) -> Result<Assembler> {
let shared_utils_path = std::path::Path::new(ASM_DIR).join(SHARED_UTILS_DIR);
let kernel_path = miden_assembly::Path::kernel_path();

Expand All @@ -131,7 +128,7 @@ fn compile_tx_kernel(source_dir: &Path, target_dir: &Path) -> Result<Assembler>
.assemble_kernel_from_dir(source_dir.join("api.masm"), Some(source_dir.join("lib")))?;

// generate kernel `procedures.rs` file
generate_kernel_proc_hash_file(kernel_lib.clone())?;
generate_kernel_proc_hash_file(kernel_lib.clone(), build_dir)?;

let output_file = target_dir.join("tx_kernel").with_extension(Library::LIBRARY_EXTENSION);
kernel_lib.write_to_file(output_file).into_diagnostic()?;
Expand Down Expand Up @@ -192,14 +189,10 @@ fn compile_tx_script_main(
tx_script_main.write_to_file(masb_file_path).into_diagnostic()
}

/// Generates kernel `procedures.rs` file based on the kernel library
fn generate_kernel_proc_hash_file(kernel: KernelLibrary) -> Result<()> {
// Because the kernel Rust file will be stored under ./src, this should be a no-op if we can't
// write there
if !BUILD_GENERATED_FILES_IN_SRC {
return Ok(());
}

/// Generates kernel `procedures.rs` file based on the kernel library.
///
/// The file is written to `{build_dir}/procedures.rs` and included via `include!` in the source.
fn generate_kernel_proc_hash_file(kernel: KernelLibrary, build_dir: &str) -> Result<()> {
let (_, module_info, _) = kernel.into_parts();

let to_exclude = BTreeSet::from_iter(["exec_kernel_proc"]);
Expand Down Expand Up @@ -230,8 +223,9 @@ fn generate_kernel_proc_hash_file(kernel: KernelLibrary) -> Result<()> {
txt
}).collect::<Vec<_>>().join("\n");

shared::write_if_changed(
KERNEL_PROCEDURES_RS_FILE,
let output_path = Path::new(build_dir).join(KERNEL_PROCEDURES_RS_FILE);
fs::write(
output_path,
format!(
r#"// This file is generated by build.rs, do not modify

Expand All @@ -247,6 +241,7 @@ pub const KERNEL_PROCEDURES: [Word; {proc_count}] = [
"#,
),
)
.into_diagnostic()
}

fn parse_proc_offsets(filename: impl AsRef<Path>) -> Result<BTreeMap<String, usize>> {
Expand Down Expand Up @@ -352,14 +347,9 @@ fn copy_shared_modules<T: AsRef<Path>>(source_dir: T) -> Result<()> {
/// The function ensures that a constant is not defined twice, except if their error message is
/// the same. This can happen across multiple files.
///
/// Because the error files will be written to ./src/errors, this should be a no-op if ./src is
/// read-only. To enable writing to ./src, set the `BUILD_GENERATED_FILES_IN_SRC` environment
/// variable.
fn generate_error_constants(asm_source_dir: &Path) -> Result<()> {
if !BUILD_GENERATED_FILES_IN_SRC {
return Ok(());
}

/// The generated files are written to `build_dir` (i.e. `OUT_DIR`) and included via `include!`
/// in the source.
fn generate_error_constants(asm_source_dir: &Path, build_dir: &str) -> Result<()> {
// Transaction kernel errors
// ------------------------------------------

Expand All @@ -370,7 +360,7 @@ fn generate_error_constants(asm_source_dir: &Path) -> Result<()> {

shared::generate_error_file(
shared::ErrorModule {
file_name: TX_KERNEL_ERRORS_FILE,
file_path: Path::new(build_dir).join(TX_KERNEL_ERRORS_RS_FILE),
array_name: TX_KERNEL_ERRORS_ARRAY_NAME,
is_crate_local: true,
},
Expand All @@ -386,7 +376,7 @@ fn generate_error_constants(asm_source_dir: &Path) -> Result<()> {

shared::generate_error_file(
shared::ErrorModule {
file_name: PROTOCOL_LIB_ERRORS_FILE,
file_path: Path::new(build_dir).join(PROTOCOL_LIB_ERRORS_RS_FILE),
array_name: PROTOCOL_LIB_ERRORS_ARRAY_NAME,
is_crate_local: true,
},
Expand Down Expand Up @@ -736,7 +726,7 @@ mod shared {
}

/// Generates the content of an error file for the given category and the set of errors and
/// writes it to the category's file.
/// writes it to the file at the path specified in the module.
pub fn generate_error_file(module: ErrorModule, errors: Vec<NamedError>) -> Result<()> {
let mut output = String::new();

Expand Down Expand Up @@ -783,26 +773,11 @@ mod shared {
.into_diagnostic()?;
}

write_if_changed(module.file_name, output)?;
fs::write(module.file_path, output).into_diagnostic()?;

Ok(())
}

/// Writes `contents` to `path` only if the file doesn't exist or its current contents
/// differ. This avoids updating the file's mtime when nothing changed, which prevents
/// cargo from treating the crate as dirty on the next build.
pub fn write_if_changed(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> Result<()> {
let path = path.as_ref();
let new_contents = contents.as_ref();
if path.exists() {
let existing = std::fs::read(path).into_diagnostic()?;
if existing == new_contents {
return Ok(());
}
}
std::fs::write(path, new_contents).into_diagnostic()
}

pub type ErrorName = String;

#[derive(Debug, Clone)]
Expand All @@ -816,9 +791,9 @@ mod shared {
pub message: String,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone)]
pub struct ErrorModule {
pub file_name: &'static str,
pub file_path: PathBuf,
pub array_name: &'static str,
pub is_crate_local: bool,
}
Expand Down
10 changes: 6 additions & 4 deletions crates/miden-protocol/src/errors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,15 @@ pub use masm_error::MasmError;

/// The errors from the MASM code of the transaction kernel.
#[cfg(any(feature = "testing", test))]
#[rustfmt::skip]
pub mod tx_kernel;
pub mod tx_kernel {
include!(concat!(env!("OUT_DIR"), "/tx_kernel_errors.rs"));
}

/// The errors from the MASM code of the Miden protocol library.
#[cfg(any(feature = "testing", test))]
#[rustfmt::skip]
pub mod protocol;
pub mod protocol {
include!(concat!(env!("OUT_DIR"), "/protocol_errors.rs"));
}

// ACCOUNT COMPONENT TEMPLATE ERROR
// ================================================================================================
Expand Down
42 changes: 0 additions & 42 deletions crates/miden-protocol/src/errors/protocol.rs

This file was deleted.

Loading