28
make: the good, the bad, and the ugly Dan Berger [email protected]. edu Titus Winters [email protected]. edu

make: the good, the bad, and the ugly

  • Upload
    garvey

  • View
    32

  • Download
    0

Embed Size (px)

DESCRIPTION

make: the good, the bad, and the ugly. Dan Berger [email protected] Titus Winters [email protected]. Outline. What is make, and why do you care? Key concepts makefiles, targets, directives & variables. A simple makefile Implicit variables A better makefile Words of caution. - PowerPoint PPT Presentation

Citation preview

Page 1: make: the good, the bad, and the ugly

make: the good, the bad, and the ugly

Dan Berger [email protected]

Titus Winters [email protected]

Page 2: make: the good, the bad, and the ugly

Outline

What is make, and why do you care? Key concepts

makefiles, targets, directives & variables.

A simple makefile Implicit variables A better makefile Words of caution

Page 3: make: the good, the bad, and the ugly

What is Make?

“The ‘make’ utility automatically determines which pieces of a large program need to be recompiled, and issues commands to recompile them.”

-- The GNU Make Manual

Page 4: make: the good, the bad, and the ugly

Why Do I Care?

Let’s say I have a program with only one source file – simple.cc.

Creating the program is easy: g++ <flags> simple.cc –o simple

What if I have 10 source files? g++ <flags> s1.cc … s10.cc –o simple

If I change two of them?

Page 5: make: the good, the bad, and the ugly

Incremental Compilation

If I know which two I’ve changed, I can recompile them (into objects) and re-link the executable.

Figuring out the minimum number of steps that must be performed is what make is good at.

Page 6: make: the good, the bad, and the ugly

How Does Make Work?

You tell make what files your program depends on – some that you provide (the source) and some that the compiler provides (objects).

You tell make how to run the compiler, and finally how to assemble all those files into the program.

When things change, make decides what commands need to be run to bring your program up to date.

Page 7: make: the good, the bad, and the ugly

For the Technically Minded

Make constructs a dependency graph: what targets depend on what other

targets how do I construct a given target

When you invoke Make for a specific target, it visits the graph, performing the needed commands to produce the thing you asked for.

Page 8: make: the good, the bad, and the ugly

It’s not Just for Programs Anymore

Make isn’t just good for compiling programs – it’s good for figuring out what commands to run to perform some task.

Time permitting, we’ll give non-programming examples of make later.

Page 9: make: the good, the bad, and the ugly

Key Concepts: Makefile

Make needs instructions on how to decide what to do – by convention, these instructions are stored in a file called “Makefile”. It’s just a convention – the –f flag to

make will tell it to look at a specific file for it’s instructions.

Makefiles (regardless of their filename) have a specific format…

Page 10: make: the good, the bad, and the ugly

Basic Makefile Format

# comment linevariable-name = valuetarget: dependencies<TAB>directive

The <TAB> is critical – it can’t be spaces, it must be a tab. Emacs has a makefile mode and will warn you if it finds an obvious error.

Page 11: make: the good, the bad, and the ugly

Make Targets

The first part of a rule – the thing make is trying to make.

Generally (but not always) a file – a .o, for example.

Targets have a (possibly empty) list of dependencies – other targets that this target depends on.

Page 12: make: the good, the bad, and the ugly

Directives

The final part of a rule – tells make what command(s) to run to create this target.

Generally the compiler for whatever language you’re working in.

Page 13: make: the good, the bad, and the ugly

Variables

If you don’t know what a variable is, time to review CS5/10.

Make variables look a lot like variables in SH. Assignment: VARNAME=Value Reference: ${VARNAME}, or $

(VARNAME)

Page 14: make: the good, the bad, and the ugly

Makefile.ex1

# three rules to build simpleall: simplesimple: simple.o<TAB>g++ -W –w –Wall –Werror –pedantic \ -o simple simple.o

simple.o: simple.cc<TAB>g++ -W –w –Wall –Werror –pedantic \ -c -o simple.o simple.cc

Page 15: make: the good, the bad, and the ugly

