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
x/mobile/cmd/gomobile: multiple packages binding #12245
Comments
There are two distinct problems in the scope of this issue. Although they are relatively connected, we need to address them individually. Problems:
The solution to the first problem is relatively easy. If there are name congestions, reject to generate bindings or name the packages. An example:
It may generate two classes ASensor.java and BSensor.java. We can simply prefix the class name in the most minimal way it will be distinguishable from the other package. Given the fact that, Go import path is unique within the GOPATH, we will eventually find a unique name. If the user is not happy with the auto-assigned names, they should be able to override the namespace themselves. I don't have a strong preference how we should represent the mapping but the information shouldn't be sitting in a separate file. Would you like to carry the discussion to golang-dev@ to ask feedback from a wider audience? |
I will not worry too much about the collision in the package names at this moment. I assume the user has full control over what the package name will be. So, for two sensor packages, the user can name one in sensorA, and another in sensorB. For binding 3rd party packages, the user can wrap them with more meaningful names. I think what I will end up implementing is $ gomobile bind -target=android -pkgpath=com.golang.app a.b.c x.y.z This will creates two classes C.java and Z.java under the same package com.golang.app. All classes will be under the same package path (com.golang.app). If pkgpath is not given, go.c.C and go.z.Z. For objective-c, $ gomobile bind -target=ios -prefix=App a.b.c x.y.z This will create AppC.{h,m} and AppZ.{h.m}, and AppC and AppZ will be used as prefixes of generated functions and types. If -prefix is omitted, GoC and GoZ. |
SGTM |
CL https://golang.org/cl/13969 mentions this issue. |
Introduce options -javapkg and -prefix for gobind command. The following generates java class Testpkg with package name com.example. gobind -lang=java -javapkg=com.example testpkg The following generates objective-c files where function and type names are prefixed with ExampleTestpkg. gobind -lang=objc -prefix=Example testpkg As discussed in golang/go#9660 and golang/go#12245. Gomobile support is not yet implemented. Change-Id: Ib9e39997ce915580a5a2e25643c0c28373f27ee1 Reviewed-on: https://go-review.googlesource.com/13969 Reviewed-by: David Crawshaw <crawshaw@golang.org>
Please reconsider this decision. One of the strengths with the Go ecosystem is that it is incredibly easy to share code. If I build a useful library and every developer will now have to manually write a wrapper the barrier to adoption is significantly higher. For example, I would love to just be able to go get a library to handle networking (checking network type WiFi/3G/etc) or location and just have it work. Having to now write a bunch of code to essentially re-implement the API imposes an unnecessary burden. All of these problems are very easily solved if you just provide a separate command in gomobile to build. Then I can do the following easily:
Now manually create my main
And build
This is consistent with how the go tool works and makes sharing code very easy. Even better, I can use EDIT: I forgot to add, that the above approach has the advantage that it makes incremental builds possible. Having gobind being run automatically by Intellij/Android Studio/XCode is very helpful since it avoids build errors. Right now the framework / aar is rebuilt on every iteration. |
@sridharv Can you explain what the gobind does? Currently it does only code generation (.java, .h, .m, .go) but your mention of incremental builds makes me think the gobind in your proposal does something more than that.
Use of buildmode flag in gomobile build is interesting, and I want to hear more about how it connects the main package and the product of previous gobind+IDE runs. Besides, I want to know how to handle the case when exported functions of pkg1 and pkg2 both depend on some types of pkg3. package pkg1 package pkg2 Our plan was to export only one type for io.Reader in this case, so both Read and Work use the same type. I don't understand what prevents the use of go generate currently. |
Firstly, thank you for responding so quickly. Secondly, I should apologize for saying the problem is "very easily solved". It definitely comes off as glib, which I didn't realize when writing it. In addition I don't think I explained some of the usage scenarios I had in mind properly. Now onto your questions.
That's a very good point. What I described earlier doesn't address this properly since there is room for user error when running ProposalThere are two parts to this. One addresses the problem of manually wrapping libraries and the other, sharing cross platform code. Binding multiple libraries in the face of package conflictsCreate a main file as you suggested in Option 3. Instead of adding comments per package just list all the packages. For packages that have name collisions use the standard Go mechanism of resolving name collisions.
Now run Java:
Objective-C:
This makes it consistent with how go resolves the same package namespace collision issue and keeps things simple as with your earlier decision. Things can be made even simpler if you disallow having any other exported members in the main package so you don't have to worry about how to bind those. Sharing libraries with supporting Java or ObjC codeThis is a separate issue, but it is affected by the choice of prefix/package path. Consider the following scenario. I am writing an SDK app with go code shared between iOS and Android. I want to do the following in my shared go code:
All the above have standardized solutions in Android and iOS respectively. If I wanted a common interface to the above I could write a go library that accepts an interface and have Java/ObjC implement that interface. The go code then calls that interface to get the directory, network state, etc. This is the kind of code that can easily live in a third party library and make development easy for everyone. However, in order to do this, the library author needs to know what Java interface / ObjC protocol to implement in their Java / ObjC supporting code. One solution is to allow package authors to specify their own Java/ObjCpackage prefix.
Packages that force a prefix are disallowed from having third party package references in their exported code. This ensures that the problem you described does not occur. Now I can do the following:
And write go code like so:
The Distributing the supporting code For this, one way would be to ask library authors to use the native code distribution options for their language. They would use Maven for Java and Cocoapods/Carthage for iOS. They just have to be careful not to package the generated binding code. Another would be allow them to place these files in a directory in their go tree. These files are then automatically copied by The I'll put together a small prototype describing the above scenarios so it is clearer. |
I'm placing my answers to your questions about code gen + build here.
The outputs are still source files.
This is an important question and one I didn't address in my comment. I don't think IDEs need to automatically know about the location of the source. The only thing that needs to know is the gomobile tool so that it can pick up these files for the build step. This can be achieved with a command line flag.
It can pick up the location of the files using a command line flag. The IDE will will pick the output of gomobile build in the same way it picks up the output of gomobile bind. The IDE can run
Nothing whatsoever :). However, my understanding is that go generate is intended to be used for pre-build steps such as code generation. Library authors can then commit generated source to their library source tree. It feels like a misuse of go generate to use it to generate a .framework or .aar. Those operations feel like they should be done by go build/gomobile build/Makefile/build.gradle. EDIT: I created #12819 to track my main concerns about code generation in gobind. Most of what I would like can be achieved without separating the two phases. |
I put together a prototype for reading the list of packages from a main file and specifying a package name override. It only works for gobind and is not fully tested right now. Depending on my time constraints I'll port it to gomobile and finish testing tomorrow. |
I currently need this feature for some work I'm doing. I'm happy to implement what was decided earlier on Aug 27 if you haven't had the time to look at it yet. Please let me know if this will be useful to you. |
I had time on Sunday and ended up implementing this (what was decided on Aug 27) for my personal use (using some of the earlier prototype code I'd written). The change is on the following branch: https://github.com/sridharv/mobile/tree/multibind2 The current status:
If this will be useful I'll write up the approach I took, test for iOS and send the CL for review. I'm happy to make any changes needed. If it's not useful I'll use it for my work now and cut over to the official version when it lands :) |
@sridharv Thanks for working on this, and sorry for not responding quickly. I am unfortunately lost where the discussion went; too many things are going on in this issue. Let's limit this issue to be what's mentioned in the title. Multiple package support. By 'what's decided earlier on Aug 27', do you mean my posting on Aug 26? Then, yes, feel free to send a CL for that. I expect the first one should be just changing the current gomobile to support multiple packages. gobind already supports binding of multiple packages. The types should be limited to each package. For supporting types from other packages, there is a separate issue (#12570) so update that one. @crawshaw is now changing the way to extract exported types, so please wait for us to finish https://go-review.googlesource.com/#/c/16913/ and sync. For other stuff you mentioned in your proposals -
Thanks! |
@hyangah Thanks for the quick response! I'll split this into two CLs. One for what you decided on Aug 26 (it shows up as 27 in my timezone) and another for the external types portion. Given how I've implemented this change it might be worth it to wait for https://go-review.googlesource.com/#/c/16913/ for both changes, but I'll defer that decision to the review. Expect this in 2-3 days time (the week has started so I'm restricted to the evenings for this). For the other stuff, I'll send an email to golang-nuts for (2) and we can revisit (1) later as you suggested. |
CL https://golang.org/cl/17010 mentions this issue. |
CL https://golang.org/cl/17023 mentions this issue. |
As discussed in golang/go#12245 Usage: gomobile bind [options] a.b.c x.y.z For java gobind and gomobile will generate go.c.C.java and go.z.Z.java. If -javapkg=com.example is specified they will generate com.example.C.java and com.example.Z.java. Tested on Darwin. Change-Id: Ia8e57c8fec7967131d55de71cc705d9e736ccca0 Reviewed-on: https://go-review.googlesource.com/17023 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
I will send the 2nd CL (iOS) late this week and the 3rd CL (Documentation) next week. I had hoped to do this last week, but had time constraints. |
CL https://golang.org/cl/17475 mentions this issue. |
As discussed in golang/go#12245 Usage: gomobile bind [options] a.b.c x.y.z For ObjC, gomobile bind will generate GoC.{h,m} and GoZ.{h,m}. If -prefix=App is specified it will generate AppC.{h,m} and AppZ.{h,m}. Tested on Darwin. Change-Id: I6af8539a0fb7ed6256f3773efc514eff436014b4 Reviewed-on: https://go-review.googlesource.com/17475 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
I believe this has been working for quite a while now. |
I need to gobind multiple packages for an app.
I considered running gomobile for each package and import multiple .so files, but that will fail due to various reasons:
Option 1:
The command will generate separate java classes for those packages, and gather all asset files under one asset directory. Conflicting package names and asset file names are error.
I was about to implement fix for x/mobile/cmd/gobind: Allow custom java package prefix #9660 and I don't know how it works with multiple packages.
Option 1.a
Option 1.b
Option 2:
Make gomobile take an input file of a certain format that lists all packages for gobind.
Option 3:
Fake main package file - so when gomobile bind sees the 'main' package, it runs gobind on all the imported packages, and process the command that specifies the custom package name for java and prefix for obj-c.
/cc @crawshaw @rakyll
The text was updated successfully, but these errors were encountered: