DEV Community

Alvin Abad
Alvin Abad

Posted on

I Love GNU Make

I love GNU Make and Makefiles. It is designed for compiling C/C++ programs but I use it for almost anything that needs to be scripted as long it makes sense. Like any tool, you use it when it's best suited for the job. My rule of thumb is if it can be done using GNU Make, I would try it first before using a more powerful scripting language like bash or Python. What makes it preferable over bash or Python, assuming it can accomplish the task at hand, is simplicity and readability of the code. That's mostly all about it. Of course, there are things, many things, it cannot do compared to Python or bash scripting. But I only switch to them if GNU Make starts becoming complicated.

I use GNU Make to build Golang programs. Below is a sample Makefile to build a Golang project.

Makefile

PROG        := helloworld
GOBIN       := $(CURDIR)/bin
PATH        := $(PATH):$(HOME)/go/bin

ifeq ($(DEBUG),true)
    DEBUG_OPT = -gcflags=all="-N -l"
endif

.PHONY: all \
        help \
        lint \
        gosec \
        fmt \
        gomodtidy \
        vet \
        build \
        install \
        test \
        clean

help:
    @echo "Usage:"
    @echo "    make clean all"
    @echo "    make clean build"
    @echo "    make DEBUG=true clean all"
    @echo "    make vet"
    @echo "    make lint"
    @echo "    make gosec"
    @echo "    make test"
    $(info GOBIN=$(GOBIN))

all: link gosec vet test install

build: gomodtidy vet
    go build -o $(PROG) cmd/main.go

install: gomodtidy vet
    @GOBIN="$(GOBIN)" go install $(DEBUG_OPT) ./...

lint:
    @PATH=$(PATH) golint ./...

gosec: gomodtidy
    @PATH=$(PATH) gosec ./...

fmt:
    go fmt ./...

vet: gomodtidy
    go vet ./...
    golangci-lint run

gomodtidy:
    @go mod tidy

test: gomodtidy
    @go test -bench= ./...

clean:
    @$(RM) -rf "$(GOBIN)"
    @$(RM) -f *.o
Enter fullscreen mode Exit fullscreen mode

As you can see, it's just a bunch of tasks that you want to run against your code. If you want to build the Golang code and produce the executable binary, you simply run:

make clean build
Enter fullscreen mode Exit fullscreen mode

If you want to run test,

make test
Enter fullscreen mode Exit fullscreen mode

If you want to run a linter against your code,

make lint
Enter fullscreen mode Exit fullscreen mode

If you want to check for security issues,

make gosec
Enter fullscreen mode Exit fullscreen mode

All these things can be accomplished using shell scripting. But I think GNU Make is more readable in this scenario. It's easy to spot the targets, which are the tasks intended for the project and how they can be executed. I can easily determine where the main program (package main) is located. I can easily see the name of the executable file and where it will be saved.

If your build script is readable, then it becomes self-documenting. You save yourself of writing a separate documentation, like how to install or build the project.

All my projects use Makefiles. By just looking at the Makefile, I can quickly see how the project is built and other tasks associated with it. To me, the quickest way to learn and understand a code base is if you can build and run it.

Top comments (0)