Reputation: 30431
I'm new to make and Makefiles, but I'm trying to create one for my next project and I'm running into PATH issues. I keep getting the error: "No such file or directory"
I've created a simple target called test
that runs all my tests using mocha.
Mocha is installed as a local node module, so its executable can be found at ./node_modules/.bin/mocha
. I'm altering my PATH as described in this make tutorial so I can refer to it as mocha
instead of typing the full path, but something doesn't seem to be working.
Here's what I have so far:
export PATH := node_modules/.bin:$(PATH)
test:
which mocha
mocha
.PHONY: test
When I run make test
I get the following output:
which mocha
node_modules/.bin/mocha
mocha
make: mocha: No such file or directory
make: *** [test] Error 1
As you can see from the output, which mocha
is correctly printing the path to the mocha executable, but when I simply run mocha
, it can't find it.
What am I doing wrong? Is there bigger picture about variable scope or persistence in Makefiles that I'm missing?
P.S. If it's important, I'm using a Mac and the version of make that comes with the XCode developer tools. This is what I get when I run make -v
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for i386-apple-darwin11.3.0
Upvotes: 13
Views: 14238
Reputation: 5952
I'm using GNU make version 4.1 on Ubuntu 16.04.4
I had a similar issue and none of the suggested solutions worked for me.
Settings to PATH
do not seem to be in effect when later variable settings take place (at least in this version of make
).
export PATH := /usr/local/bin:/bin:/usr/bin
# Path setting is not in effect here, 'which' returns an empty string
# even when 'vw' is installed in /usr/local/bin/vw
VW = $(which vw)
The solution that worked for me was to inject the earlier PATH
setting explicitly into the particular sub-shell used to assign a later make variable, like this:
VW = $(shell env PATH=$(PATH) which vw)
The following Makefile
example demonstrates the case that works vs the one that doesn't:
SHELL := /bin/bash
export PATH := /usr/local/bin:/bin:/usr/bin
# Expecting 'vw' to be found, due to PATH setting above
# ('vw' is in /usr/local/bin/vw)
VW_NOT_OK = $(which vw)
VW_OK = $(shell env PATH=$(PATH) which vw)
all:
# -- Doesn't work:
@echo "VW_NOT_OK='$(VW_NOT_OK)'"
# -- Works:
@echo "VW_OK='$(VW_OK)'"
Reproducing the problem and solution:
$ make --version| head -1
GNU Make 4.1
$ make
# -- Doesn't work:
VW_NOT_OK=''
# -- Works:
VW_OK='/usr/local/bin/vw'
Upvotes: 3
Reputation: 166319
This should work:
PATH := $(PATH):$(PWD)/node_modules/.bin
SHELL := env PATH=$(PATH) /bin/bash
Upvotes: 2
Reputation: 718
In OSX you also need to also set SHELL:
PATH := node_modules/.bin:$(PATH)
SHELL := /bin/bash
Upvotes: 13
Reputation: 100781
I can't reproduce your results (using GNU make 3.81 on a GNU/Linux system). It appears that there may be some difference in either the way the Apple system works, or that Apple has made some kind of patch to the GNU make version they ship that is causing this problem.
GNU make has two ways of running recipes: the normal way, where it invokes a shell and passes the recipe to the shell to be run, and the "fast path", where, if make sees that the command is "simple enough" (that is if it contains no shell special characters), it will chop up the command into words and directly execute the command without invoking the shell. The latter is much faster, but since it's being invoked directly it inherits the PATH
setting from GNU make itself not from the shell.
It appears that for some reason the version of GNU make shipped by Apple is not working properly in that it's not setting the environment correctly for commands which are run directly by GNU make, via the "fast path".
I have a very vague recollection of something like this being discussed on the GNU make mailing lists, but after spending some time searching I wasn't able to come up with anything.
You can "fix" this problem by forcing your command to use the slow path, by introducing some shell special characters (globbing, ;
, pipes, etc.). Or you can use a fully-qualified path to the program.
Or, you can go get the source code for GNU make and build it yourself; if this difference is a result of a "fix" by Apple that should make it work better. Or install GNU make from homebrew or ports, which will also get you a newer version with more features, I expect.
Upvotes: 12
Reputation: 674
I am afraid that you can't do that Try with "local" variables instead
NODE_MODULES := node_modules/.bin
test:
@ $(NODE_MODULES)/mocha
Upvotes: 0