Difference between revisions of "Make"
Line 80: | Line 80: | ||
Before we leave this example, there are two more rules to look at—the ‘clean’ and ‘spotless’ rules. These tidy up any files we created using the makefile. It is good practice, and rather handy, to write these rules. They both have the questionable distinction of being designated ‘PHONY’. This indicates that the targets do not refer to a real file. We call these rules by name, i.e. ‘make clean’, or ‘make spotless’, and since the targets don’t exist, the actions will always be triggered. | Before we leave this example, there are two more rules to look at—the ‘clean’ and ‘spotless’ rules. These tidy up any files we created using the makefile. It is good practice, and rather handy, to write these rules. They both have the questionable distinction of being designated ‘PHONY’. This indicates that the targets do not refer to a real file. We call these rules by name, i.e. ‘make clean’, or ‘make spotless’, and since the targets don’t exist, the actions will always be triggered. | ||
− | ==More Files, I Say, More Files== | + | ==More Files, I Say, More Files!== |
Variables, multiple dependencies. | Variables, multiple dependencies. |
Revision as of 09:47, 9 October 2007
Introduction to Make
We will explore the wonderous world of make using a number of examples. To get your copy of the examples, from their version control repository, simply type:
svn co http://source.ggy.bris.ac.uk/subversion/intro-to-make/trunk ./intro-to-make
Hello World
Without further ado, let's meet our first example:
cd intro-to-make/examples/example1
List the files:
Makefile, hello_world.c
and type:
make
Tada! We've successfully cleared the first and biggest hurdle--automating the (OK modest:) compilation task for hello_world.exe. Now try running it:
./hello_world.exe
We can remove unwanted intermediate object files by typing:
make clean
Or clean up the directory completely using:
make spotless
Well, you'll be pleased to know that the worst bit is over--we've used make to compile our program, and even tidied up after ourselves. From here on in, we’ll use our first makefile as a foundation and just expand the scope of what we can do.
Key Concepts: Rules, Targets and Dependencies
Makefiles are composed of rules and variables. We will see some variables soon. For now, let’s look at rules. A rule in a makefile has the general form:
Target : dependencies Actions
Note the tab at the start of the actions lines. You need one. Don't ask, don't ask. It’s just the way it is!
A rule can have many dependencies and more than one action.
A rule will trigger if the dependencies are satisfied and they are ‘newer’ than the target. If the rule is triggered, the actions will be performed. This all sounds rather abstract, so let’s consider something more concrete. Take a look at the contents of Makefile in our example. In particular, the rule:
hello_world.o : hello_world.c gcc –c hello_world.c –o hello_world.o
So, our target here is hello_world.o, our dependency is hello_world.c and our action is to use gcc to create an object file from the source code. Our dependency is satisfied, since the file hello_world.c exists. The file hello_world.o does not exist. In this case the rule will trigger and compilation action will be performed. If the file hello_world.o did exist, make would compare the date-stamps for hello_world.o and hello_world.c. If the source code proved to be newer than object code, the file hello_world.o would be updated using the specified action.
We see a similar pattern in the rule:
all : hello_world.o gcc hello_world.o –o hello_world.exe
In this rule, however, there is—and never will be—a file called ‘all’. When this is the case, the rule will always trigger.
When calling make in its default mode, it will look for a file called Makefile (or makefile) in the current directory and start reading it from the top down. It will read down until it finds the first rule and look to see if the dependencies are satisfied. If the dependencies are not satisfied, it will look for a rule, with a target matching the missing dependency, and so on. In this way, make chains down a sequence of rules until it finds a satisfied dependency and then wind back up to its starting point, performing the specified actions along the way.
For our simple makefile, the ‘all’ rule is first. The dependency is unsatisfied, but there is a rule with hello_world.o as a target. The dependency on this second rule is satisfied (the file hello_world.c exists). The associated action is performed, and hello_world.o is created. Winding back up the chain, the ‘all’ rule can now trigger, and hello_world.exe is created. Hurrah!
Before we leave this example, there are two more rules to look at—the ‘clean’ and ‘spotless’ rules. These tidy up any files we created using the makefile. It is good practice, and rather handy, to write these rules. They both have the questionable distinction of being designated ‘PHONY’. This indicates that the targets do not refer to a real file. We call these rules by name, i.e. ‘make clean’, or ‘make spotless’, and since the targets don’t exist, the actions will always be triggered.
More Files, I Say, More Files!
Variables, multiple dependencies.
Try touch.