makefilegnu-makeparallel-builds

Makefile: why always use `$(MAKE)` instead of `make`?


I usually use a high level build system like cmake for building my C/C++ code. But for various reasons I am using straight GNU make.

I am doing recursive build where each directory has a makefile.

I recently had to change all my makefiles from using make to $(MAKE) and then parallel builds started working.

The literature I've read all say "always use $(MAKE)" (O'Reilly book, 5+ solutions on stackoverflow.com from people with greater than 10-40K points).

In your makefiles, why always use $(MAKE) instead of make?

(obviously ONE reason is because $(MAKE) somehow enables parallel builds.)

Is there more happening than simple substitution of $(MAKE) with make?


Solution

  • Matthieu's answer is correct, but not complete.

    The best thing to do is read the GNU make manual section related to using the MAKE variable.

    In addition to using the correct make executable (which is reason enough), GNU make attempts to understand which recipes invoke recursive instances of make. Any recipe that does so is treated specially in a few ways:

    First, that recipe is invoked even if you run make -n, make -q, or make -t.

    Second, in order to communicate with its sub-makes (for example, to allow the jobserver to work properly) make maintains a set of open file descriptors (for pipes). For "normal" (non-recursive) recipes make will close those file descriptors before spawning the recipe (so that (a) recipes can't accidentally mess up that communication, and (b) because some programs / scripts are written to expect specific file descriptors are unused). For recipes that are determined to be recursive invocations, make will not close those file descriptors.

    GNU make uses two different ways to detect whether a recipe is a recursive make, or not. One of them is that you can add the + special character to the beginning of the recipe. The second is the presence of the $(MAKE) (or ${MAKE}) variable references in the recipe.