Open rive-n opened 4 months ago
I'm not sure how to do exactly what you want -- build a stand-alone program that includes arbitrary Go modules -- but I do have some advice. It boils down to "figure out what they did with the standard library and then do that."
First, build a non-stand-alone Go program that creates a Yaegi interpreter and uses the package successfully.
This would probably look something like this:
yaegi extract
on the external package to build a symbol table for all exported symbols in the package. This generated code updates a Symbols
variable assumed to already exist in whatever package the file is in. It looks something like this:// Code generated by 'yaegi extract github.com/google/uuid'. DO NOT EDIT.
package _test
import (
"github.com/google/uuid"
"reflect"
)
func init() {
Symbols["github.com/google/uuid/uuid"] = map[string]reflect.Value{
// function, constant and variable definitions
"ClockSequence": reflect.ValueOf(uuid.ClockSequence),
// ...
Symbols
variable of type interp.Exports
in that file's package. (Depending on where you ran yaegi extract
, you may need to manually update the package
declaration in the generated file. By default, extract
specifies a packaged based on your $PWD when you run yaegi extract
.)import "github.com/you/your_app/path/to/your_package"
i := interp.New(...)
Use
the Symbols
generated by extract
, e.g. i.Use(your_package.Symbols)
ImportUsed()
, e.g. i.ImportUsed()
i.Eval("import \"github.com/google/uuid\"")
And that should get you an interpreter that can use uuid
variable/functions/types.
Arranging for all that to happen in a stand-alone executable is up to you.
The following program
sample.go
triggers an unexpected resulthttps://github.com/traefik/yaegi/issues/671 ->
It's also possible to re-build an interpreter containing a pre-compiled library and its wrapper (generated by goexports), so the package can be imported without the overhead of interpretation, as it is done for the standard library packages in yaegi.
I've added external library into runtime using
"import"
, generatedextract
file foryaegi
, but, TL;DR it won't find the package which is already imported inside the runtime:./yaegi extract "github.com/google/uuid"
yaegi/cmd/yaegi.go
:or
func main() {} ... _ = uuid.New() ...
go build ./cmd/yaegi
/ # ./ya
Got
Inside mounted namespace without "uuid" package:
Yaegi Version
Additional Notes
Maybe I am just confused by the doc itself and there is no
legit
way to hook something from the runtime itself or maybe I am just wrong with the implementation, but still it's not clear how can you import something external.Basically, what I am trying to achieve is: Build an interpreter with the package
X
in it's runtime and after, use the binary with the packageX
inside it without packageX
being installed on the system (some sort of from memory loading)