2014-02-11 37 views
6

我是新来make和Makefiles,但我正在尝试为我的下一个项目创建一个,并且遇到PATH问题。我不断收到错误:“没有这样的文件或目录”在Makefile中设置PATH的问题

我创建了一个名为test简单的目标,使用mocha运行了所有的考试。

Mocha作为本地节点模块安装,因此它的可执行文件位于./node_modules/.bin/mocha。我正在改变我的路径,如this make tutorial中所述,所以我可以将其称为mocha而不是键入完整路径,但似乎没有工作。

这是我到目前为止有:

export PATH := node_modules/.bin:$(PATH) 

test: 
    which mocha 
    mocha 

.PHONY: test 

当我运行make test我得到以下的输出:

which mocha 
node_modules/.bin/mocha 
mocha 
make: mocha: No such file or directory 
make: *** [test] Error 1 

正如你可以从输出中看到,which mocha正确打印路径mocha可执行文件,但是当我只是运行mocha时,它找不到它。

我在做什么错?是否有关于我失踪的Makefiles中的变量作用域或持久性的更多信息?

P.S.如果它很重要,我使用Mac和XCode开发人员工具附带的make版本。这是我所得到的,当我运行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 
+0

这很奇怪。如果删除'export PATH:= node_modules/.bin:$( PATH)'并运行make,如下所示:$ PATH = node_modules/.bin:$ PATH make test工作正常吗? –

+0

是的,如果我这样做,工作得很好。 –

回答

5

(使用GNU使GNU/Linux系统上3.81),我无法重现你的结果。看起来苹果系统的工作方式可能会有所不同,或者苹果已经为他们发布的GNU make版本提供了某种补丁,导致了这个问题。

GNU make有两种运行配方的方式:调用shell并将配方传递给shell以运行的正常方式,以及“快速路径”,其中如果发现命令是“简单“(即如果它不包含shell特殊字符),它会将命令分割成单词并直接执行命令而不调用shell。后者要快得多,但由于它是直接调用的,它继承了GNU的PATH设置,而不是从shell中自行设置。

似乎由于某些原因,Apple发布的GNU make版本无法正常工作,因为它没有正确地为通过“快速路径”由GNU make直接运行的命令设置环境。

我有一个非常模糊的回忆,就像在GNU make邮件列表上讨论的那样,但花了一些时间搜索后,我无法想出任何东西。

通过引入一些shell特殊字符(globbing,;,管道等),您可以通过强制您的命令使用慢速路径来“解决”此问题。或者您可以使用程序的完全合格路径。或者,你可以去获取GNU make的源代码并自己构建它;如果这种差异是苹果“修复”的结果,应该使它工作得更好。或者从自制软件或者端口安装GNU make,这也将为你带来更多功能的更新版本,我期望。

+0

是的,如果我使用完整路径,这是奇怪的部分,它确实有效。是的,如果我将该代码放入文件并运行它,它的确行得通。如果你能在Linux上工作,也许这是一个mac事情。 –

+0

我觉得这很奇怪。如果你有倾向性,你可以尝试安装直接的GNU make,可以自己构建(很简单),也可以通过MacPort或Brew来安装。我想知道苹果是否可以“帮助”修补他们的GNU make版本,以某种方式破坏事情。 – MadScientist

+2

另一件要检查的事情是改变你对'mocha'的调用,看起来像这样:':; mocha'。这样做会绕过GNU make的快速路径处理并强制它调用一个shell。如果这样做的话,那么我更怀疑苹果版本的GNU make有什么奇怪的地方。 – MadScientist

0

恐怕you can't do that 尝试用 “局部” 变量,而不是

NODE_MODULES := node_modules/.bin 

test: 
    @ $(NODE_MODULES)/mocha 
+0

那么,根据我读过的文章,你可以做到这一点。而且由于'哪个mocha'正在工作,看起来它*确实*适用于该行。另外,如果我打印出PATH变量,它确实包含了node_modules位,但也许这只是作用于make子进程的范围,我不知道。 –

+3

链接的SO问题与此不相关。确实,子流程不能修改其父母的环境,但这不是这里发生的事情。这个问题是问如何让makefile修改调用者的环境。这个问题完全不同:它想修改儿童的环境,这是完全合理的,并得到支持。 – MadScientist

+0

我看到了,如果您认为它可能会误导未来的读者,我准备将其删除。 –

8

在OSX你还需要还set SHELL

PATH := node_modules/.bin:$(PATH) 
SHELL := /bin/bash 
2

这应该工作:

PATH := $(PATH):$(PWD)/node_modules/.bin 
SHELL := env PATH=$(PATH) /bin/bash 
+0

如果不是PATH值的双引号,它几乎可以工作。引号在Makefile赋值中没有特殊的含义,所以它们被简单地预置并附加到PATH中,有效地屏蔽了第一个和最后一个值(除非有一个名为“node_modules/.bin”的目录) – Steven