From 09c25baa2b6c8107844f2d2943b64bea980f9dcf Mon Sep 17 00:00:00 2001 From: Linwei Shang Date: Wed, 8 Dec 2021 14:53:57 -0800 Subject: [PATCH] fix: Rust canister resolve dependency (#1949) * Rust canister resolve dependency * e2e * skip shellcheck * Fix cargo install * Remove cargo install * Inter-canister call from update method * Install ic-cdk-optimizer before e2e * Install ic-cdk-optimizer during provision-{os} * Increase timout to 1800s --- .github/workflows/e2e.yml | 2 +- e2e/assets/rust_deps/Cargo.toml | 4 ++++ e2e/assets/rust_deps/dfx.json | 23 +++++++++++++++++++ e2e/assets/rust_deps/patch.bash | 1 + .../rust_deps/src/multiply_deps/main.mo | 11 +++++++++ e2e/assets/rust_deps/src/rust_deps/Cargo.toml | 14 +++++++++++ e2e/assets/rust_deps/src/rust_deps/lib.rs | 11 +++++++++ .../rust_deps/src/rust_deps/rust_deps.did | 3 +++ e2e/tests-dfx/rust.bash | 15 ++++++++++++ src/dfx/src/lib/builders/rust.rs | 23 ++++++++++++++++++- 10 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 e2e/assets/rust_deps/Cargo.toml create mode 100644 e2e/assets/rust_deps/dfx.json create mode 100644 e2e/assets/rust_deps/patch.bash create mode 100644 e2e/assets/rust_deps/src/multiply_deps/main.mo create mode 100644 e2e/assets/rust_deps/src/rust_deps/Cargo.toml create mode 100644 e2e/assets/rust_deps/src/rust_deps/lib.rs create mode 100644 e2e/assets/rust_deps/src/rust_deps/rust_deps.did diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index a218c5320a..5cf371091b 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -127,7 +127,7 @@ jobs: fi export - name: Run e2e test - run: timeout 1200 bats "e2e/$E2E_TEST" + run: timeout 1800 bats "e2e/$E2E_TEST" aggregate: name: e2e:required diff --git a/e2e/assets/rust_deps/Cargo.toml b/e2e/assets/rust_deps/Cargo.toml new file mode 100644 index 0000000000..654647eb91 --- /dev/null +++ b/e2e/assets/rust_deps/Cargo.toml @@ -0,0 +1,4 @@ +[workspace] +members = [ + "src/rust_deps", +] diff --git a/e2e/assets/rust_deps/dfx.json b/e2e/assets/rust_deps/dfx.json new file mode 100644 index 0000000000..1f2e105954 --- /dev/null +++ b/e2e/assets/rust_deps/dfx.json @@ -0,0 +1,23 @@ +{ + "canisters": { + "multiply_deps": { + "main": "src/multiply_deps/main.mo", + "type": "motoko" + }, + "rust_deps": { + "candid": "src/rust_deps/rust_deps.did", + "package": "rust_deps", + "type": "rust", + "dependencies": [ + "multiply_deps" + ] + } + }, + "networks": { + "local": { + "bind": "127.0.0.1:8000", + "type": "ephemeral" + } + }, + "version": 1 +} \ No newline at end of file diff --git a/e2e/assets/rust_deps/patch.bash b/e2e/assets/rust_deps/patch.bash new file mode 100644 index 0000000000..be830bd8c9 --- /dev/null +++ b/e2e/assets/rust_deps/patch.bash @@ -0,0 +1 @@ +# nothing to do diff --git a/e2e/assets/rust_deps/src/multiply_deps/main.mo b/e2e/assets/rust_deps/src/multiply_deps/main.mo new file mode 100644 index 0000000000..d427e71f03 --- /dev/null +++ b/e2e/assets/rust_deps/src/multiply_deps/main.mo @@ -0,0 +1,11 @@ +actor Multiply { + + var cell : Nat = 1; + + public func mul(n:Nat) : async Nat { cell *= n*3; cell }; + + public query func read() : async Nat { + cell + }; +} + diff --git a/e2e/assets/rust_deps/src/rust_deps/Cargo.toml b/e2e/assets/rust_deps/src/rust_deps/Cargo.toml new file mode 100644 index 0000000000..52285adfb8 --- /dev/null +++ b/e2e/assets/rust_deps/src/rust_deps/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rust_deps" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +path = "lib.rs" +crate-type = ["cdylib"] + +[dependencies] +ic-cdk = "0.3" +ic-cdk-macros = "0.3" diff --git a/e2e/assets/rust_deps/src/rust_deps/lib.rs b/e2e/assets/rust_deps/src/rust_deps/lib.rs new file mode 100644 index 0000000000..b5f4d16d21 --- /dev/null +++ b/e2e/assets/rust_deps/src/rust_deps/lib.rs @@ -0,0 +1,11 @@ +use ic_cdk_macros::*; +use ic_cdk::export::candid; + +#[import(canister = "multiply_deps")] +struct CounterCanister; + +// Inter-canister call can only be from a update call +#[update] +async fn read() -> candid::Nat { + CounterCanister::read().await.0 +} diff --git a/e2e/assets/rust_deps/src/rust_deps/rust_deps.did b/e2e/assets/rust_deps/src/rust_deps/rust_deps.did new file mode 100644 index 0000000000..b4f4a7f3b9 --- /dev/null +++ b/e2e/assets/rust_deps/src/rust_deps/rust_deps.did @@ -0,0 +1,3 @@ +service : { + "read": () -> (nat); +} diff --git a/e2e/tests-dfx/rust.bash b/e2e/tests-dfx/rust.bash index b271f51d03..8383cb5764 100644 --- a/e2e/tests-dfx/rust.bash +++ b/e2e/tests-dfx/rust.bash @@ -20,6 +20,7 @@ teardown() { assert_command dfx build hello assert_match "ic-cdk-optimizer not installed" cargo install ic-cdk-optimizer + # shellcheck disable=SC2030 export PATH="$HOME/.cargo/bin/:$PATH" assert_command dfx build hello assert_match "Executing: ic-cdk-optimizer" @@ -27,3 +28,17 @@ teardown() { assert_command dfx canister --no-wallet call hello greet dfinity assert_match '("Hello, dfinity!")' } + +@test "rust canister can resolve dependencies" { + dfx_new_rust rust_deps + install_asset rust_deps + + dfx_start + assert_command dfx deploy + assert_command dfx canister call multiply_deps read + assert_match '(1 : nat)' + assert_command dfx canister call multiply_deps mul '(3)' + assert_match '(9 : nat)' + assert_command dfx canister call rust_deps read + assert_match '(9 : nat)' +} diff --git a/src/dfx/src/lib/builders/rust.rs b/src/dfx/src/lib/builders/rust.rs index f610275e54..4b820770f8 100644 --- a/src/dfx/src/lib/builders/rust.rs +++ b/src/dfx/src/lib/builders/rust.rs @@ -59,7 +59,7 @@ impl CanisterBuilder for RustBuilder { fn build( &self, - _pool: &CanisterPool, + pool: &CanisterPool, canister_info: &CanisterInfo, _config: &BuildConfig, ) -> DfxResult { @@ -78,6 +78,27 @@ impl CanisterBuilder for RustBuilder { .arg("--release") .arg("-p") .arg(package); + + if let Ok(dependencies) = self.get_dependencies(pool, canister_info) { + for deps in dependencies { + let canister = pool.get_canister(&deps).unwrap(); + cargo.env( + format!("CANISTER_ID_{}", canister.get_name()), + deps.to_text(), + ); + if let Some(output) = canister.get_build_output() { + let candid_path = match &output.idl { + IdlBuildOutput::File(p) => p.as_os_str(), + }; + + cargo.env( + format!("CANISTER_CANDID_{}", canister.get_name()), + candid_path, + ); + } + } + } + info!( self.logger, "Executing: cargo build --target wasm32-unknown-unknown --release -p {}", package