<commit_before>---
title: Make and Go for Fun and Profit
---

I've been somewhat interested in Go for quite a while now. It's gotten to the
point where it has replaced Ruby for me in those places where I write command
line utilities which are too involved for them to make sense to be a shell
script. I don't have too many opinions about the language itself, but I like
the static type system and that it's a compiled language. And to be honest,
the build system and how to utilize it have been the most interesting bits for
me so far. One thing I especially like is the fact that go provides a bunch of
tooling to do different things but how you tie them together is up to you. So
this gives rise to some fun use cases for a nice Makefile.

### The Basics
Every project I start gets this Makefile with some basic setups and variable
definitions that I always want.

```make
export GO15VENDOREXPERIMENT = 1

# variable definitions
NAME := coolthings
DESC := a nice toolkit of helpful things
PREFIX ?= usr/local
VERSION := $(shell git describe --tags --always --dirty)
GOVERSION := $(shell go version)
BUILDTIME := $(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
BUILDDATE := $(shell date -u +"%B %d, %Y")
BUILDER := $(shell echo "`git config user.name` <`git config user.email`>")
PKG_RELEASE ?= 1
PROJECT_URL := "https://github.com/mrtazz/$(NAME)"
LDFLAGS := -X 'main.version=$(VERSION)' \
           -X 'main.buildTime=$(BUILDTIME)' \
           -X 'main.builder=$(BUILDER)' \
           -X 'main.goversion=$(GOVERSION)'

```

For the most part this just defines a whole bunch of meta data that gets
compiled into the binaries via linker flags. This is a pattern I have seen in
a lot of Go projects and I really like that this is somewhat of a standard
thing to do. Especially with the static nature of Go binaries, the more
helpful information you can compile into the binary the better it is when you
have to figure out where a binary comes from.

I also always have a handful of tasks defined that are helpful for running
tests and such, especially to have a uniform and documented way how they are
run locally and on CI.

```make
# development tasks
test:
	go test $$(go list ./... | grep -v /vendor/ | grep -v /cmd/)

coverage:
	@-go test -v -coverprofile=cover.out $$(go list ./... | grep -v /vendor/ | grep -v /cmd/)
	@-go tool cover -html=cover.out -o cover.html

benchmark:
	@echo "Running tests..."
	@go test -bench=. $$(go list ./... | grep -v /vendor/ | grep -v /cmd/)
```

These make heavy use of `go list` to determine existing packages to run tests
for. The rules also exclude the vendor folder as I don't want to run those
tests and the cmd folder which I will describe more in the next section.

### Structure for multiple binaries

Go has this defacto standard of how to structure code if your build produces
multiple executables. Since your main entry point in the app is always the
main package and there can only be one per directory (which is also true for
any other package btw) you need to separate different executables by<commit_msg>add the fixed version of the coverage target<commit_after>---
title: Make and Go for Fun and Profit
---

I've been somewhat interested in Go for quite a while now. It's gotten to the
point where it has replaced Ruby for me in those places where I write command
line utilities which are too involved for them to make sense to be a shell
script. I don't have too many opinions about the language itself, but I like
the static type system and that it's a compiled language. And to be honest,
the build system and how to utilize it have been the most interesting bits for
me so far. One thing I especially like is the fact that go provides a bunch of
tooling to do different things but how you tie them together is up to you. So
this gives rise to some fun use cases for a nice Makefile.

### The Basics
Every project I start gets this Makefile with some basic setups and variable
definitions that I always want.

```make
export GO15VENDOREXPERIMENT = 1

# variable definitions
NAME := coolthings
DESC := a nice toolkit of helpful things
PREFIX ?= usr/local
VERSION := $(shell git describe --tags --always --dirty)
GOVERSION := $(shell go version)
BUILDTIME := $(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
BUILDDATE := $(shell date -u +"%B %d, %Y")
BUILDER := $(shell echo "`git config user.name` <`git config user.email`>")
PKG_RELEASE ?= 1
PROJECT_URL := "https://github.com/mrtazz/$(NAME)"
LDFLAGS := -X 'main.version=$(VERSION)' \
           -X 'main.buildTime=$(BUILDTIME)' \
           -X 'main.builder=$(BUILDER)' \
           -X 'main.goversion=$(GOVERSION)'

```

For the most part this just defines a whole bunch of meta data that gets
compiled into the binaries via linker flags. This is a pattern I have seen in
a lot of Go projects and I really like that this is somewhat of a standard
thing to do. Especially with the static nature of Go binaries, the more
helpful information you can compile into the binary the better it is when you
have to figure out where a binary comes from.

I also always have a handful of tasks defined that are helpful for running
tests and such, especially to have a uniform and documented way how they are
run locally and on CI.

```make
# development tasks
test:
	go test $$(go list ./... | grep -v /vendor/ | grep -v /cmd/)

PACKAGES := $(shell find ./* -type d | grep -v vendor)

coverage:
	@echo "mode: set" > cover.out
	@for package in $(PACKAGES); do \
		if ls $${package}/*.go &> /dev/null; then  \
		go test -coverprofile=$${package}/profile.out $${package}; fi; \
		if test -f $${package}/profile.out; then \
		cat $${package}/profile.out | grep -v "mode: set" >> cover.out; fi; \
	done
	@-go tool cover -html=cover.out -o cover.html

benchmark:
	@echo "Running tests..."
	@go test -bench=. $$(go list ./... | grep -v /vendor/ | grep -v /cmd/)
```

These make heavy use of `go list` to determine existing packages to run tests
for. The rules also exclude the vendor folder as I don't want to run those
tests and the cmd folder which I will describe more in the next section.

### Structure for multiple binaries

Go has this defacto standard of how to structure code if your build produces
multiple executables. Since your main entry point in the app is always the
main package and there can only be one per directory (which is also true for
any other package btw) you need to separate different executables by
{'fraction_non_alphanumeric': 0.08870841792909574, 'fraction_numerical': 0.0012494143370295175, 'mean_word_length': 3.5906810035842294, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1754192', 'n_tokens_mistral': 1822, 'n_tokens_neox': 1772, 'n_words': 1009}