This is a creation in Article, where the information may have evolved or changed.
I've been using Golang for a while, and during the development of Golang, I've been used to repeatedly manually execute go build
and both go test
commands. But now I'm out of this habit. If you only use simple commands without parameters, it may not be scary to do so directly. But in some complex tasks, if it's still manual execution go build
go test
, it can be a headache.
We can solve this problem by other means. For example, you can use a bash script to do this, or a better choice (at least for me) is to write a makefile. Make this tool is born to do these things, in makefile we can put all the common tasks together. I am not a makefile expert, so I may not be able to teach you how to write a good makefile. But in this article, I'm going to show you the Makefile I'm using, and most of my projects use these Makefile. Let's get Started:
# Go parametersGOCMD=goGOBUILD=$(GOCMD) buildGOCLEAN=$(GOCMD) cleanGOTEST=$(GOCMD) testGOGET=$(GOCMD) getBINARY_NAME=mybinaryBINARY_UNIX=$(BINARY_NAME)_unixall: test buildbuild: $(GOBUILD) -o $(BINARY_NAME) -vtest: $(GOTEST) -v ./...clean: $(GOCLEAN) rm -f $(BINARY_NAME) rm -f $(BINARY_UNIX)run: $(GOBUILD) -o $(BINARY_NAME) -v ./... ./$(BINARY_NAME)deps: $(GOGET) github.com/markbates/goth $(GOGET) github.com/markbates/pop# Cross compilationbuild-linux: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BINARY_UNIX) -vdocker-build: docker run --rm -it -v "$(GOPATH)":/go -w /go/src/bitbucket.org/rsohlich/makepost golang:latest go build -o "$(BINARY_UNIX)" -v
I prefer the DPY (Don ' t Repeat yourself) principle. So, in makefile
The beginning of the definition defines commonly used commands and variables, and we can easily reference the defined commands and variables later.
# Basic go commandsGOCMD=goGOBUILD=$(GOCMD) buildGOCLEAN=$(GOCMD) cleanGOTEST=$(GOCMD) testGOGET=$(GOCMD) get# Binary namesBINARY_NAME=mybinaryBINARY_UNIX=$(BINARY_NAME)_unix
In :
front of the goal called Makefile, for example build:
, build
is a goal. If you make
specify a target when executing a command, for example make run
, make builds the target. If no parameters are provided, make defaults to the first target. In our example, the called Target is all
built.
$ make run ## call specific task$ make ## make tool calls "all" task
Basic commands
The most critical part of makefile is building. When make executes, the defined variable is expanded, and $(GOBUILD)
make go build
actually executes the go build
command. The generated binaries are named -o $(BINARY_NAME)
. In addition, I find it -v
useful to switch to verbose mode using parameters. In verbose mode, you can see the package that is currently being built.
build: $(GOBUILD) -o $(BINARY_NAME) -v ## expands to: "go build -o mybinary -v"
Because most of us are lazy, we have a run
goal called. The binaries run
are built and executed after the build completes.
run: $(GOBUILD) -o $(BINARY_NAME) -v ./... ./$(BINARY_NAME)
Generally speaking, the test
command should be part of the makefile. I personally always like to use verbose mode to better debug and observe test run.
test: $(GOTEST) -v ./...
If the project uses CI (continuous integration)/CD (continuous Delivery), even if it is just for consistency, it is a good practice to maintain a series of dependencies in the package. This can be deps
done through the target, which go get
gets all the dependent dependencies through the command.
deps: $(GOGET) github.com/markbates/goth $(GOGET) github.com/markbates/pop
clean
to end this section. rm -f
The order was used to remove the
$(BINARY_XXX)
binary files.
clean: $(GOCLEAN) rm -f $(BINARY_NAME) rm -f $(BINARY_UNIX)
Cross-compiling commands
If project development is on one system and needs to be run on another, it is convenient to include a cross-compiled command in makefile. I usually run binary on the container's Linux platform, so makefile contains the Linux build.
build-linux: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BINARY_UNIX) -v
If your code uses C binding, you may encounter some problems. The problem with CGO is that you need a GCC that is compatible with a given platform. If the development is done on osx/windows, then you need to have a Linux-compatible GCC. At least for me, using the configuration gcc cross-compiling C code on OSX is not easy. If you need CGO, Docker mirroring is the best way to create a Linux build. The only requirement in this way is that Docker must be installed.
docker-build: docker run --rm -it -v "$(GOPATH)":/go -w /go/src/bitbucket.org/rsohlich/makepost golang:latest go build -o "$(BINARY_UNIX)" -v
The Makefile example of this article can be found here.
Translator: The original use of the Makefile can actually be better, for example, in the comments below the original point, it should be indicated at least .PHONY:
, build
the other should be run
the precondition. However, we can learn some of the desirable parts.
This article was translated from: Golang:don ' t afraid of makefiles