Search code examples
makefilegnu-make

make --dry-run: how can it execute things that are supposed not to be executed?


If you call make with the option --dry-run, it prints the commands that would be executed without executing them. If you want it to work recursively, you can replace any internal make call by $(MAKE).

So my question is, even in this case: if make -n won't execute any body of any rule, how can it execute things that happens inside such body rules that are not supposed to be executed?

Consider, for instance, the following (made up) example:

FOLDERS = path1 path2 path3

all:
   for T in $(FOLDERS); cd ./$$T; $(MAKE) -s; cd ../; done;

NOTE: Yes, I know, there are probably more elegant ways to do it.

How is it possible that these three calls to make are "executed" if executing them implies to execute the body of all, which is not supposed to be executed? Are all body of all rules "falsely" executed or something? How does, executing-and-not-executing is implemented here?


Solution

  • There are exceptions named in the GNU make manual for when it does execute commands even when -n (aka dry run) is specified:

    9.3 Instead of Executing Recipes
    -n
    “No-op”. Causes make to print the recipes that are needed to make the targets up to date, but not actually execute them. Note that some recipes are still executed, even with this flag (see How the MAKE Variable Works). Also any recipes needed to update included makefiles are still executed (see How Makefiles Are Remade).

    5.7.1 How the MAKE Variable Works
    As a special feature, using the variable MAKE in the recipe of a rule alters the effects of the ‘-t’ (‘--touch’), ‘-n’ (‘--just-print’), or ‘-q’ (‘--question’) option. Using the MAKE variable has the same effect as using a ‘+’ character at the beginning of the recipe line. See Instead of Executing the Recipes. This special feature is only enabled if the MAKE variable appears directly in the recipe: it does not apply if the MAKE variable is referenced through expansion of another variable. In the latter case you must use the ‘+’ token to get these special effects.

    Since your all target references $(MAKE) directly, the commands are invoked.