Skip to content

Instantly share code, notes, and snippets.

@awreece
Created March 2, 2012 07:32
Show Gist options
  • Save awreece/1956513 to your computer and use it in GitHub Desktop.
Save awreece/1956513 to your computer and use it in GitHub Desktop.
Simplest Possible Makefile
# Comments in makefiles follow the same form as comments in bash.
# Makefiles need to be named "Makefile" or "makefile".
# In makefiles, variables are declared in the following manner (the entire
# string after the equals and up to but excluding the newline is the
# content of the variable)
#
# Note: there are other ways to declare variables that are not explored in this
# tutorial.
TARGET = my_cc
# To access a make variable, do
# $(FOO)
# Make sure to use parentheses (they are necessary in most cases).
# It is traditional in make to have whitespace separated lists. In make, a \
# at the end of a line removes the following newline.
SOURCES = lexicalanalyzer.c \
parser.c \
pmachine.c \
driver.c
# The syntax below is a special way to access a variable that also does a
# pattern replacement : in this case, it replaces all .c extensions with a .o
#
# Another common alternative is:
# OBJECTS = $(patsubst %.c, %.o, $(SOURCES))
OBJECTS = $(SOURCES:.c=.o)
# These are default variables in make, but it is traditional to overwrite them.
CC=gcc
CFLAGS= -O1 -g -Wall
LD=ld
LDFLAGS=
# Make rules are of the form (target) : (pre-requisite). The first make
# rule in the file the default one executed when you call "make" with no
# arguments. It is possible to run a different rule by running "make test",
# for example. Consequently, it is traditional for an "all" or "default" rule
# to be the first one in a file.
all : $(TARGET)
# All lines following the make rule that are indented by a tab are known as
# the recipe for a rule and are executed by a shell if the rule needs to be
# evaluated. In addition, make specifies some special variables that are
# valid in the context of a make rule:
# $@ expands to the target in question
# $^ expands to the space separated list of all the pre-requisites
# $< expands to the name of the first pre-requisite
# (There are many more, but these three are the most common)
#
# In this case, the recipe (after expansion of make variables) is
# ld -o my_cc lexicalanalyzer.o parser.o pmachine.o driver.o
$(TARGET) : $(OBJECTS)
$(LD) $(LDFLAGS) -o $@ $^
# Note that more than one target can be on the left hand side for a given make
# rule. This is equivalent to making a unique rule for each target of the make
# rule.
#
# In this case, this is a special form of a make rule where make attempts to do
# pattern matching. If no explicit rule is found for a pre-requisite, implicit
# rules such as the one below are checked until one is found that matches the
# pre-requisite.
#
# In this case, since none of the object files in $(OBJECTS) have an explict rule,
# they are each matched by the following implicit make rule. One such expansion
# of this implicit rule is:
# parser.o : parser.c
# gcc -O1 -g -Wall -o parser.o -c parser.c
#
# Note that this rule and the equivalent rules for .cpp, .s, and other files are
# provided by default with make.
%.o : %.c
$(CC) $(CFLAGS) -o $@ -c $<
# Note that there can be multiple rules that match a given target and that make
# intelligently matches all of them. Here we specify that all of our object files
# depend on a common header. Since we used the variable $< above in our implicit
# rule, the header file will not be passed to gcc (only the first pre-requisite is).
$(OBJECTS) : common.h
# The .PHONY target is a fake target. All targets that are a pre-requisite of
# the .PHONY target are updated regardless of the status of their pre-requisites.
#
# Rules that specify commands to be run rather than files to be created (such
# as clean, install, test, or default) ought to be declared .PHONY.
.PHONY : clean all
clean :
rm -f $(OBJECTS)
# For more information, see http://www.gnu.org/software/make/manual/make.html
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment