2014-02-11 40 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