https://github.com/cafxx/mgo
Build and bundle multiple GOAMD64 variants in a single executable
https://github.com/cafxx/mgo
amd64 build go golang runtime-detection
Last synced: 5 months ago
JSON representation
Build and bundle multiple GOAMD64 variants in a single executable
- Host: GitHub
- URL: https://github.com/cafxx/mgo
- Owner: CAFxX
- License: mit
- Created: 2023-05-08T02:22:02.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2025-08-22T05:37:28.000Z (10 months ago)
- Last Synced: 2025-08-22T07:28:30.236Z (10 months ago)
- Topics: amd64, build, go, golang, runtime-detection
- Language: Go
- Homepage:
- Size: 1.07 MB
- Stars: 13
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# mgo
Build your code for multiple [`GOAMD64` variants][1] and bundle all of them in a
launcher capable of picking at runtime the most appropriate variant for the
processor in use.
This is mostly useful if you want to provide `GOAMD64` variants because of the extra
runtime performance this yields, but you have no control over which processor
microarchitecture the executable will be run on.
## Install
```
go install github.com/CAFxX/mgo@latest
```
## Usage
When building your code just replace `go build [...]` with `mgo [...]`: the resulting
executable will contain 4 variants, each optimized for one of `GOAMD64=v1`, `GOAMD64=v2`,
`GOAMD64=v3` and `GOAMD64=v4`, and a launcher that will pick the appropriate one at
runtime.
At runtime it is possible to override which variant is used by specifying in the
`GOAMD64` environment variable one of the values `v1`, `v2`, `v3`, or `v4`.
To check which version is being executed you can add the `MGODEBUG=log` environment
variable when starting the compiled binary. In this case the launcher will print on
stderr a line similar to the following at startup (in this example, to signal that
the `v3` variant is being used):
```
[mgo] launcher: starting variant GOAMD64=v3
```
Otherwise you can find out which version is being used by resolving the `/proc//exe`
symlink, where `` is the process ID of the launched process:
```
$ PID=...
$ readlink /proc/$PID/exe
/memfd:/usr/bin/foobar [GOAMD64=v3] (deleted)
```
You can extract a specific embedded executable using `MGODEBUG=extract` when starting the
compiled binary, e.g. `MGODEBUG=extract GOAMD64=v3` will dump to stdout the executable for
`GOAMD64=v3` instead of starting it.
## Notes
- `mgo` requires Go >= 1.20
- The resulting executable will be over 4 times as large as a normal build output
- Startup of the resulting executable is going to be a bit slower (tens of milliseconds)
- Currently only `GOOS=linux` and `GOARCH=amd64` are supported, and only in
`buildmode`s that produce executables (not archives, plugins, or libraries)
## TODO
- Further minimize launcher overhead
- Start process with `GOMAXPROCS=1` and `GOGC=off` instead of setting them in `init`
- Avoid the `write` to the memfd (find ways to populate the new process directly from the binary in `RODATA`)
- Embed build metadata of the built `v1` variant into the launcher, so that introspection
tools can use it
- Support `GOARCH=arm` and [`GOARCH=arm64`](https://github.com/golang/go/issues/60905)
## Quick sanity check
```
rm -f mgo* && \
echo stage0 && go build && \
echo stage1 && ./mgo -o mgo1 && sha1sum mgo1 && \
echo stage2 && ./mgo1 -o mgo2 && sha1sum mgo2 && \
echo stage3 && ./mgo2 -o mgo3 && sha1sum mgo3
```
This command should succeed and produce three identical hashes.
[1]: https://go.dev/wiki/MinimumRequirements#amd64