Skip to content

feature(cargo-miden): parse local path Miden dependencies from Cargo.toml #485

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 15, 2025
Merged
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
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 33 additions & 31 deletions tests/integration/src/compiler_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ pub struct CompilerTestBuilder {
/// The extra MASM modules to link to the compiled MASM program
link_masm_modules: LinkMasmModules,
/// Extra flags to pass to the midenc driver
midenc_flags: Vec<Cow<'static, str>>,
midenc_flags: Vec<String>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason for this change? Most of the flags we pass are constant strings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The names of the dependencies (Miden package filenames) that passed via --link-library option. They are parsed from our section in Cargo.toml.

/// Extra RUSTFLAGS to set when compiling Rust code
rustflags: Vec<Cow<'static, str>>,
/// The cargo workspace directory of the compiler
Expand Down Expand Up @@ -225,8 +225,7 @@ impl CompilerTestBuilder {
]);
let mut midenc_flags = vec!["--debug".into(), "--verbose".into()];
if let Some(entrypoint) = entrypoint {
midenc_flags
.extend(["--entrypoint".into(), format!("{}", entrypoint.display()).into()]);
midenc_flags.extend(["--entrypoint".into(), format!("{}", entrypoint.display())]);
}
Self {
config: Default::default(),
Expand Down Expand Up @@ -269,7 +268,7 @@ impl CompilerTestBuilder {
None => (),
}
self.midenc_flags
.extend(["--entrypoint".into(), format!("{}", entrypoint.display()).into()]);
.extend(["--entrypoint".into(), format!("{}", entrypoint.display())]);
self
}

Expand All @@ -278,7 +277,7 @@ impl CompilerTestBuilder {
&mut self,
flags: impl IntoIterator<Item = Cow<'static, str>>,
) -> &mut Self {
self.midenc_flags.extend(flags);
self.midenc_flags.extend(flags.into_iter().map(|s| s.to_string()));
self
}

