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

Running cargo test fails out-of-the-box on an M1 Mac #473

Closed
rfk opened this issue Jun 3, 2021 · 9 comments
Closed

Running cargo test fails out-of-the-box on an M1 Mac #473

rfk opened this issue Jun 3, 2021 · 9 comments
Assignees

Comments

@rfk
Copy link
Collaborator

rfk commented Jun 3, 2021

Some notes from a discussion earlier today with @skhamis; please add your own notes here as appropriate.

On a checkout of uniffi-rs on an M1 Mac, cargo test fails when running the Kotlin bindings tests. IIUC the issue we ran into was:

  • On the M1, cargo builds native libraries as arm64 by default.
  • The JVM installed on the M1 was an x86_64 binary, meaning that Java programs would run in virtualized mode.
  • Under such circumstances, JNA (rightfully!) wants to load x64_64 dylibs, and is not able to load arm64 dylibs. (ref Platform.RESOURCE_PREFIX on Darwin x64 and M1 java-native-access/jna#1313 for a bit of discussion about this in JNA).
  • So when we try to run the UniFFI kotlin bindings tests we:
    • cargo build the target crate for the native host, making an arm64 dylib.
    • Run java to execute the Kotlin tests, which launches as a virtualized executable.
    • The tests try to load the dylib and error out, complaining that it is the wrong architecture.
      • (Which is misleading from a debugging point of view, because it's java that is the "wrong" architecture)

Two things we could try to solve this:

  • Figure out how to get an M1 native Java environment, and document it in our README.
  • Figure out how to make cargo build x86_64 binaries for use in these tests.

┆Issue is synchronized with this Jira Task
┆Issue Number: UNIFFI-64

@skhamis
Copy link
Contributor

skhamis commented Jun 3, 2021

This is an excellent write-up! I think you covered everything here. The only thing I'll add is the actual error log for verbosity:

java.lang.UnsatisfiedLinkError: dlopen(/Users/skhamis/moz/uniffi-rs/target/debug/libuniffi_coverall.dylib, 9): no suitable image found.  Did find:
	/Users/skhamis/moz/uniffi-rs/target/debug/libuniffi_coverall.dylib: mach-o, but wrong architecture
	/Users/skhamis/moz/uniffi-rs/target/debug/libuniffi_coverall.dylib: mach-o, but wrong architecture
	at com.sun.jna.Native.open(Native Method)
	at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:277)
	at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:461)
	at com.sun.jna.Library$Handler.<init>(Library.java:192)
	at com.sun.jna.Native.load(Native.java:596)
	at com.sun.jna.Native.load(Native.java:570)
	at uniffi.coverall._UniFFILib$Companion$INSTANCE$2.invoke(coverall.kt:1293)
	at uniffi.coverall._UniFFILib$Companion$INSTANCE$2.invoke(coverall.kt:750)
	at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
	at uniffi.coverall._UniFFILib$Companion.getINSTANCE$main(coverall.kt:750)
	at uniffi.coverall.CoverallKt.createSomeDict(coverall.kt:1094)
	at Test_coverall.<init>(test_coverall.kts:12)
test uniffi_foreign_language_testcase_test_coverall_kts ... FAILED

failures:

---- uniffi_foreign_language_testcase_test_coverall_kts stdout ----
Error: running `kotlinc` failed
thread 'uniffi_foreign_language_testcase_test_coverall_kts' panicked at 'assertion failed: `(left == right)`
  left: `1`,
 right: `0`: the test returned a termination value with a non-zero status code (1) which indicates a failure', /rustc/9bc8c42bb2f19e745a63f3445f1ac248fb015e53/library/test/src/lib.rs:193:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    uniffi_foreign_language_testcase_test_coverall_kts

test result: FAILED. 2 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 32.53s

and running a file on the lib that is erroring out nets:
/Users/skhamis/moz/uniffi-rs/target/debug/libuniffi_coverall.dylib: Mach-O 64-bit dynamically linked shared library arm64

@skhamis
Copy link
Contributor

