Makefile 101

Makefile 101: Useful tips and tricks

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

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

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

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

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 :

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.

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

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

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

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

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

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

Getting dynamic value from command

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:



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store