Skip to content
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

cargo-mobile2 does not support cargo workspaces #306

Open
neupsh opened this issue Apr 28, 2024 · 3 comments
Open

cargo-mobile2 does not support cargo workspaces #306

neupsh opened this issue Apr 28, 2024 · 3 comments

Comments

@neupsh
Copy link

neupsh commented Apr 28, 2024

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"]
  1. create member project for android: mkdir -p dioxus-mobile-test and cd into it: cd dioxus-mobile-test
  2. Run cargo mobile init in there and use default values, select wry template and let it complete successfully.
  3. 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"
  1. 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
Copy link
Author

neupsh commented Apr 30, 2024

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
Copy link

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

@Pandicon
Copy link

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

I have just spent a solid moment trying to make it work with the .cargo/config.toml file. But only the env. var works for me. Does the cargo config file work for you?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants