golang/go

x/mobile: support multiple independent bindings in the same app

yancheng199287 opened this issue · 23 comments

Please answer these questions before submitting your issue. Thanks!

  1. What version of Go are you using (go version)?
    1.5
  2. What operating system and processor architecture are you using (go env)?
    windows amd64
  3. What did you do?
    I make arr module by use gomobile bind common, but I have two different package hello and halou,so I do this:

as follow
gomobile bind -target=android golang.org/x/mobile/example/bind/hello

gomobile bind -target=android golang.org/x/mobile/example/bind/halou

I get two aar module,then import them by android studio ,

when I build apk,happen erro messsage

Error:Error converting bytecode to dex:
Cause: com.android.dex.DexException: Multiple dex files define Lgo/LoadJNI;
:app:transformClassesWithDexForDebug FAILED
Error:Execution failed for task ':app:transformClassesWithDexForDebug'.

com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'D:\jdk\bin\java.exe'' finished with non-zero exit value 2

I know resason that two arr include two jar file,but them have same LoadJNI.class and Seq.class,

so conflict!

I want to know that how to resolve it by good way?

when I delete one of them arr module,I build apk successful!

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':app:transformNative_libsWithMergeJniLibsForDebug'.

    com.android.build.api.transform.TransformException: com.android.builder.packaging.DuplicateFileException: Duplicate files copied in APK lib/x86/libgojni.so
    File1: D:\golang\gopath\src\golang.org\x\mobile\example\bind\android\app\build\intermediates\exploded-aar\android\mygo\unspecified\jni
    File2: D:\golang\gopath\src\golang.org\x\mobile\example\bind\android\app\build\intermediates\exploded-aar\android\hello\unspecified\jni

can not use more aar !!!!

oh my god,very boring

got the identical thing today.

enabling MultDex is possible apparently as fix in Android Studio. But dont knwo too much.
I just removed one of the Dependencies and it got rid of the error.

I wonder if devs really need more than one golang dependency in their Android apps ?

Hello, I got the same issue using two go packages that translates into two android modules, but the go directory in the .aar files are identical. Using multidex didn't cut it for me, because I ended up with following error:

Error:Execution failed for task ':app:transformClassesWithJarMergingForDebug'.
> com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: go/LoadJNI.class

I tried to exclude the LoadJNI.class from one of the dependencies using gradle without luck :/

Any ideas?

Is it not a possibility to merge them to one go package and deal with only one .aar?

Gomobile doesn't support multiple independent instances in the same app. As @hyangah points out, list multiple packages to gomobile bind or in the "pkg" setting for the gobind gradle plugin. Gomobile will then build one set of bindings covering all the packages list.

This would be nice. Not a great developer experience for Java developers to have to learn Go building tools just 2 use more than 1 go library in their apps. I'd expect to see meteoric growth in the use of Go on Android if this is fixed.

Is this going to be fixed anytime soon? This is a really big blocker as the number of go-mobile libraries is growing and it is going to create a lot of compatibility issues in the feature.

I don't have plans to work on it, sorry.

I got the same problem on Android(The two aar supported by different team).

First, I think it is just the problem of .so conflict. So, I modify the source of go-mobile and changed the name of .so just like "libgojniX.so".

Then I got another problem: "duplicate class go.Seq".

Continue to modify the source of go-mobile, change the default package "go" to "go.xxx". Then I got the class go.xxx.Seq.

Import the new aar to the project, It was compiled successfully.

But, when I run the app. It throws some go-runtime error:

