How to enter a parent directory in Makefile?

2019-08-12 12:08发布

问题:

I've got the following Makefile (GNU Make 3.81):

CWD:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

all:
        pwd
        cd "$(CWD)/.."
        pwd
        cd ".."
        pwd

Here is the output:

$ make
pwd
/Users/kenorb/temp/foo
cd "/Users/kenorb/temp/foo/.."
pwd
/Users/kenorb/temp/foo
cd ".."
pwd
/Users/kenorb/temp/foo

It seems that cd'ing to parent directory via .. doesn't take any effect.

How do I change the current working directory to a parent directory relatively to Makefile file?

回答1:

This issue has to do with the fact that each line of a rule's recipe is executed in a dedicated shell instance (i.e.: a new process). So, running cd in one line, won't have any effect for a command in another line, because these commands are executed by different processes.

Changing the working directory for a recipe

You can either use .ONESHELL (GNU Make 3.82 or later) to run all the recipe's lines in a single and the same shell instance:

CWD:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

.ONESHELL:
all:
        pwd
        cd "$(CWD)/.."
        pwd
        cd ".."
        pwd

or just keep all the commands in a single line:

CWD:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

all:
        pwd; cd "$(CWD)/.."; pwd; cd ".."; pwd

The change of the working directory takes effect only inside that recipe.


Note that changing the current working directory inside the makefile for the shell that invoked make is not possible, since that's a process' property, and the running make instance that will execute cd is another (sub)process. Therefore, it will only change the working directory of that subprocess.

That is the same reason you cannot change the working directory of a shell by executing a script without sourcing it: because the script runs in a new shell instance (i.e.: a subprocess).