Notes - Make

Minimal Makefile Explainer

CFLAGS = -Wall -Wextra
CC = gcc
VPATH = src
 
 
make_tutorial : main.o calculator.o greeter.o
        $(CC) $(CFLAGS) $? -o $@
 
main.o : main.c
        $(CC) $(CFLAGS) -c $? -o $@
 
calculator.o : calculator.c
        $(CC) $(CFLAGS) -c $? -o $@
 
greeter.o : greeter.c
        $(CC) $(CFLAGS) -c $? -o $@

Each consecutive rule after the make_tutorial rule is creating an object file from the source file of same the name. I can understand how complex this feels. So let us break down each of these automatic and implicit variables and understand what they mean.

  • $(CC): Calls the GNU C Compiler (gcc).
  • $(CFLAGS): An implicit variable to pass in our compiler flags like -Wall, etc.
  • $?: Names of all prerequisite files that are newer than the target. In the rule for main.o, $? will expand to main.c IF main.c has been modified after main.o had been generated.
  • $@: This is the target name. I am using this to omit typing the rule name twice. In rule for main.o, $@ expands to main.o.

Automatic variables

The make utility has a few automatic variables to help ease repetition even further. These variables are commonly used in a rule’s recipe. Some of the automatic variables are as follows:

Automatic variablesMeaning
$@Name of the rule of target. Usually used to specify the output filename.
$<Name of the first pre-requisite.
$?Names of all pre-requisites that are newer than the target. i.e. files that have been modified after the most recent code compilation
$^Names of all pre-requisites with spaces between them.

You can find the full list of the automatic variables on GNU Make’s official documentation.

Purpose of a makefile and how does makefile.am differ

This section is llm-generated by Phind

A Makefile is a file that contains a set of directives used by a make build automation tool to generate a target/goal. The main purpose of a Makefile is to simplify the build process of a software project. It allows developers to specify how to derive the target program from the source files, and in what order the files should be processed Source 2, Source 5.

A Makefile contains rules, which are the instructions for building the target. Each rule has a target, prerequisites, and a recipe. The target is the file to be generated, the prerequisites are the files that the target depends on, and the recipe is the series of commands that make will execute to generate the target Source 5, Source 6.

For example, a simple Makefile might look like this:

CFLAGS = -Wall -Wextra
CC = gcc
VPATH = src
 
make_tutorial : main.o calculator.o greeter.o
       $(CC) $(CFLAGS) $? -o $@
 
main.o : main.c
       $(CC) $(CFLAGS) -c $? -o $@
 
calculator.o : calculator.c
       $(CC) $(CFLAGS) -c $? -o $@
 
greeter.o : greeter.c
       $(CC) $(CFLAGS) -c $? -o $@

This Makefile specifies how to compile and link several C source files into a single executable Source 5.

On the other hand, a Makefile.am is a script designed to feed Autoconf to provide dependency information as a higher-level yet more readable abstraction. Autoconf uses this information to generate Makefile.in files, which contain scripts and information for the actual configuration process. This combination helps us save precious time as we don’t need to dig through the pile of configuration mayhem anymore Source 1.

In summary, the main difference between a Makefile and a Makefile.am is that the former is used by the make tool to build a software project, while the latter is used by the automake tool to generate a Makefile.in file, which is then used by autoconf to generate a Makefile.