| >A Go project should only require the Go compiler to build successfully. But they don't. The go compiler doesn't support yarn, npm, protobuf, open-api generators, doc generators like md2man, go-bindata-assetfs, gox and everything you need to complete the code generation done in modern Go applications. So how do you orchestrate this? People use Makefiles, bash scripts, go scripts and everything in between and combined. It gives you a plethora of bewildering and confusing build options which can't be solved with `go build`, and neither with `make` in a straight forward fashion. Add `go get -u ... && go mod vendor` with some `npm install` in the Makefile, along with some overriding and/or ignoring `$GOFLAGS`, `$LDFLAGS` and `$CGO_LDFLAGS` and you got yourself an ecosystem hostile for packaging and compilation. A go project can't use `go build` by itself - but it can't really use the Makefile either as people overengineer the process. But let me stress this. Always use plain Makefiles over any other methods. It's there and has been used for decades for a reason. |
Since I consider it necessary for production executables to explain where they came from, and I therefore embed the Git commit hash and other such information into the executable, it is simply a non-starter to ship my production executables coming from a bare "go build". So I have a shell script-based release process for all my projects that handles all that. In the spirit of Go, it's actually something I've been copy/pasting from project to project, because it always turns out that each one deviates so far from the "base" for its own individual reasons that there's hardly any reason to try to extract out any sort of "base" script. Since my Go projects are generally small-ish (I don't necessarily do "microservices" but I don't do massive monolithic exes, not because I'm super-awesome but just due to the domain I'm working in), make doesn't bring a whole lot of value since the entire final compile for me is under 5 seconds. YMMV. This script also handles tagging in a coherent way and some other basic software engineering maintenance tasks.
I really recommend this approach, and if necessary, doing the work necessary to maintain the ability to quickly do just a "go build". It helps "go test" keep working properly too since the rules for having "go build" work are pretty much the same as having "go test" work.
(In fact, as appropriate, I recommend it out of the context of Go, too. It just isn't always as easy. But prioritize keeping that dev turnaround down. If you're sitting there staring at a build process, use that time to think about how you can cut it down. It isn't just about the raw temporal efficiency... it's about your human brain and the way it stays motivated. The time loss of a one minute build is utterly insignificant next to the slowly-drained motivation and enjoyment the one minute build costs you.)