Expand Down Expand Up @@ -306,7 +305,7 @@ impl CompilerTestBuilder {

/// Consume the builder, invoke any tools required to obtain the inputs for the test, and if
/// successful, return a [CompilerTest], ready for evaluation.
pub fn build(self) -> CompilerTest {
pub fn build(mut self) -> CompilerTest {
// Set up the command used to compile the test inputs (typically Rust -> Wasm)
let mut command = match self.source {
CompilerTestInputType::CargoMiden(_) => {
Expand Down Expand Up @@ -398,31 +397,26 @@ impl CompilerTestBuilder {

// Build test
match self.source {
CompilerTestInputType::CargoMiden(config) => {
let expected_wasm_artifact_path = config.wasm_artifact_path();
let skip_rust_compilation =
std::env::var("SKIP_RUST").is_ok() && expected_wasm_artifact_path.exists();
let wasm_artifact_path = if !skip_rust_compilation {
let mut args = vec![command.get_program().to_str().unwrap().to_string()];
let cmd_args: Vec<String> = command
.get_args()
.collect::<Vec<&OsStr>>()
.iter()
.map(|s| s.to_str().unwrap().to_string())
.collect();
args.extend(cmd_args);
let wasm_artifacts =
cargo_miden::run(args.into_iter(), cargo_miden::OutputType::Wasm).unwrap();
assert_eq!(
wasm_artifacts.len(),
1,
"expected one Wasm artifact, got {:?}",
wasm_artifacts
);
wasm_artifacts.first().unwrap().clone()
} else {
drop(command);
expected_wasm_artifact_path
CompilerTestInputType::CargoMiden(..) => {
let mut args = vec![command.get_program().to_str().unwrap().to_string()];
let cmd_args: Vec<String> = command
.get_args()
.collect::<Vec<&OsStr>>()
.iter()
.map(|s| s.to_str().unwrap().to_string())
.collect();
args.extend(cmd_args);
let build_output =
cargo_miden::run(args.into_iter(), cargo_miden::OutputType::Wasm)
.unwrap()
.expect("'cargo miden build' should return Some(CommandOutput)")
.unwrap_build_output(); // Use the new method
let (wasm_artifact_path, dependencies) = match build_output {
cargo_miden::BuildOutput::Wasm {
artifact_path,
dependencies,
} => (artifact_path, dependencies),
other => panic!("Expected Wasm output, got {:?}", other),
};
let artifact_name =
wasm_artifact_path.file_stem().unwrap().to_str().unwrap().to_string();
Expand All @@ -440,6 +434,10 @@ impl CompilerTestBuilder {
}));
// dbg!(&inputs);

for dep in &dependencies {
self.midenc_flags.push("--link-library".to_string());
self.midenc_flags.push(dep.to_str().unwrap().to_string());
}
let context = setup::default_context(inputs, &self.midenc_flags);
let session = context.session_rc();
CompilerTest {
Expand All @@ -448,6 +446,7 @@ impl CompilerTestBuilder {
context,
artifact_name: artifact_name.into(),
entrypoint: self.entrypoint,
dependencies,
..Default::default()
}
}
Expand Down Expand Up @@ -874,6 +873,8 @@ pub struct CompilerTest {
ir_masm_program: Option<Result<Arc<midenc_codegen_masm::MasmComponent>, String>>,
/// The compiled package containing a program executable by the VM
package: Option<Result<Arc<miden_mast_package::Package>, String>>,
/// Miden packages for dependencies
pub dependencies: Vec<PathBuf>,
}

impl fmt::Debug for CompilerTest {
Expand Down Expand Up @@ -907,6 +908,7 @@ impl Default for CompilerTest {
masm_src: None,
ir_masm_program: None,
package: None,
dependencies: Vec::new(),
}
}
}
Expand Down
55 changes: 15 additions & 40 deletions tests/integration/src/rust_masm_tests/rust_sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,14 @@ fn rust_sdk_p2id_note_script() {
.map(|s| s.to_string())
.collect();
dbg!(env::current_dir().unwrap().display());
let outputs = cargo_miden::run(args.into_iter(), cargo_miden::OutputType::Masm)
.expect("Failed to compile the basic-wallet package");
let masp_path: PathBuf = outputs.first().unwrap().clone();
let build_output = cargo_miden::run(args.into_iter(), cargo_miden::OutputType::Masm)
.expect("Failed to compile the basic-wallet package")
.expect("'cargo miden build' for basic-wallet should return Some(CommandOutput)")
.unwrap_build_output(); // Use the new method
let masp_path = match build_output {
cargo_miden::BuildOutput::Masm { artifact_path } => artifact_path,
other => panic!("Expected Masm output for basic-wallet, got {:?}", other),
};
dbg!(&masp_path);

//
Expand Down Expand Up @@ -163,46 +168,14 @@ fn rust_sdk_cross_ctx_account() {

#[test]
fn rust_sdk_cross_ctx_note() {
// Build cross-ctx-account package
let args: Vec<String> = [
"cargo",
"miden",
"build",
"--manifest-path",
"../rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.toml",
"--lib",
"--release",
// Use the target dir of this test's cargo project to avoid issues running tests in parallel
// i.e. avoid using the same target dir as the basic-wallet test (see above)
"--target-dir",
"../rust-apps-wasm/rust-sdk/cross-ctx-note/target",
]
.iter()
.map(|s| s.to_string())
.collect();
dbg!(env::current_dir().unwrap().display());

let outputs = cargo_miden::run(args.into_iter(), cargo_miden::OutputType::Masm)
.expect("Failed to compile the cross-ctx-account package for cross-ctx-note");
let masp_path: PathBuf = outputs.first().unwrap().clone();

dbg!(&masp_path);

let _ = env_logger::builder().is_test(true).try_init();

let config = WasmTranslationConfig::default();

let mut builder = CompilerTestBuilder::rust_source_cargo_miden(
"../rust-apps-wasm/rust-sdk/cross-ctx-note",
config,
[
"-l".into(),
"std".into(),
"-l".into(),
"base".into(),
"--link-library".into(),
masp_path.clone().into_os_string().into_string().unwrap().into(),
],
["-l".into(), "std".into(), "-l".into(), "base".into()],
);
builder.with_entrypoint(FunctionIdent {
module: Ident::new(Symbol::intern("miden:base/[email protected]"), SourceSpan::default()),
Expand All @@ -215,10 +188,12 @@ fn rust_sdk_cross_ctx_note() {
test.expect_masm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.masm")]);
let package = test.compiled_package();
let mut exec = Executor::new(vec![]);
let account_package =
Arc::new(Package::read_from_bytes(&std::fs::read(masp_path).unwrap()).unwrap());
exec.dependency_resolver_mut()
.add(account_package.digest(), account_package.into());
for dep_path in test.dependencies {
let account_package =
Arc::new(Package::read_from_bytes(&std::fs::read(dep_path).unwrap()).unwrap());
exec.dependency_resolver_mut()
.add(account_package.digest(), account_package.into());
}
exec.with_dependencies(&package.manifest.dependencies).unwrap();
let trace = exec.execute(&package.unwrap_program(), &test.session);
}
Expand Down
4 changes: 4 additions & 0 deletions tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ overflow-checks = false
debug = true
trim-paths = ["diagnostics", "object"]

# Miden dependencies for cargo-miden build/linking
[package.metadata.miden.dependencies]
"miden:cross-ctx-account" = { path = "../cross-ctx-account" }

# TODO: switch to miden table
[package.metadata.component]
package = "miden:cross-ctx-note"
Expand Down
3 changes: 3 additions & 0 deletions tools/cargo-miden/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ cargo-generate = "0.23"
path-absolutize = "3.1.1"
tokio.workspace = true
cargo-config2 = "0.1.24"
serde.workspace = true
toml.workspace = true
serde_json = "1.0"

[dev-dependencies]
miden-mast-package.workspace = true
8 changes: 8 additions & 0 deletions tools/cargo-miden/src/compile_masm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub fn wasm_to_masm(
wasm_file_path: &Path,
output_folder: &Path,
is_bin: bool,
dependency_paths: &[PathBuf], // New parameter
) -> Result<PathBuf, Report> {
if !output_folder.exists() {
return Err(Report::msg(format!(
Expand Down Expand Up @@ -52,6 +53,13 @@ pub fn wasm_to_masm(
args.push(entrypoint_opt.as_ref());
}

// Add dependency linker arguments (Step 3.3)
for dep_path in dependency_paths {
args.push("--link-library".as_ref());
// Ensure the path is valid OsStr
args.push(dep_path.as_os_str());
}

let session = Rc::new(Compiler::new_session([input], None, args));
let context = Rc::new(Context::new(session));
midenc_compile::compile(context.clone())?;
Expand Down
Loading