I'm reading a book about the make
command and there is a paragraph:
If any of the prerequisites has an associated rule, make attempts to
update those first. Next, the target file is considered. If any
prerequisite is newer than the target, the target is remade by
executing the commands. Each command line is passed to the shell and
is executed in its own subshell.
Could you explain the concept of subshell used there and why is it necessary to use such a subshell?
Best Answer
make(1)
itself does not know how to run shell commands. It could have been made to do so, but the Unix Way is to have well-separated concerns:make(1)
knows how to build dependency graphs that determine what has to be made, andsh(1)
knows how to run commands.The point the author is trying to make there is that you must not write those command lines such that a later one depends on a former one, except through the filesystem. For example, this won't work:
If this were a two-line shell script, the first command's output would be passed as an argument to the second command. But since each of these commands gets run in a separate sub-shell, the
$foo
variable's value gets lost after the first sub-shell exists, so there is nothing to pass to the first.One way around this, as hinted above, is to use the filesystem:
That stores the output of the first command in a persistent location so the second command can load the value up.
Another thing that trips
make(1)
newbies up sometimes is that constructs that are usually broken up into multiple lines for readability in a shell script have to be written on a single line or wrapped up into an external shell script when you do them in aMakefile
. Loops are a good example; this doesn't work:You have to use semicolons to get everything onto a single line instead:
For myself, whenever doing that gives me a command line longer than 80 characters or so, I move it into an external shell script so it's readable.