Manage more code with Make

The GNU make utility, commonly abbreviated as make, is a tool for controlling the generation of executables from source files. make automatically determines which changed parts of a complex program need recompilation. make uses Makefiles to control how you build programs.

GNU make and Makefile overview

To create a usable form (usually executable files) from the source files of a particular project, perform several necessary steps. Record the actions and their sequence to be able to repeat them later.

Red Hat Enterprise Linux contains GNU make, a build system designed for this purpose.

What is GNU make
GNU make reads Makefiles which contain the instructions describing the build process. A Makefile contains multiple rules that describe a way to satisfy a certain condition (target) with a specific action (recipe). Rules can hierarchically depend on another rule.

Running make without any options makes it look for a Makefile in the current directory and attempt to reach the default target. The actual Makefile file name can be one of Makefile, makefile, and GNUmakefile. The default target is determined from the Makefile contents.

To run make with a specific target:

$ make target
Makefile structure and syntax
Makefiles use a relatively simple syntax for defining variables and rules, which consists of a target and a recipe. The target specifies what is the output if a rule is executed. The lines with recipes must start with the TAB character.

Typically, a Makefile contains rules for compiling source files, a rule for linking the resulting object files, and a target that serves as the entry point at the top of the hierarchy.

Basic Makefile example
Consider the following Makefile for building a C program which consists of a single file, hello.c.
all: hello

hello: hello.o
        gcc hello.o -o hello

hello.o: hello.c
        gcc -c hello.c -o hello.o

This example shows that to reach the target all, file hello is required. To get hello, one needs hello.o (linked by gcc), which in turn is created from hello.c (compiled by gcc).

The target all is the default target because it is the first target that does not start with a period (.). Running make without any arguments is then identical to running make all, when the current directory contains this Makefile.

Advanced Makefile with variables
A more typical Makefile uses variables for generalization of the steps and adds a target "clean" - remove everything but the source files.
CC=gcc
CFLAGS=-c -Wall
SOURCE=hello.c
OBJ=$(SOURCE:.c=.o)
EXE=hello

all: $(SOURCE) $(EXE)

$(EXE): $(OBJ)
        $(CC) $(OBJ) -o $@

%.o: %.c
        $(CC) $(CFLAGS) $< -o $@

clean:
        rm -rf $(OBJ) $(EXE)

Adding more source files to such Makefile requires only adding them to the line where the SOURCE variable is defined.

Installed documentation
  • Use the man utility to view manual pages installed on your system:
    $ man make
  • Use the info utility to view information pages installed on your system:
    $ info make

Example: Build a C program using a Makefile

To build a sample C program by using a Makefile, follow the steps in this example.

Before you begin

  • You must understand the concepts of Makefiles and make. For details, see GNU make and Makefile overview. .Procedure
    1. Create a directory hellomake:
      $ mkdir hellomake
    2. Change to the created directory:
      $ cd hellomake
    3. Create a file hello.c with the following contents:
      #include <stdio.h>
      
      int main(int argc, char *argv[]) {
        printf("Hello, World!\n");
        return 0;
      }
    4. Create a file Makefile with the following contents:
      CC=gcc
      CFLAGS=-c -Wall
      SOURCE=hello.c
      OBJ=$(SOURCE:.c=.o)
      EXE=hello
      
      all: $(SOURCE) $(EXE)
      
      $(EXE): $(OBJ)
              $(CC) $(OBJ) -o $@
      
      %.o: %.c
              $(CC) $(CFLAGS) $< -o $@
      
      clean:
              rm -rf $(OBJ) $(EXE)
      Important
      The Makefile recipe lines must start with the tab character. When you copy this example from the documentation, the cut-and-paste process might paste spaces instead of tabs. If this happens, correct the issue manually.
    5. Run make:
      $ make
      gcc -c -Wall hello.c -o hello.o
      gcc hello.o -o hello

      This creates an executable file hello.

    6. Run the executable file hello:
      $ ./hello
      Hello, World!
    7. Run the Makefile target clean to remove the created files:
      $ make clean
      rm -rf hello.o hello