yet another makefile tutorial

You’re so lucky to visit my yet another Makefile tutorial because there are so many tutorials about Makefile on the Internet that it is almost impossible for my post to standout in google’s search result. But I bet you are still confused about the logic of Makefile. Yes, the basic idea of Makefile is simple: execute the recipe if any of the modification time of prerequisites is newer than target. However, in reality, you will find strange usage about the target, prerequisite, recipe, and rule. The basic idea of Makefile is based on the assumption of files for targets and prerequisites. The reality is much more complicated.

Consider a simple example:

first:second
  echo aa

Suppose there is a file “first” and a file “second” in current directory and second is older than first. The output of Make is:

mingw32-make
mingw32-make: ‘first’ is up to date.

The echo command is not executed, which is what we expect. Since second is an existing file, make won’t complain about “*** No rule to make target ‘second’, needed by ‘first’.  Stop.” Now delete second and run make, you will see the error message. Now add a new rule without prerequisite and recipe:

first:second
  echo aa
second:

What do you think about the output? Does it complain “*** No rule to make target ‘second’, needed by ‘first’? No, even second does not exist now, there exists a rule for second so run that rule. A rule without prerequisite or recipe and the target is a nonexistent file tells make that the target has been made and updated to the latest time. Now first is older than second and the recipe for the first rule is run which echos aa.

Now create file second again and touch first to make first newer than second. Run make and observe what happens. Do you think make will echo aa? No, the output is:

mingw32-make: ‘first’ is up to date.

It turns out the existence of file takes precedent over the rule. But Make also checks(runs) the second rule. Don’t believe it? Consider the following example:

first:second
  echo aa
second:FORCE

It will display:

mingw32-make: *** No rule to make target ‘FORCE’, needed by ‘second’.  Stop.

which means the second rule is being checked(run). How about the following Makefile:

first:second
  echo aa
second:FORCE
  echo bb
FORCE:

Since second exists and older than first, does make do nothing? No, actually, since the second rule is checked and the check result is to run its recipe, the output is echo bb. Of course the recipe of the first rule is still not executed.

If a rule has a non-existent target and has no prerequisite, the target is considered out of date and need to run its recipe to update it.

So

first:second
  echo aa
second:FORCE
  echo bb
FORCE:
  echo cc

will output:

echo cc
cc
echo bb
bb

If a rule has an existing file target and has no prerequisite, the target is considered to be up to date and does not need to to updated by running its recipe. So if you create a file FORCE, the output would be

echo bb
bb

The logic is confusing here because there are many combinations about whether the target exists or not, whether the prerequisite exists or not, whether the recipe exists or not. You can get it clear by remember one rule: if the target is not an existing file, update it (updating does not mean creating a file)anyway to the latest time, which means running the possible recipe from possible prerequisites.

 

 

Leave a Reply