pushd not working in makefile
Asked Answered
F

3

27

I have the following rule in a makefile:

ninja:
    git clone git://github.com/martine/ninja.git
    pushd ninja
    pwd
    git checkout release
    ./configure.py --bootstrap
    popd

The idea is to download and build ninja automatically as a project dependency. Notice that the pwd command is just there to make sure that the directory was pushed. Here's the output it generates:

git clone git://github.com/martine/ninja.git
Cloning into 'ninja'...
remote: Counting objects: 8646, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 8646 (delta 0), reused 0 (delta 0), pack-reused 8642
Receiving objects: 100% (8646/8646), 1.88 MiB | 427.00 KiB/s, done.
Resolving deltas: 100% (6114/6114), done.
Checking connectivity... done.
pushd ninja
~/Desktop/core/ninja ~/Desktop/core
pwd
/Users/fratelli/Desktop/core
git checkout release
error: pathspec 'release' did not match any file(s) known to git.
make: *** [ninja] Error 1

As you can see the directory does get pushed into the stack, but pwd does not return the correct directory. That's also why the checkout fails afterwards. Any ideas how to fix this?

Fortis answered 30/8, 2015 at 23:37 Comment(4)
Can you test the following pushd ninja && pwd?Tasty
It works! It now fails on the ./configure line. It seems that it only changes the directory for the duration of the command. I'm guessing that a shell instance is created for every command line?Ingemar
This pushd ninja && git checkout release && ./configure.py --bootstrap works, but I guess it can get messy pretty fast...Ingemar
This is because each command runs in a "fresh" context so the pushd will not change the directory for following commands. Hence the workaround with chaining many commands in one.Godoy
J
28

Each line in a makefile target recipe is run in its own shell session. This doesn't affect most recipes as they operate in the directory they need to by default. When they don't do that and you need to use cd or pushd then you need to write the commands all on the same line or tell make that the lines are continued.

See Splitting Recipe Lines for more details and examples.

Jingo answered 31/8, 2015 at 0:0 Comment(0)
S
0

workaround:

  • \ at end of line in Makefile
  • make SHELL='bash -ex'
Struve answered 11/10, 2021 at 15:4 Comment(0)
H
0

Another workaround:

do_something:
    cd path/to/dir && \
    ...            && \
    cd $(CURDIR)   && \
    ...
Homeless answered 22/4 at 14:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.