From e62b5bedae9c604f044aa27d12e42e289446f46e Mon Sep 17 00:00:00 2001 From: axtloss Date: Sun, 21 Apr 2024 15:09:19 +0200 Subject: [PATCH] feat: Migrate plugins to c-shared This migrates plugins from using go/plugin to ebitengine/purego and c-shared. With this change vib and plugins do not need to be built against the exact same api version anymore, which makes the deployment of vib with plugins much easier. --- core/plugins.go | 34 ++++++++++++++++++++++++---------- core/structs.go | 10 +++------- go.mod | 5 +++++ go.sum | 4 ++++ 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/core/plugins.go b/core/plugins.go index 4d6a4fa..fd66d1b 100644 --- a/core/plugins.go +++ b/core/plugins.go @@ -1,9 +1,12 @@ package core import ( + "C" + "encoding/json" "fmt" - "plugin" + "strings" + "github.com/ebitengine/purego" "github.com/vanilla-os/vib/api" ) @@ -19,20 +22,31 @@ func LoadPlugin(name string, module interface{}, recipe *api.Recipe) (string, er if !pluginOpened { fmt.Println("Loading new plugin") buildModule = Plugin{Name: name} - var err error - loadedPlugin, err := plugin.Open(fmt.Sprintf("%s/%s.so", recipe.PluginPath, name)) - if err != nil { - panic(err) - } - buildFunction, err := loadedPlugin.Lookup("BuildModule") + + loadedPlugin, err := purego.Dlopen(fmt.Sprintf("%s/%s.so", recipe.PluginPath, name), purego.RTLD_NOW|purego.RTLD_GLOBAL) if err != nil { panic(err) } - buildModule.BuildFunc = buildFunction.(func(interface{}, *api.Recipe) (string, error)) + var buildFunction func(*C.char, *C.char) string + purego.RegisterLibFunc(&buildFunction, loadedPlugin, "BuildModule") + buildModule.BuildFunc = buildFunction buildModule.LoadedPlugin = loadedPlugin - openedPlugins[name] = buildModule } fmt.Printf("Using plugin: %s\n", buildModule.Name) - return buildModule.BuildFunc(module, recipe) + moduleJson, err := json.Marshal(module) + if err != nil { + return "", err + } + recipeJson, err := json.Marshal(recipe) + if err != nil { + return "", err + } + + res := buildModule.BuildFunc(C.CString(string(moduleJson)), C.CString(string(recipeJson))) + if strings.HasPrefix(res, "ERROR:") { + return "", fmt.Errorf("%s", strings.Replace(res, "ERROR: ", "", 1)) + } else { + return res, nil + } } diff --git a/core/structs.go b/core/structs.go index 4edbd10..10f1f09 100644 --- a/core/structs.go +++ b/core/structs.go @@ -1,10 +1,6 @@ package core -import ( - "plugin" - - "github.com/vanilla-os/vib/api" -) +import "C" type Module struct { Name string `json:"name"` @@ -26,6 +22,6 @@ type ModuleCommand struct { type Plugin struct { Name string - BuildFunc func(interface{}, *api.Recipe) (string, error) - LoadedPlugin *plugin.Plugin + BuildFunc func(*C.char, *C.char) string + LoadedPlugin uintptr } diff --git a/go.mod b/go.mod index 39a5e9c..4595a35 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,11 @@ require github.com/spf13/cobra v1.7.0 require github.com/mitchellh/mapstructure v1.5.0 +require ( + github.com/ebitengine/purego v0.7.1 // indirect + golang.org/x/sys v0.7.0 // indirect +) + require ( github.com/google/uuid v1.3.0 github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index 3ac7eea..55decbd 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA= +github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -14,6 +16,8 @@ github.com/vanilla-os/vib/api v0.0.0-20240212085722-f163a19e5a63 h1:WwnKmkEFT0nQ github.com/vanilla-os/vib/api v0.0.0-20240212085722-f163a19e5a63/go.mod h1:vjJzDfFxfFHN5O2hcMwGM9De3+H9gGa00Pr3Um6EmCA= github.com/vanilla-os/vib/api v0.0.0-20240331150207-852011e4d96f h1:sRPpotRlyj3Qx4ftt5oYf7JQuIYTQwwPq93xomWaIKQ= github.com/vanilla-os/vib/api v0.0.0-20240331150207-852011e4d96f/go.mod h1:vjJzDfFxfFHN5O2hcMwGM9De3+H9gGa00Pr3Um6EmCA= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=