Exploring Makefile in c/c++ projects


Introduction

You might have stumbled upon Makefile in your projects or might be just curious about what they are. This article will go through a brief overview of what is a MakeFile and understand its workings.

Makefile is generally used for creating build scripts for c/c++ projects and can in general be used for automating tasks. Nowadays python and bash scripting are widely used for this exact purpose and hence you may occasionally encounter Makefile in automating scripts.

What is a Makefile?

make - GNU make utility to maintain groups of programs

A Makefile is an input file for a Linux/UNIX command line utility called make. In short, a Makefile is a list of operations (Target) that has a list of instructions (Recipes) that will be executed when the make command is run in the working directory of the Makefile with appropriate arguments. we will discuss how this works in detail in the below sections.

💡
learn more about Make utility using the "man make" command in Linux shell.

Example Makefile

  • Open up a Linux shell in either Linux or WSL for Windows and create a Makefile in that directory

  • use text editors of your choice to edit the Makefile and type the below example Makefile config

  • run the make command in the same directory as the Makefile and you can see that the instruction is executed.

Important Note: instructions(recipe) use tabbed indentation only don't use space key to indent the instruction. use the "Tab" key to indent the instructions.
  • you could see that the make command executed the target "example_target" with all the instructions inside the target.

  • in short, the syntax of adding targets and recipes in Makefile follows the below syntax

      target: prerequisites
      <TAB> recipe
    

More about Targets

we can have multiple Tasks(targets) with respective instructions (recipes) like the below

💡
If we don't specify what target to run the make command will take the first target and execute it.
  • you can run a specific target using the make command by specifying make with the target name. this will ensure only that particular task is being run

syntax: make [Target_name] ...

make create_file // single target execution
[or]
make create_file delete_file //will run multiple targets
  • In general, we can set a default target that will execute desired tasks when you don't pass any Target name as a parameter.

  • using .DEFAULT_GOAL := [TargetName] or using all: as the target as the first target in the prerequisites section and list all tasks that need to be run by default. this will ensure to run all the listed tasks as default. we will learn more about prerequisites in the next section.

About Prerequisites

As the name suggests prerequisites are a list of arguments that can be a dependency of Target or a file that has to be present to proceed further and execute the instructions. you can specify prerequisites for all tasks based on your instruction dependencies.

💡
let's say you need some file to be present or a task to be executed that will fall under prerequisite.

For example, let's say you have a task that compiles a C++ file the rule could be that the file should be present in that root directory then your prerequisite will be like that.

compile_to_binary: file.cpp
    g++ file.cpp -o binary.out

you will have the following error if the file. cpp is not present in the directory

and further execution is terminated.

Conclusion

Hope that now you will be able to have a fundamental understanding of Makefile and how you can use this make utility to create automation scripts as well as build scripts for languages like C++ and c.