2018-10-26 13:44:12.902 26549-0/? E/Go: fatal error: runtime: cannot reserve arena virtual address space
2018-10-26 13:44:12.902 26549-0/? E/Go: runtime: panic before malloc heap initialized
2018-10-26 13:44:12.902 26549-26570/? E/GoLog: fatal error: runtime: cannot reserve arena virtual address space
2018-10-26 13:44:12.902 26549-26570/? E/GoLog: runtime: panic before malloc heap initialized
2018-10-26 13:44:12.904 26549-0/? E/Go: runtime stack:
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: runtime stack:
2018-10-26 13:44:12.904 26549-0/? E/Go: runtime.throw(0x71bbc3a33c, 0x33)
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: runtime.throw(0x71bbc3a33c, 0x33)
2018-10-26 13:44:12.904 26549-0/? E/Go: 	/usr/local/go/src/runtime/panic.go:605 +0x70 fp=0x71bb8c6390 sp=0x71bb8c6370 pc=0x71bba2fd40
2018-10-26 13:44:12.904 26549-0/? E/Go: runtime.mallocinit()
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: 	/usr/local/go/src/runtime/panic.go:605 +0x70 fp=0x71bb8c6390 sp=0x71bb8c6370 pc=0x71bba2fd40
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: runtime.mallocinit()
2018-10-26 13:44:12.904 26549-0/? E/Go: 	/usr/local/go/src/runtime/malloc.go:360 +0x368 fp=0x71bb8c6430 sp=0x71bb8c6390 pc=0x71bba16248
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: 	/usr/local/go/src/runtime/malloc.go:360 +0x368 fp=0x71bb8c6430 sp=0x71bb8c6390 pc=0x71bba16248
2018-10-26 13:44:12.904 26549-0/? E/Go: runtime.schedinit()
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: runtime.schedinit()
2018-10-26 13:44:12.904 26549-0/? E/Go: 	/usr/local/go/src/runtime/proc.go:481 +0x38 fp=0x71bb8c6470 sp=0x71bb8c6430 pc=0x71bba322a8
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: 	/usr/local/go/src/runtime/proc.go:481 +0x38 fp=0x71bb8c6470 sp=0x71bb8c6430 pc=0x71bba322a8
2018-10-26 13:44:12.904 26549-0/? E/Go: runtime.rt0_go(0x0, 0x71bb8c64e0, 0x7255aa63c0, 0x7259662548, 0x0, 0x72596625e0, 0x72596625f0, 0x0, 0x0, 0x71bc0114f0, ...)
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: runtime.rt0_go(0x0, 0x71bb8c64e0, 0x7255aa63c0, 0x7259662548, 0x0, 0x72596625e0, 0x72596625f0, 0x0, 0x0, 0x71bc0114f0, ...)
2018-10-26 13:44:12.904 26549-0/? E/Go: 	/usr/local/go/src/runtime/asm_arm64.s:70 +0xbc fp=0x71bb8c64a0 sp=0x71bb8c6470 pc=0x71bba56b7c
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: 	/usr/local/go/src/runtime/asm_arm64.s:70 +0xbc fp=0x71bb8c64a0 sp=0x71bb8c6470 pc=0x71bba56b7c

Is there any way to decouple them(go-runtime&logic.so)?
I don't know how to fix it. Need Help!

There is no easy fix for two instances of the Go runtime in one process. Even if you could get it to work it would be wasteful.

Why not build the two projects together into one aar?

I got the same problem on Android(The two aar supported by different team).

First, I think it is just the problem of .so conflict. So, I modify the source of go-mobile and changed the name of .so just like "libgojniX.so".

Then I got another problem: "duplicate class go.Seq".

Continue to modify the source of go-mobile, change the default package "go" to "go.xxx". Then I got the class go.xxx.Seq.

Import the new aar to the project, It was compiled successfully.

But, when I run the app. It throws some go-runtime error:

2018-10-26 13:44:12.902 26549-0/? E/Go: fatal error: runtime: cannot reserve arena virtual address space
2018-10-26 13:44:12.902 26549-0/? E/Go: runtime: panic before malloc heap initialized
2018-10-26 13:44:12.902 26549-26570/? E/GoLog: fatal error: runtime: cannot reserve arena virtual address space
2018-10-26 13:44:12.902 26549-26570/? E/GoLog: runtime: panic before malloc heap initialized
2018-10-26 13:44:12.904 26549-0/? E/Go: runtime stack:
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: runtime stack:
2018-10-26 13:44:12.904 26549-0/? E/Go: runtime.throw(0x71bbc3a33c, 0x33)
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: runtime.throw(0x71bbc3a33c, 0x33)
2018-10-26 13:44:12.904 26549-0/? E/Go: 	/usr/local/go/src/runtime/panic.go:605 +0x70 fp=0x71bb8c6390 sp=0x71bb8c6370 pc=0x71bba2fd40
2018-10-26 13:44:12.904 26549-0/? E/Go: runtime.mallocinit()
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: 	/usr/local/go/src/runtime/panic.go:605 +0x70 fp=0x71bb8c6390 sp=0x71bb8c6370 pc=0x71bba2fd40
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: runtime.mallocinit()
2018-10-26 13:44:12.904 26549-0/? E/Go: 	/usr/local/go/src/runtime/malloc.go:360 +0x368 fp=0x71bb8c6430 sp=0x71bb8c6390 pc=0x71bba16248
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: 	/usr/local/go/src/runtime/malloc.go:360 +0x368 fp=0x71bb8c6430 sp=0x71bb8c6390 pc=0x71bba16248
2018-10-26 13:44:12.904 26549-0/? E/Go: runtime.schedinit()
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: runtime.schedinit()
2018-10-26 13:44:12.904 26549-0/? E/Go: 	/usr/local/go/src/runtime/proc.go:481 +0x38 fp=0x71bb8c6470 sp=0x71bb8c6430 pc=0x71bba322a8
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: 	/usr/local/go/src/runtime/proc.go:481 +0x38 fp=0x71bb8c6470 sp=0x71bb8c6430 pc=0x71bba322a8
2018-10-26 13:44:12.904 26549-0/? E/Go: runtime.rt0_go(0x0, 0x71bb8c64e0, 0x7255aa63c0, 0x7259662548, 0x0, 0x72596625e0, 0x72596625f0, 0x0, 0x0, 0x71bc0114f0, ...)
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: runtime.rt0_go(0x0, 0x71bb8c64e0, 0x7255aa63c0, 0x7259662548, 0x0, 0x72596625e0, 0x72596625f0, 0x0, 0x0, 0x71bc0114f0, ...)
2018-10-26 13:44:12.904 26549-0/? E/Go: 	/usr/local/go/src/runtime/asm_arm64.s:70 +0xbc fp=0x71bb8c64a0 sp=0x71bb8c6470 pc=0x71bba56b7c
2018-10-26 13:44:12.904 26549-26570/? E/GoLog: 	/usr/local/go/src/runtime/asm_arm64.s:70 +0xbc fp=0x71bb8c64a0 sp=0x71bb8c6470 pc=0x71bba56b7c

Is there any way to decouple them(go-runtime&logic.so)?
I don't know how to fix it. Need Help!

Could u please give me more details about modifying the so name and the default package name "go", Since I mainly work on Android, I'm confusing about which file to change, and how to let it take effect
BTW, I'm trying to split the two gomobile into two processes in android, Don't know whether there any experience or whether this is a solution solving this problem

There is no easy fix for two instances of the Go runtime in one process. Even if you could get it to work it would be wasteful.

Why not build the two projects together into one aar?

In the "real world", Sometimes we need to work with multiple teams(which may not open sourced), And there is no easy way they sharing code or the procedure, So I think this puzzle may not be such meanless, And I just trying to hack it

There is no easy fix for two instances of the Go runtime in one process. Even if you could get it to work it would be wasteful.

Why not build the two projects together into one aar?

@eliasnaur
I've tried steps like @nobeginning ,Changed names like libgojniX.so and package name, Make it out out an aar that could coexist with past libgojni.so and xx.jar under same android project, And beyond my expectation,I didn't get issues like @nobeginning, it just run well under one process(I just write a demo for{sleep(),print}) function called by new Thread in Android, And make sure it just loaded with /proc/xx/maps), And Also When I split it into a process(in android it's possible with set process under manifest). It works too.

So The question is, Is there anything improved since this talk made this possible? (Maybe my logic too simple, But at least one process load two libgojni.so(maybe two go runtime?) and it worked.
And Since it worked, Is there anything else I should concern about for long term things or different system versions? (maybe it just worked for a while or under my arm64 Android 8, for long term or another system it may cause some issues under android?) I'm not familiar with low level of gomobilie, maybe there some key principle behind "There is no easy fix for two instances of the Go runtime in one process"?

One fundamental restriction to multiple independent Go runtimes on Android: there is only one TLS_SLOT_APP (on Android 10+). See https://golang.org/cl/170117/ and https://golang.org/issue/29674.

Have you seen -buildmode=shared and -linkshared? Buildmode=shared builds your non-main packages as Go libraries that you can link together with a main package with -linkshared. Note that buildmode=shared is not the same as buildmode=c-shared.

As far as I know, -buildmode=shared works fine on Linux, so making it run on Android should be possible. However, I haven't heard about anyone attempting it, so you're probably in for some work on the Go toolchain. In particular, the TLS issue I mentioned above likely affects -buildmode=shared.

Another approach that could work is -buildmode=plugin, which is about loading Go code at runtime. I know even less about that.

just FYI, on the apple side, using two gomobile .xcframework fails linking due to duplicate symbols too

for context: we want to distribute apple-targeted libraries (via cocoapods) with gomobile .xcframeworks and until this is supported we would need to produce monolithic libraries that contain and expose every go-side functionalities the users native code needs to access I think

So, does some one found at least somehow reliable solution except for merging two libs together? Maybe something with those build modes?

This issue also makes publishing Flutter packages that depend on Gomobile libraries somewhat pointless, as you aren't able to import more than one Flutter plugin that depends on Gomobile. And as those are different packages (possibly packaged by different maintainers), it doesn't seem that the "combine them into one AAR" approach would work.

I'm having the same problem and it looks like I have to give up one of the go libraries, which will cause my workload to become too high! Hope to solve this problem soon!!

I'm having the same problem in 2024! any idea how to fix this issue?

keep an eye on it