You can use the builder to create a cross-platform Go module that can be used as a dependency in another application. You import the module like any other module.
However, when you build your application, you must use: go build --ldflags="-checklinkname=0" -tags shrinkpkg$(go env GOVERSION) .
You can also use: gorun as a substitute for go run.
NOTE: DO NOT APPLY linker flags: -s -w. (This also means running go test --ldflags="-checklinkname=0" -c -o <output dir> separately)
You will need to test your module by building a consumer application. When you run the consumer appplication, most likely it will spit out errors that look like this:
Load error: unresolve external:github.com/bytedance/gopkg/lang/fastrand.Intn
You need to then create a regtypes.<namespace> file in each directory containing a package where the error is relevant.
This file is yaml formatted and will record the import paths and the functions or objects that golinker complains about:
regtypes.plugin_builder file:
runtime:
- runtime.GC
bufio:
- bufio.ScanLines
- (&bufio.Scanner{}).Scan
github.com/bytedance/gopkg/lang/fastrand:
- fastrand.Intn
context:
- new(context.Context)
alias runtime:
- (&alias.writeBarrier{})Keep doing this process until you discover the full list of "missing" symbols. Keep adding them to the file.
Finally when you've discovered all the "missing" symbols, rebuild your package from scratch (but now with the regtypes file present).
The regtypes file will pre-register symboles that golinker could not resolve.
You will need to do a final manual fix-up of your code comments. It will mostly include removing newlines between your comment blocks and their associated functions/methods/variables etc.
| FLAG | DETAILS | EXAMPLE | NOTES |
|---|---|---|---|
go |
Go versions to build for | --go 1.22-1.24.1 | All go versions that you want to build against must be already installed on your machine. |
X |
Preprocessor variable replacements | Works for var and const. (strings and ints) |
|
os |
Set GOOS environment variable | --os darwin,windows,linux | |
GOOS |
Set GOOS environment variable | ||
arch |
Set GOARCH environment variable | --arch amd64,arm64 | |
GOARCH |
Set GOARCH environment variable | ||
tags |
Pass build tags through to compiler | --tags tag1,tag2,tag3 | |
quotes |
Enable double-quote mode for -X flags | ||
i |
Automatically install go versions not found on machine | -i | |
work |
Print temporary work directory and do not delete | Sets directory to store temporary generated build files | |
explain |
Print step-by-step operations being performed | ||
o |
Set output directory | Needs to be non-existent. | |
test |
Run black-box tests (TODO) | ||
wasm |
Embed wasm_exec.js file into module (TODO) | ||
L |
Inject LICENSE, LICENSE.md or LICENSE.txt into generated code | ||
copyright |
Copyright header to inject into generated code | ||
keep |
Which files to keep? (list of glob patterns) | Copies additional non-go files. See Match | |
namespace |
New suffix to ensure regtypes and ignore files, generated variables and methods don't clash | default: plugin_builder This also changes these files: ignore.<namespace> and regtypes.<namespace> |
|
message |
A message to print to os.Stdout when a module gets loaded | --message 'red::Do not use in PRODUCTION' | Gets displayed when module gets initialized by consumer application. |
modname |
Change module name | Changes the module name. eg. github.com/romance-dev/word-gen => github.com/romance-dev/try-word-gen |
Sometimes you may not want packages (eg. sub-packages) converted to plugins, but you still want them included in the final module.
In the directory of the sub-package, include a file: ignore.<namespace> (e.g ignore.plugin_builder). Inside the file, you can also newline-list glob patterns to define arbitrary files that should be considered "part of" the package. This is usually files that are embedded.
This is not production ready due to various critical bugs in downstream dependencies.
Exported Generics functions have issues with type assertions and type switches.
The plugin always includes exported variables that point to the real variable in the underlying package. This means you must dereference them using (*) when you set them and/or access them.
You also need to call <package>.INITIALIZE_VARS_DO_NOT_CALL_INSIDE_INIT() outside of an func init() (eg. from main).