The CloudFlare blog is awesome. This post was succinct, but super valuable to teams who need to manage versioning, etc. (really there are tons of use cases). I like how they admitted that they were doing things inefficiently and explained what they learned to make their dev lives easier. Thanks again, CloudFlare!
I used to use ldflags heavily for things like that, but nowa days i tend to avoid them - depending on the use case atleast.
Why? Well, many of my projects i don't want to distribute a binary for. I don't want to have to make a whole build process where i build multiple OSs, host it (github upload, etc), and update corresponding documents.
`npm install -g foo` doesn't require that, `go install foo` doesn't require that, so why am i putting myself through a large headache over nothing?
So these days, if i'm writing a Go binary that i intend to mostly use myself, or have other Go developers use, i bake the version/etc information into the files via a build script. For those projects, the Go source is a 100% complete, valid binary. ldflags are still awesome for certain things, but it is really, really nice when your source code is a proper representation of the output result.
Anyway, not bashing ldflags, just talking about my experience :)
As a sysadmin who's embraced Go for a lot of my day to day work, it really bugs me when Go developers do not publish binary releases of their apps.
1) Go makes this easy.
2) One of the advantages of Go is that the program is compiled. Most of the people who want to use your app are not going to be other go developers.
3) Versioning your code is a good practice and if there's a hosted binary release somewhere I can rely on it in my docker/config management process.
Maybe there is a market for "go get" in the cloud where you could paste a repository link and get back binaries for a selected distribution. It should be pretty easy to set up too.
Correction, Go makes compiling and dependencies easy. It does not provide me with a platform for incremental distribution. If i could `go push v1.0 myapp` and you could download my 1.0 binary from Google? Well, i'd do that gladly.
And in general, we all spend as much time as we're willing to on free OSS. Usually it's for problems we solve, for ourselves. Unless you come to my repo and ask me for a binary, i have no information about anyone who is unable to build the binaries - or what their platform/arch might even be.
Do i build for everything, all the time, on the off chance that some random sysadmin might want to use `curl -O myrepo/bin` instead of `go get myrepo/bin`? I choose not to personally - but if the project gets popular, and there is a legitimate need for people to be able to download the bin, i'd gladly manage it. This is just not the default thing for me to do.
> Most of the people who want to use your app are not going to be other go developers.
In my example, you're wrong there. As i said, I'm choosing to do this because i'm targeting go developers. If i was writing a windows GUI app, of course i would release a binary.
> Versioning your code is a good practice and if there's a hosted binary release somewhere I can rely on it in my docker/config management process.
I'm not sure i follow here. I do version my code. Infact, it's even more versioned than if i used ldflags (imo) - because by injecting the version from Git at compile time, my binary has the version, but my code doesn't. You have to have my git repo, to know what version my code is at.
Moreover, with ldflags, you have to download my binary. You can't simply `go get foo/bar` to get the bin.
I understand your frustration, bins are nice - but strictly speaking from an OSS perspective, there is too much resistance in the process of releasing binaries (to my knowledge).
Perhaps there is a tool to automatically push a binary for a specific git tag to Github?
And I suppose you're going to expect the binaries to be packaged for every platform as well. Supporting Various Linux distros, Windows, and OS/X all with various combinations of target processors and word size is a pain that becomes a management nightmare which doesn't have to be endured with a dependable build system.
This is one area that the Go ecosystem leaves me wanting a bit more. Idiomatic Go says that my package should be go-gettable, which AFAIK just uses `go install` command after fetching dependencies.
Is there an idiomatic way to include build options/tasks, while remaining go-gettable?
I guess that's pretty reasonable. Especially coupled with sensible defaults for your variables like "unreleased" in the article. If you're building for a release you're probably a lot more up-to-speed on the needs for a release build anyway.
This will give you just the tag name if the current commit is tagged (useful for version tags), otherwise TAG-N-COMMIT, where N is the number of commits since TAG, and finally append -dev if the tree is dirty.
Almost what I've been doing but I didn't know about the "dirty" option so I had a script I wrote to check if there are uncommitted changes and append a suffix like you do. Now I can get rid of that. Thanks.