How I could add dir to $PATH in Makefile?

LinuxMakefile

Linux Problem Overview


I want to write a Makefile which would run tests. Test are in a directory './tests' and executable files to be tested are in the directory './bin'.

When I run the tests, they don't see the exec files, as the directory ./bin is not in the $PATH.

When I do something like this:

EXPORT PATH=bin:$PATH
make test

everything works. However I need to change the $PATH in the Makefile.

Simple Makefile content:

test all:
    PATH=bin:${PATH}
    @echo $(PATH)
    x

It prints the path correctly, however it doesn't find the file x.

When I do this manually:

$ export PATH=bin:$PATH
$ x

everything is OK then.

How could I change the $PATH in the Makefile?

Linux Solutions


Solution 1 - Linux

Did you try export directive of Make itself (assuming that you use GNU Make)?

export PATH := bin:$(PATH)

test all:
    x

Also, there is a bug in you example:

test all:
    PATH=bin:${PATH}
    @echo $(PATH)
    x

First, the value being echoed is an expansion of PATH variable performed by Make, not the shell. If it prints the expected value then, I guess, you've set PATH variable somewhere earlier in your Makefile, or in a shell that invoked Make. To prevent such behavior you should escape dollars:

test all:
    PATH=bin:$$PATH
    @echo $$PATH
    x

Second, in any case this won't work because Make executes each line of the recipe in a separate shell. This can be changed by writing the recipe in a single line:

test all:
    export PATH=bin:$$PATH; echo $$PATH; x

Solution 2 - Linux

By design make parser executes lines in a separate shell invocations, that's why changing variable (e.g. PATH) in one line, the change may not be applied for the next lines (see this post).

One way to workaround this problem, is to convert multiple commands into a single line (separated by ;), or use One Shell special target (.ONESHELL, as of GNU Make 3.82).

Alternatively you can provide PATH variable at the time when shell is invoked. For example:

PATH  := $(PATH):$(PWD)/bin:/my/other/path
SHELL := env PATH=$(PATH) /bin/bash

Solution 3 - Linux

Path changes appear to be persistent if you set the SHELL variable in your makefile first:

SHELL := /bin/bash
PATH := bin:$(PATH)

test all:
    x

I don't know if this is desired behavior or not.

Solution 4 - Linux

What I usually do is supply the path to the executable explicitly:

EXE=./bin/
...
test all:
    $(EXE)x

I also use this technique to run non-native binaries under an emulator like QEMU if I'm cross compiling:

EXE = qemu-mips ./bin/

If make is using the sh shell, this should work:

test all:
    PATH=bin:$PATH x

Solution 5 - Linux

To set the PATH variable, within the Makefile only, use something like:

PATH := $(PATH):/my/dir

test:
@echo my new PATH = $(PATH)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSzymon LipińskiView Question on Stackoverflow
Solution 1 - LinuxEldar AbusalimovView Answer on Stackoverflow
Solution 2 - LinuxkenorbView Answer on Stackoverflow
Solution 3 - LinuxunderspecifiedView Answer on Stackoverflow
Solution 4 - LinuxRichard PenningtonView Answer on Stackoverflow
Solution 5 - LinuxkarnhickView Answer on Stackoverflow