Saturday, March 21, 2015

Go development on OpenBSD

is perfectly fine. In this post I'll go over the tools I use, their setup and some pitfalls that you might encounter while first dipping your toes in lang/go on OpenBSD. I will also mention a new go related port I just submitted for review & inclusion :)




My typical golang setup on Linux is nothing fancy. Sublime Text & goconvey pretty much sums it up completely. Go is also present in pretty much every Linux distro out there or trivial to compile on your own. How does OpenBSD stack up?

If you are running a current snapshot (or 5.7 when it comes out) then you have go 1.4.1 available as a pre-built package from ports. The first step you need to take is to install it on your system:

pkg_add go

The first trap you might fall into is not raising your system limits. Try to run your newly installed go package. A simple `go version` will do.

$ go version
runtime: panic before malloc heap initialized
fatal error: runtime: cannot reserve arena virtual address space

runtime stack:
runtime.throw(0x854ce92)
        /usr/local/go/src/runtime/panic.go:491 +0x83 fp=0xcfbcb6cc sp=0xcfbcb6b4
runtime.mallocinit()
        /usr/local/go/src/runtime/malloc.c:223 +0xe9 fp=0xcfbcb708 sp=0xcfbcb6cc
runtime.schedinit()
        /usr/local/go/src/runtime/proc.c:137 +0x34 fp=0xcfbcb720 sp=0xcfbcb708
runtime.rt0_go(0xcfbcb7b4, 0xfff, 0x85470a0, 0x0, 0x0, 0x0, 0x57945d2b, 0xcfbcb76c, 0xcfbcb7b0, 0xcfbcb76c, ...)
        /usr/local/go/src/runtime/asm_386.s:100 +0xed fp=0xcfbcb724 sp=0xcfbcb720
$
Oh my! Is it broken? Nope. OpenBSD is quite strict by default and applications are limited in the amount of RAM, file handles, cpu time etc. they can use. If you didn't hit that problem then your limits are either already raised or you ran the command as root (why would you do that?). Before you proceed with your development journey you should either raise those limits as documented in login.conf(5) or if you're already in the staff group you can raise your limits for a single terminal. I personally prefer the second option as I think most applications (hello browsers) are too aggressive with resource usage and should be reminded more often that they are not the sole process in the system :)

Here is the mantra I hit every time in a terminal before starting any go commands/editors:

export GOPATH=/home/mulander/go
export PATH=$PATH:$GOPATH/bin
ulimit -n 512
ulimit -p 512
ulimit -d 2036792

The first two should be self explanatory if you did any golang development in the past. The other three handle your limits. No, this time `man ulimit` won't help you as they are shell built ins. If you're the adventurous type then you can go ahead and read the source for ulimit implementation or just read ksh(1). For those that believe me without going to the source/man page:
  • -n - sets the amount of file descriptors that can be open at once
  • -p - sets the amount of processes that can be run by the user at once
  • -d - sets the size limit (in kilobytes) on the size of the data area
Setting an ulimit affects the shell and any processes that are created by this shell after a limit is imposed.

Properly set limits will allow you to work with the go tool:

$ go version
go version go1.4.1 openbsd/386

I mentioned Sublime Text in the passing and as you can guess there is no native binary for OpenBSD. Before switching to ST I was an eager emacs user and decided to give it another try for golang. So go ahread and:

pkg_add emacs
I'm personally using the -gtk3 flavour of the port configured to use MELPA for package management (go read about it). For go development I installed the following packages:
You can find my ~/.emacs file here.
So far I'm more than happy with the way emacs handles go code. All of the above extensions are in MELPA. I just linked them for the eye-candy demo's they all include on their pages (and their documentation!).

By now we have a working go compiler & a development environment/editor. What's next? For me it's goconvey which is a small golang app that runs in the background and constantly runs unit tests displaying a great summary of them in your browser by serving a page on localhost:8080 (default).


Installing goconvey is trivial, just perform go get as noted on their page. What you will find tricky though is the first time you run the app with -cover=true - it will complain that the cover tool is not installed which is true since we didn't do that yet.

This is the last significant pitfall you will encounter. Go will instruct you to go get the tool which will probably end up as follows:

$ go get golang.org/x/tools/cmd/cover 
go install golang.org/x/tools/cmd/cover: open
/usr/local/go/pkg/tool/openbsd_386/cover: permission denied
What happens here is the result of a decision by the golang authors. The go tools want to install in a special $GOTOOLDIR which defaults to /usr/local/go/pkg/tool/openbsd_386/ on my system. Since this is outside your users directory the system correctly blocks write permission to it (you didn't run that as root did you?). So how to get the code coverage tool? You have two options.
  1. Run the command as root (not recommended but I did that fallacy myself :()
  2. Use my port
I hope that by the time you are reading this the port will be pkg_add away. Generally I created a devel/gocover port today that downloads the tools after I hit the same problem some time ago, compiles the cover tool and installs it where go expects to find it. It's undergoing a review now on the ports@ mailing list and if all goes well should be imported to the ports tree. If you want to see this happen please download it, test it and report any problems to me :) While there you might also be interested in the textproc/godoc tool for a nice documentation browser for go packages, this one also hit the mailing list not so long ago. 

With the cover tool installed my personal requirements for a go development setup are met. I must say that I am pretty much satisfied with go on OpenBSD. The only drawback I still feel is the lack of the race detector tool:
$ go test -race
go test: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64
but I can live without it for the time being.

Hope this helped you, happy Go hacking on OpenBSD.