DEV Community

Cover image for Basic Introduction to Makefiles
Abhinav Srinivasan
Abhinav Srinivasan

Posted on

Basic Introduction to Makefiles

What is a Makefile?

Oftentimes as software programs become complicated, with multiple files and hundreds if not thousands of lines of code, managing all this can be a rather demanding and time-consuming process. This is where Makefiles come in.

A Makefile, is essentially a set of instructions written in code that, when implemented properly, can serve as a powerful tool to link multiple files together. Doing so makes testing programs much easier. Instead of handling the different files independently, the instructions automate the entire process, compiling all the files together with a basic make command.

Makefiles intelligently track the various code changes in multiple files and accurately link them. To maximize productivity, it only rebuilds code that has changed since the last compilation. Doing so will ensure that it runs smoothly and, especially with large programs, does not cause lag in the system.

Structure of a Makefile

Now, let’s learn how to make these Makefiles 👀
Example:

`example1: example1.o example2.o
gcc -o main main.o util.o

example1.o: example1.c
gcc -c example1.c

example2.o: example2.c
gcc -c example2.c

clean:
rm *.o example1
`
Enter fullscreen mode Exit fullscreen mode

Above is a basic example of how a Makefile should look like. There are three source files: example1.c and example2.c. It then goes on to specify the compilation commands and the target executable file named "main".

example1: example1.o example2.o
    gcc -o main main.o util.o
Enter fullscreen mode Exit fullscreen mode

The first line here states that the main executable depends on example1.o and the example2.o files. The command following the rule compiles the object files and links them together to create the executable "main". One thing to make sure of is the indentation. For the command, it should be exactly 1 tab indent from the left side of the page.

example1.o: example1.c
    gcc -c example1.c
Enter fullscreen mode Exit fullscreen mode

The second line states that the target "main.o" depends on the source file main.c. The command following the rule compiles main.c into an object file (-c flag indicates compilation without linking).

example2.o: example2.c
gcc -c example2.c
Enter fullscreen mode Exit fullscreen mode

The third line states that util.o depends on util.c and, similarly, the command under it runs it properly.

clean:
rm *.o example1
Enter fullscreen mode Exit fullscreen mode

Lastly, the final rule defines a target "clean" which is used for cleaning up the generated object files and the executable. The command rm .o main removes all object files (.o) and the "main" executable.

Doing this will ensure that the three source files are combined through just the make command.

Quick Mention

One other aspect of Makefiles I just thought of mentioning was Parallel Builds. They are a powerful feature offered by Makefiles, which allow for the execution of build tasks and also speeds up the compilation process. By utilizing the available CPU cores, Makefiles can distribute the workload across multiple jobs, effectively reducing the overall build time. With the -j flag followed by the desired number of parallel jobs, developers can unleash the full potential of their systems, achieving faster iterations and improved productivity.

Top comments (0)