DEV Community

Cover image for Makefile Fundamentals
0066cc
0066cc

Posted on • Originally published at 0066cc.com on

Makefile Fundamentals

What's a makefile?

A makefile is simply a file consisting of one or more scripts, referred to as targets, that can be run by the user using the make program that is available on most Linux distributions.

These targets consist of one or more commands that would otherwise need to be repeatedly typed out by hand; hence by bundling these commands together it is possible to automate portions of, or all, of the build process when compiling a program. Additionally, makefiles can also be used to automate testing and general computing processes.

Makefile Fundamental Structure

An outline example of a makefile is listed below:

msg="This message was stored in a variable!"
target_name:
    echo "Hi! This is a command that will be run!"
    echo "Each target can run more than one command!"
# This is a comment, it wont show up when you run the makefile.
another_target_name:
    echo "And this is another command that could be run independently!"
    # This is also a valid comment
final_target_name: example.txt
    echo $(msg)

Enter fullscreen mode Exit fullscreen mode

The key takeaways from this example are that:

  • Each runnable target of your makefile must have a name that ends with a colon (:).
  • Each command inside a section must be indented by one tab. Indenting with spaces will result in an error.
  • In larger makefiles it may be appropriate to add comments explaining non-obvious commands. Comments can be inserted with a hashtag (#). Comments do not need to be indented the same way regular commands are.
  • Placing a file name after the target name can be used to specify file(s) that are needed for the target to run.
  • Makefiles also offer support for variables like those seen on the first and last line.

Using A Makefile

If you wish to get a better feel for how makefiles work, try experimenting with changing the target names and ordering. To run the above makefile for yourself:

  1. Create a new blank text file in a directory you have access to.
  2. Open the new file in a text editor.
  3. Either copy or type out the example makefile listed above.
  4. Save the file as 'makefile' and close the file.
  5. Open a terminal and navigate to the directory containing the makefile.
  6. Type 'make target_name' and run the command.
  7. Type 'make another_target_name' and run the command.
  8. Type 'make final_target_name' and run the command.
  9. Type 'make' and run the command.

Output of Step 6:

echo "Hi! This is a command that will be run!"
Hi! This is a command that will be run!
echo "Each target can run more than one command!"
Each target can run more than one command!

Enter fullscreen mode Exit fullscreen mode

Output of Step 7:

echo "And this is another command that could be run independently!"
And this is another command that could be run independently!

Enter fullscreen mode Exit fullscreen mode

Output of Step 8:

make: *** No rule to make target 'example.txt', needed by 'makefile'. Stop.

Enter fullscreen mode Exit fullscreen mode

Requirements

You should have received an error when you attempted to run this target. Why is that? The reason for this error is that a requirement has been specified for this target; in order for this target to run the file specified immediately after the target name must be present (in this example 'example.txt').

Output of Step 8 (Corrected):

In order to make this target run create a file called 'example.txt' in the same directory as the makefile. 'Example.txt' can contain anything or even be blank but as long as the file exists, it meets the requirements of the makefile.

Running the makefile now presents the following:

echo "This message was stored in a variable!"
This message was stored in a variable!

Enter fullscreen mode Exit fullscreen mode

Output of Step 9:

echo "Hi! This is a command that will be run!"
Hi! This is a command that will be run!
echo "Each target can run more than one command!"
Each target can run more than one command!

Enter fullscreen mode Exit fullscreen mode

No target Specified

It can also be important to remember that simply typing make with no additional specifications will automatically attempt to run the first target listed in the makefile. In this instance, running 'make' will output the same result as make target_name.

> make
echo "Hi! This is a command that will be run!"
Hi! This is a command that will be run!
echo "Each target can run more than one command!"
Each target can run more than one command!

> make target_name
echo "Hi! This is a command that will be run!"
Hi! This is a command that will be run!
echo "Each target can run more than one command!"
Each target can run more than one command!

Enter fullscreen mode Exit fullscreen mode

Additional Features

Hide Displaying Commands

By default, makefiles will automatically display the command that is being run, like how the echo command is shown before actually echoing the text:

> make
echo "Hi!"
Hi!

Enter fullscreen mode Exit fullscreen mode

To suppress showing the command that is being run and just display the output, prepend the command in question with an at-symbol(@).

make:
    @echo "Hi!"

Enter fullscreen mode Exit fullscreen mode

Doing so will now output:

> make
Hi!

Enter fullscreen mode Exit fullscreen mode

Variables

It's also possible to define variables in a makefile, these can be used to include additional information that can be passed to a command or used to alter how a target should run.

Declaring and Using Variables

Variables must be declared outside any targets like so:

msg="Hello!"
text="Another variable!"
make:
    echo $(msg)
    echo $(text)

Enter fullscreen mode Exit fullscreen mode

Once a variable has been declared, it can then be used in a target by enclosing the variable name with a dollar-sign and brackets $().

Passing Variables

It is possible to pass variables into the makefile from the command-line when a target is run like so:

> make msg="New value!"

Enter fullscreen mode Exit fullscreen mode

Using the same makefile as above will now display:

> make msg="New value!"
echo "New value!"
New value!
echo "Another variable!"
Another variable!

Enter fullscreen mode Exit fullscreen mode

By passing variables this way, they do not need to be declared and initialised in the makefile itself, instead it is possible to simply use the variable as if it has already been declared like so:

make:
    echo $(msg)

Enter fullscreen mode Exit fullscreen mode

Note how msg has not been declared at the top of the file; if you attempt to run the makefile with no additional information then the following will be displayed:

> make
echo

Enter fullscreen mode Exit fullscreen mode

As the variable has not been given a value, nothing is printed to the screen. In order to give msg a value, the makefile must be ran like so:

> make msg="New value!"
echo "New value!"
New value!

Enter fullscreen mode Exit fullscreen mode

Custom Makefile Name

Although makefile is the default filename that will be checked for when you run make, it is possible to use an alternative filename.To do so, when running the make command include the -f switch followed by the name of the file you want to use:

> make -f alternativeMake print_msg

Enter fullscreen mode Exit fullscreen mode

In the above, the make command is used on a file called alternativeMake and attempts to run a target called print_msg.

Additional Resources

That concludes the fundamentals of makefiles, this guide covered:

  • Makefile structure and syntax.
  • Requirements
  • Declaring, using, and passing variables.
  • Modifying output with command suppression.
  • Custom makefile names

If you are interested in learning about even more of the features that makefiles offer (such as conditional targets, functions, and recursively expanded variables), consider consulting the official documentation.

Top comments (0)