QUESTION:
I'm not a Go expert, so I may be doing this in a way that is not the ideal approach for Go. Essentially, I have a main application that needs to be able to have plugins written for it. The plugins all adhere to a given format and are built with go build -buildmode=plugin
. I don't want the end user to need to recompile the main application every time. Ideally, you should be able to drag and drop it to a new computer without issue.
To pass information between the plugins and the application, I have a third package defined called "common" that I treat similar to a C-header file. It only defines interfaces and a few integer constants that both can use. The application generates types that adhere to the interface and can pass them to the plugins to use.
When I compile, it seems to work fine, and the application can load the plugins using plugin.Open
. The catch comes when trying to move the location of the common
package. I built the original application in a local directory and I have a script that installs the application and the copies the common
package into the GOPATH
so that it can be found. Now, when I try to create plugins and compile them referencing the global copy of the common
package, I can't load them in the main application because it sees the two occurrences of the package as being different versions.
My understanding is that to determine package version, a hash is made of all the Go files in the package at compile time. Is this hash including the location on the server where the package was found as well?
I know for a fact that the actual versions of the packages are identical. The only different is that I did cp -r src/myapp /usr/local/go/src
. Is there a better way to accomplish this than my approach that still allows the user to move the main application around to different machines and not need to recompile it?
Further explanation:
Here is my directory structure
./
|-- main.go
|-- src/myapp/common
| |-- Common.go
|-- install.sh
Once I compile this into myapp
, I copy src/myapp/common
into the GOPATH
and then build plugins with go build -buildmode=plugin
against that package. When loading those plugins from myapp
, it sees the two versions of myapp/common
as being different, although the only difference is location on the server.
ANSWER:
Have you tried instead keeping the path of the common package stable? You should probably have that in its own repo (so that both projects can refer to it), or keep it in your app repo, but allow plugins to link to it there.
So for example say your project lives at:
github.com/brianwest/myapp
you could make the import path (for both app and plugins):
github.com/brianwest/myapp/src/common
OR
github.com/brianwest/common
and keep it stable across the app and plugins, then it should just work and you won't need the script to copy it into gopath, or if you do it can put it at src/github.com/brianwest/common and use that path in both plugins and your app.
COMMENTS:
Ok, so the correct approach would be to separate the common package into a separate project altogether, and then have both reference that independent project? That makes sense. If it is later moved to a new machine, will it still work correctly with the main app being compiled on the original machine? – Brian Nov 28 '17 at 13:46
-
Yes the idea is to keep the common package at a stable import url - go will see different urls as different packages. So fix that and it should work fine. If a separate project you could call it plugins or something like that and make it support functions for plugins, along with a readme which explains how to build one. – Kenny Grant Nov 28 '17 at 16:05
-
Gotcha! I tried that, and it appears to solve my issue. Much appreciated. – Brian Nov 28