Using "make" and writing Makefiles

make is a Unix tool that simplifies building programs when they are composed from many files, or building many programs simultaneously. It is able to determine when source files have changed and rebuild only those components needed for an update.

This is just a quick overview, see the man page for more details. A more complete reference can be found in the GNU make manual.


Using Make

  1. Create a Makefile: When you download many open source programs, this is already done for you. Inside this file is a list of dependencies and rules for how to build the software. If you add in additional source files or programs, you may need to update this to keep it up to date.
  2. Edit source files
  3. Run make: All you need to do is run the program from the command line without any arguments.

    % make

    You can also specify a "target" or make use of multiple processors.

    # compile a specific target
    
    % make target_name
    
    # clean up things (rule needs to be in the Makefile)
    
    % make clean
    
    # use multiple processors (in this case 3)
    
    % make -j 3
    

Writing a Makefile

While it may seem that Makefiles are a bit arcane, they can be readily understood with just a little bit of information.

Sample Makefiles

Here is a simple makefile to build a C program.


# build a program from 2 files and one shared header
CC = gcc
CFLAGS = -g

program: source1.c source2.c
	$(CC) $(CFLAGS) -o program source1.c source2.c 

This is OK for a small program, but you can only recompile the parts that have changed with just a few changes.


# build a program from 2 files and one shared header
CC = gcc
CFLAGS = -g

source1.o: source1.c
	$(CC) $(CFLAGS) -c source1.c

source2.o: source2.c
	$(CC) $(CFLAGS) -c source2.c

program: source1.o source2.o
	$(CC) $(CFLAGS) -o program source1.o source2.o 

If you are using the proper variables (e.g., CC and CFLAGS), then you can take advantage of make's builtin rules for creating object files. For example, it knows how to properly make a .o file from a .c file. Run make --print-data-base to see all the builtin rules.

This means you can shorten the above makefile down to just one specified build rule, with the rest being implicit. (I've added some additional debugging in to the compiler flags.)


# build a program from 2 files and one shared header
CC = gcc
CFLAGS = -g -Wall -pedantic

program: source1.o source2.o
	$(CC) $(CFLAGS) -o program source1.o source2.o 

There are also a variety of automatic variables that make uses when evaluating a rule. Two that I find useful are:

So we can further simplify things by writing:


# build a program from 2 files and one shared header
CC = gcc
CFLAGS = -g -Wall -pedantic

program: source1.o source2.o
	$(CC) $(CFLAGS) -o $@ $^ 

For other languages, other variables are used. For example:


Last Modified: October 06, 2011 - Benjamin A. KupermanVI Powered