tauri-apps / cargo-mobile2

Rust on mobile made easy!
Apache License 2.0
1.5k stars 71 forks source link

cargo-mobile2 does not support cargo workspaces #306

Open neupsh opened 2 months ago

neupsh commented 2 months ago

Describe the bug Cargo mobile does not support cargo workspaces. If I create a mobile project under a workspace, it fails to build as it cannot find built shared libraries under <android project>/target/. When you use workspace, those files are all under the <workspace-dir>/target instead of under each member project inside the workspace.

Steps To Reproduce

  1. Create a workspace directory (mkdir parent) and add a Cargo.toml with the following contents:
    [workspace]
    members = ["dioxus-mobile-test"]
  2. create member project for android: mkdir -p dioxus-mobile-test and cd into it: cd dioxus-mobile-test
  3. Run cargo mobile init in there and use default values, select wry template and let it complete successfully.
  4. Update the Cargo.toml for this project with the following. (Note I ran into linker issue when I tried to just run the default wry template. The following instructions are from dioxus mobile setup)
    [dependencies]
    anyhow = "1.0.56"
    log = "0.4.11"
    dioxus = { version = "0.5", features = ["mobile"] }
    wry = "0.35.0"
    tao = "0.25.0"
  5. Update the src/lib.rs with the following:
    src/lib.rs
  use anyhow::Result;
  use dioxus::prelude::*;

  #[cfg(target_os = "android")]
  fn init_logging() {
      android_logger::init_once(
          android_logger::Config::default()
              .with_max_level(log::LevelFilter::Trace)
      );
  }

  #[cfg(not(target_os = "android"))]
  fn init_logging() {
      env_logger::init();
  }

  #[cfg(any(target_os = "android", target_os = "ios"))]
  fn stop_unwind<F: FnOnce() -> T, T>(f: F) -> T {
      match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) {
          Ok(t) => t,
          Err(err) => {
              eprintln!("attempt to unwind out of `rust` with err: {:?}", err);
              std::process::abort()
          }
      }
  }

  #[no_mangle]
  #[inline(never)]
  #[cfg(any(target_os = "android", target_os = "ios"))]
  pub extern "C" fn start_app() {
      fn _start_app() {
          stop_unwind(|| main().unwrap());
      }

      #[cfg(target_os = "android")]
      {
          tao::android_binding!(
              com_example,
              dioxus_mobile_test,
              WryActivity,
              wry::android_setup, // pass the wry::android_setup function to tao which will invoke when the event loop is created
              _start_app
          );
          wry::android_binding!(com_example, dioxus_mobile_test);
      }
      #[cfg(target_os = "ios")]
      _start_app()
  }

  pub fn main() -> Result<()> {
      init_logging();

      launch(app);

      Ok(())
  }

  fn app() -> Element {
      let mut items = use_signal(|| vec![1, 2, 3]);

      log::debug!("Hello from the app");

      rsx! {
          div {
              h1 { "Hello, Mobile"}
              div { margin_left: "auto", margin_right: "auto", width: "200px", padding: "10px", border: "1px solid black",
                  button {
                      onclick: move|_| {
                          println!("Clicked!");
                          let mut items_mut = items.write();
                          let new_item = items_mut.len() + 1;
                          items_mut.push(new_item);
                          println!("Requested update");
                      },
                      "Add item"
                  }
                  for item in items.read().iter() {
                      div { "- {item}" }
                  }
              }
          }
      }
  }

  1. Run cargo android build - It fails as it expects to link artifacts from parent/dioxus-mobile-test/target/ instead of the parent/target/ directory which is where they are present when using cargo workspace feature.
  Finished dev [unoptimized + debuginfo] target(s) in 1m 09s
  error: Failed to symlink lib
  Library artifact not found at /tmp/parent/dioxus-mobile-test/target/aarch64-linux-android/debug/libdioxus_mobile_test.so. Make sure your Cargo.toml file has a [lib] block with `crate-type = ["staticlib", "cdylib",
"rlib"]`

Expected behavior Android build is successful.

Platform and Versions (please complete the following information): Host OS: archlinux Target OS: android (aarch64-linux-android) Rustc: rustc 1.77.2 (25ef9e3d8 2024-04-09) Ouput of cargo mobile doctor:

[!] cargo-mobile v0.11.1
• Contains commits up to "chore(deps): update to windows-rs 0.56 and other deps (#305)\n"
• Installed at "~/.cargo/.cargo-mobile2"
✗ Failed to get OS info: Failed to find `VERSION` in "/etc/os-release": "NAME=\"Arch Linux\"\nPRETTY_NAME=\"Arch Linux\"\nID=arch\nBUILD_ID=rolling\nANSI_COLOR=\"38;2;23;147;209\"\nHOME_URL=\"https://archlinux.org/
\"\nDOCUMENTATION_URL=\"https://wiki.archlinux.org/\"\nSUPPORT_URL=\"https://bbs.archlinux.org/\"\nBUG_REPORT_URL=\"https://gitlab.archlinux.org/groups/archlinux/-/issues\"\nPRIVACY_POLICY_URL=\"https://
terms.archlinux.org/docs/privacy-policy/\"\nLOGO=archlinux-logo\n"
• rustc v1.77.2 (25ef9e3d8 2024-4-9)

[✔] Android developer tools
• SDK v26.1.1 installed at "~/Android/Sdk"
• NDK v27.0.11718014-beta1 installed at "~/Android/Sdk/ndk/latest"

[✔] Connected devices
• No connected devices were found

Other notes

If you rename the parent Cargo.toml to Cargo.toml.backup and try to build the dioxus-mobile-test project again, it works without error, as it builds the artifacts inside the dioxus-mobile-test/target directory and expects them there.

Would be interested to know if there are any workarounds until this is resolved as well. Thank you.

neupsh commented 2 months ago

Got one workaround: you can pass the target directory of workspace and it builds successfully: CARGO_TARGET_DIR="../target" cargo android build

Perhaps there is a way to add one more else condition here to check for workspace and add workspace target directory if the CARGO_TARGET_DIR is not set. I wonder if there is a way to get the target directory from cargo itself.

kochmaxence commented 1 month ago

Either use CARGO_TARGET_DIR or set target-dir in .cargo/config.toml of your crate.