Makefile basic
make - a handy automation tool

  Mar 07, 2018 -   read
  engineering, unix, programming, tutorial

Keep seeing Makefile in popular open source repositories and wondering what it is? Me too, after browsing the Internet and learn some basic stuff on make utility, I decide to take note here, in this blog. The make utility requires a file, Makefile , which defines a set of tasks to be executed. You can use make to compile source codes, produce a final executable binary, which can then be installed using make install.

Let’s start by printing the classic Hello world... on the terminal. Create a empty directory which containing a file Makefile with this content:

welcome:
    @echo "Hello world..."

Now run the file by typing make, the output will be:

$ make
echo "Hello world..."
Hello world...

In the example above:

  • welcome behaves like a function name, as in any programming language. This is called the target.
  • The prerequisites or dependencies follow the target. In the above example, we have not defined any prerequisites in this example.
  • The command echo "Hello world..." is called the recipe. The recipe uses prerequisites to make a target.
  • The target, prerequisites, and recipes together make a rule.

To summarize, below is the syntax of a typical rule:

target: [prerequisites]
<TAB> [recipes]
[targets]

Let’s add a few more targets: generate and clean to the Makefile:

welcome:
    @echo "Hello world..."
generate:
    @echo "Creating empty text files..."
    touch file-{1..10}.txt
clean:
    @echo "Cleaning up..."
    rm *.txt

If we try to run make after the changes, only the target welcome will be executed. That’s because only the first target in the Makefile is the default target. Often called the default goal, this is the reason you will see all as the first target in most projects. It is the responsibility of all to call other targets. We can override this behavior using a special phony target called .DEFAULT_GOAL.

Let’s include that at the beginning of our Makefile:

.DEFAULT_GOAL := generate

This will run the target generate as the default:

$ make
Creating empty text files...
touch file-{1..10}.txt

As the name suggests, the phony target .DEFAULT_GOAL can run only one target at a time. This is why most Makefile include all as a target that can call as many targets as needed.

Let’s include the phony target all and remove .DEFAULT_GOAL:

all: welcome generate

welcome:
    @echo "Hello world..."
generate:
    @echo "Creating empty text files..."
    touch file-{1..10}.txt
clean:
    @echo "Cleaning up..."
    rm *.txt

Before running make, let’s include another special phony target, .PHONY, where we define all the targets that are not files. make will run its recipe regardless of whether a file with that name exists or what its last modification time is. Here is the complete Makefile:

.PHONY: all welcome generate clean

all: welcome generate

welcome:
    @echo "Hello world..."
generate:
    @echo "Creating empty text files..."
    touch file-{1..10}.txt
clean:
    @echo "Cleaning up..."
    rm *.txt

The make invocation should run welcome and generate:

$ make
Hello world...
Creating empty text files...
touch file-{1..10}.txt

It is a good practice not to call clean in all or put it as the first target (default target). clean should be called manually when cleaning is needed as a first argument to make:

$ make clean
Cleaning up...
rm *.txt

Now that you have an idea of how a basic Makefile works and how to write a simple Makefile.

:smile:

Dang Chien
Software engineer, solution architect and Agile practitioner.
Do you find this article helpful ❤️ ? Support me with a coffee via paypal.me/ck1910, give me a shout out on Twitter at @dangchien87, or help to share this article instead.