Makefile.ex2

CPPFLAGS=-W –w –Wall –Werror –pedanticCXX=g++all: simplesimple: simple.o<TAB>${CXX} –o simple simple.osimple.o: simple.cc<TAB>${CXX} ${CPPFLAGS} –o simple.o

–c \ simple.cc

Page 16: make: the good, the bad, and the ugly

Implicit Rules & Their Variables

Make has a slew of implicit rules – for example, it “knows” how to turn a .cc file into a .o file without you telling it. To make these implicit rules flexible,

make uses a range of built-in variable names in them.

If you assign to these variables, make will insert those values into the rules.

Page 17: make: the good, the bad, and the ugly

Some Built In Variables

CC – the C compiler CFLAGS – flags for the C compiler CXX – the C++ compiler CPPFLAGS – any guesses? LD – the linker LDFLAGS – let’s not see the same

hands…

Page 18: make: the good, the bad, and the ugly

Makefile.ex3

CPPFLAGS=-W –w –Wall –Werror –pedantic

all: simple

Page 19: make: the good, the bad, and the ugly

Having Make Figure Out Dependencies

Makefile.ex3 only works for single file projects.

Real projects have more than one file, and those files have to be built in a specific order.

Make (with some help from the compiler) can figure out that order for you.

Page 20: make: the good, the bad, and the ugly

Makefile.ex4

CC=${CXX}SOURCE = simple.cc.depend:${SOURCE}<TAB>@set –e; $(CC) –MM ${CPPFLAGS} \ ${SOURCE} | \ sed ‘s/\($*\)\.o[ :]*/\1.o : /g’ \ > .depend; [ -s $@ ] || rm –f $@-include .depend

Page 21: make: the good, the bad, and the ugly

Say What?

If you really want to know how/why it works – I encourage you to go figure it out. Read the make manual Read the sed man page See if you can figure out what’s going

on.

Page 22: make: the good, the bad, and the ugly

Having Make Find The Source

Thanks to some nifty tricks built into (gnu) make – you often don’t even need to tell make what the source files are.

You might think you could do: SOURCE = *.cc

But that’s not what you want. What you want: SOURCE := $(wildcard *.cc)

Page 23: make: the good, the bad, and the ugly

Why Not SOURCE=*.cc?

The trouble with saying SOURCE = *.cc

Is that make doesn’t evaluate that wildcard during variable assignment, it will expand it when the variable is used in a target or command.

SOURCE := $(wildcard *.cc)

Page 24: make: the good, the bad, and the ugly

Two Forms of = ??

There are two different assignment operators in Make: = is a “deferred” assignment – it’s

evaluated when make is actually running commands.

:= is an “immediate” assignment – it’s evaluated when make is reading makefiles and deciding what to do.

the distinction is subtle, and can be confusing.

Page 25: make: the good, the bad, and the ugly

Next Step: Figuring out the Objects

Wouldn’t it be nice if we could tell make – “the list of objects is the list of source files, but replace .cc with .o” ?

We can, like this:

OBJS := $(patsubst %.cc,%.o,$(wildcard *.cc)) Or this:

OBJS = $(SOURCE:.cc=.o)

Page 26: make: the good, the bad, and the ugly

So What Do We End Up With?

CC=${CXX}CPPFLAGS=-w –W –Wall –Werror –pedanticCPPFLAGS += -gLDFLAGS =SOURCE := $(wildcard *.cc)OBJS := $(patsubst %.cc,%.o,$(wildcard *.cc))TARGET = simpleall : ${TARGET}${TARGET}: ${OBJS}.depend…

Page 27: make: the good, the bad, and the ugly

So What’s Not To Love?

Makefile syntax is ugly – especially the fact that TABs have to be TABs.

While make has been ported to many operating systems, it’s easy to write Makefiles that aren’t portable. That sed trick, for example, won’t work on

Windows. Many have tried to “fix” make – few of

those efforts have survived.

Page 28: make: the good, the bad, and the ugly

Learning More

% info make google for “make tutorial”