4 ms·
You're missing half of what makefiles are for: only building what you need based on dependencies. I never used Go so the following may not be technically corre
by williamdclt 9y ago
You're missing half of what makefiles are for: only building what you need based on dependencies.
I never used Go so the following may not be technically correct, but in principle:
- The `build` rule should be `build: *.go` so that it builds only if a file has changed.
- The `run` rule should have the `build` rule as dependency, so as to not rebuild if nothing has changed. Plus, it avoid to repeat the almost-identical build command (which is not very DRY)
Plus, I'm not convinced of the usefulness of having a $GOCMD variable (or $GOGET, $GOBUILD...). But again, never used go, no idea if the tooling is as tweakable as C (for which this kind of variable is used a lot in makefiles)
- jgrahamc 9y agoYou really don't want to do that. I know what you mean but the go command handles the dependency stuff. Trying to shoe horn that into a Makefile is a disaster.
- zeveb 9y agoIt's doable though: 'go list -f "{{.Stale}}" $PACKAGE' can be used to determine if a package needs to be rebuilt; this can be used in a make rule which touches a stamp file, and then the stamp file may be relied upon for other make rules. My quibble with the example Makefile as written is that it doesn't utilise 'go install,' which I much prefer to 'go build.'
- baby 9y agoI don't think you can/need make to check timestamps for Go. `go build` will do it for you.
- humanrebar 9y agoYou do if you want to only run some tests sometimes or only trigger a new docker image if the binary actually changed.
- insertnickname 9y agogo install caches build artifacts and only rebuilds when necessary (or when explicitly instructured to rebuild everything). go build builds from scratch every time—IIRC and if it hasn't changed since this I learned this. There's no need to attempt to reimplement go install's caching in make.
- lobster_johnson 9y agoYou can get build caching with "go build -i". It's a not very well known option.
- LaGrange 9y agoYou can figure out what the dependencies of a file using go list, I used something like ${GOCMD} list -f "{{ .ImportPath }} {{join .Deps \" \" }}" ./cmd/$command | \ xargs ${GOCMD} list -f "{{ if not .Standard }}build/mac/${command}: {{ range .GoFiles }}{{ \$.Dir }}/{{ . }} {{ end }}{{ end }}" ./cmd/${command} | \ sed "s: /go/src/com.test/your/package/: :g" ...and then including the output of that in the Makefile. There are ways to make sure it gets rebuilt if anything changes, but you'll pay a performance price. It's rather similar to what happens with C, as far as I remember. It was quite evil, somewhat redundant, and I eventually found make to complicate things for my application more than it was helpful, but sure, you can map modified go files to whatever tasks you might want to do. EDIT: note that, unlike in C, go (usually) has a single static output file, so without the .o stage, the dependencies are quite dynamic - a change to a go file not included directly might be cause for a recompile. You can build intermediates, (I think either Buck or Bazel do that?) and link by hand, but that's very non-standard.
- munro 9y agoI've recently started using Makefiles for this reason, it cut my cache hit on checking if my docker image needs a rebuild based on dependencies from 1.8s to 0.03s. My workflow had me hitting this check probably 20 times/day, so it was a huge time save! IGNORE_FILES := "Makefile\|.gitignore\|.dockerignore" DOCKER_CONTEXT := $(shell git ls-files -cmo --exclude-standard \ --exclude-from=.dockerignore \ | grep -v $(IGNORE_FILES)) .PHONY: build build: .build/docker_image .build/docker_image: .build $(DOCKER_CONTEXT) docker build -t $(IMAGE) . docker images -q $(IMAGE) > $@ .build: @mkdir -p $@ I'm still figuring this stuff out, so I would love any feedback. :)