skhamis commented Jun 8, 2021

So wanted to update on this as I had time to finally fix it! The real issue was indeed having incompatible Java and JNA versions which is "fixed" by installing an arm64 java.

  1. I ended up settling on using JEnv which is a really nice way to manage multiple JVMs
  2. I installed Azul JDK (offers native arm64 JVM) in addition to my existing OpenJDK (the original x86_64)
  3. I specifically switched to use JVM arm64 for the uniffi-rs project
    All tests pass!

While this definitely over-complicates things for M1 users. I actually believe this is the way to go for the near future as it allows flexibility for arm64 and x86_64 when one or the other is needed for simple compiling. I do think this was in part contributing to "operator error" as I had x86_64 JVM but JNA auto-detects and "forces" arm64 since it detects that platform.

Don't necessarily know what the "right" way to fix this would be other than possibly detecting what JVM they have and generating the libs based on that but this seems really specific to Apple silicon. Possibly a doc that FAQ with what is happening? Definitely open to any ideas!

@rfk
Copy link
Collaborator Author

rfk commented Aug 3, 2021

@badboy this could be an interesting one for you to take a look at as well, and in fact I'm curious if you encountered this problem yourself.

@badboy badboy self-assigned this Aug 3, 2021
@badboy
Copy link
Member

badboy commented Aug 3, 2021

Indeed, I'll take a look here

@badboy
Copy link
Member

badboy commented Aug 3, 2021

It seems in the meantime the offered JDK is native and thus all things already work?

Native run:

$ which java
/opt/homebrew/opt/openjdk@11/bin/java

$ file $(which java)
/opt/homebrew/opt/openjdk@11/bin/java: Mach-O 64-bit executable arm64

$ java -version
openjdk version "11.0.10" 2021-01-19
OpenJDK Runtime Environment (build 11.0.10+9)
OpenJDK 64-Bit Server VM (build 11.0.10+9, mixed mode)

$ curl -o jna.jar https://repo1.maven.org/maven2/net/java/dev/jna/jna/5.8.0/jna-5.8.0.jar
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1689k  100 1689k    0     0  8445k      0 --:--:-- --:--:-- --:--:-- 8445k

$ CLASSPATH=$(pwd)/jna.jar cargo test -- uniffi_foreign_language_testcase_test_coverall_kt
    Finished test [unoptimized + debuginfo] target(s) in 0.07s
     Running unittests (target/debug/deps/cdylib_dependency-2e11dfb46e5deee9)

[...]

$ echo $?
0

Rosetta 2 run (x86_64 emulation):

$ arch -x86_64 zsh

$ which java
/usr/local/Cellar/openjdk@8/1.8.0+282/bin/java

$ file $(which java)
/usr/local/Cellar/openjdk@8/1.8.0+282/bin/java: Mach-O 64-bit executable x86_64

$ java -version
openjdk version "1.8.0_282"
OpenJDK Runtime Environment (build 1.8.0_282-bre_2021_01_20_16_06-b00)
OpenJDK 64-Bit Server VM (build 25.282-b00, mixed mode)

$ CLASSPATH=$(pwd)/jna.jar cargo test -- uniffi_foreign_language_testcase_test_coverall_kt
    Finished test [unoptimized + debuginfo] target(s) in 0.07s
     Running unittests (target/debug/deps/cdylib_dependency-2e11dfb46e5deee9)

[...]

$ echo $?
0

@badboy
Copy link
Member

badboy commented Aug 3, 2021

cc @rfk -- IMO we can close this now. wdyt?

@rfk
Copy link
Collaborator Author

rfk commented Aug 4, 2021

@skhamis, WDYT? ^

@skhamis
Copy link
Contributor

skhamis commented Aug 4, 2021

I think we can safely close this, seems to be a mis-configure of binaries JDK/JNA and anyone running into this issue will be able to work thru their potential JNA issues.

@rfk
Copy link
Collaborator Author

rfk commented Aug 4, 2021

Thanks for digging in!

@rfk rfk closed this as completed Aug 4, 2021
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