Makefile 101

Makefile 101: Useful tips and tricks

Alex Tan
4 min readJun 6, 2020


Here are some useful tips on using Makefile and how to optimize them:

Creating a Makefile

In order to work with Makefile , we need to create one first:

Hello World

Let’s start with a basic command. Add this to your Makefile :

Then run make greet . Hurray, you ran your first Makefile command!

Hello World

Chaining Commands

Makefile commands can be chained.

Chaining Makefile commands

Running this will produce the following output:

Executing chained commands

This is especially useful when you have multiple steps involved, e.g. building and deploying a container:

A more complex example of chaining commands with Makefile

Suppressing command output

To suppress the command being executed, add @ before the command:

Suppressing command output

Note the difference between @echo hello command andecho bye command when running $ make greet :

Using Environment Variables

You can pass environment variables into Makefile when running the command:

Using Environment Variables

Let’s see what will happen when we run the command while passing in the environment variable:

Passing environment variables in command

This is useful if you need to use Makefile to configure builds for certain environment, e.g. ENV=prod make build.

Loading environment variables from file

Makefile can also load environment variables from .env file. We will touch more on how to load different .env files ( .env.staging, .env.production ) next.

Including .env file in Makefile

If you want to make it optional, add the minus sign before include. Otherwise, an error will occur if the .env file does not exist:

Making .env file optional

The export will export all available environment variables in the Makefile.

You can include as many .env files as you want, the order matters though

Including multiple .env files

Loading enviroment variables dynamically

You can also load environment variables dynamically based on the current environment. The example below assumes that you use the ENV environment variable:

Including .env files based on existing ENV


Toggling different environment when running Makefile command

Environment guards

Say if we only want to ensure that certain command can only be run in certain environment:

Setting up guards for environment variables


Guard for different environment

You can make a CLI with your Makefile

Just run make without any commands, it will print the command and the description.

Useful variables

Here are the common variables that might be useful when you are working with Makefiles. Note that to run the shell command, it has to be within the brackets and prefixed with shell, e.g. $(shell git rev-parse HEAD) .

Useful Makefile variables

Using dynamic variables in command

Sometimes you just want to get dynamic values from your command:

Getting dynamic value from command

Modular Makefiles

You can separate your Makefiles into smaller Makefiles. This promote reusability, while keeping your Makefile small. Say you have the following Makefiles:

In database/Makefile:


In docker/Makefile:


You can now include them in your main Makefile at the root of your project directory:

Main Makefile

And you can run all the commands that are available in docker/Makefile and database/Makefile:

Running all commands from combined Makefile

The only disadvantage is that the naming of the command cannot be the same.

Hope you find this tips useful! You can also find the README for this article here in my Github Repo: