Commands executed by make inherit their processing environment from make itself. This environment includes the current working directory, file descriptors, and the environment variables passed by make .
When a subshell is created, make adds a few variables to the environment:
MAKEFLAGS MFLAGS MAKELEVEL
The MAKEFLAGS variable includes the command-line options passed to make . The MFLAGS variable mirrors MAKEFLAGS and exists for historical reasons. The MAKELEVEL variable indicates the number of nested make invocations. That is, when make recursively invokes make , the MAKELEVEL variable increases by one. Subprocesses of a single parent make will have a MAKELEVEL of one. These variables are typically used for managing recursive make . We'll discuss them in the Section 6.1 in Chapter 6.
Of course, the user can add whatever variables they like to the subprocess environment with the use of the export directive.
The current working directory for an executed command is the working directory of the parent make . This is typically the same as the directory the make program was executed from, but can be changed with the the --directory=<replaceable>directory</ replaceable > (or -C ) command-line option. Note that simply specifying a different makefile using ”file does not change the current directory, only the makefile read.
Each subprocess make spawns inherits the three standard file descriptors: stdin , stdout , and stderr . This is not particularly noteworthy except to observe that it is possible for a command script to read its stdin . This is "reasonable" and works. Once the script completes its read, the remaining commands are executed as expected. But makefile s are generally expected to run without this kind of interaction. Users often expect to be able to start a make and "walk away" from the process, returning later to examine the results. Of course, reading the stdin will also tend to interact poorly with cron -based automated builds.
A common error in makefile s is to read the stdin accidentally :
$(DATA_FILE): $(RAW_DATA) grep pattern $(RAW_DATA_FILES) > $@
Here the input file to grep is specified with a variable ( misspelled in this example). If the variable expands to nothing, the grep is left to read the stdin with no prompt or indication of why the make is "hanging." A simple way around this issue is to always include /dev/null on the command line as an additional "file":
$(DATA_FILE): $(RAW_DATA) grep pattern $(RAW_DATA_FILES) /dev/null > $@
This grep command will never attempt to read stdin . Of course, debugging the makefile is also appropriate!