在Makefile中设置路径时出现问题

在Makefile中设置路径时出现问题,makefile,Makefile,我不熟悉制作和制作文件,但我正试图为我的下一个项目创建一个,我遇到了路径问题。我不断收到错误:“没有这样的文件或目录” 我创建了一个名为test的简单目标,它使用 Mocha作为本地节点模块安装,因此其可执行文件可在/node\u modules/.bin/Mocha中找到。我正在更改中所述的路径,以便将其称为mocha,而不是键入完整路径,但似乎有些东西不起作用 以下是我目前掌握的情况: export PATH := node_modules/.bin:$(PATH) test: w

我不熟悉制作和制作文件,但我正试图为我的下一个项目创建一个,我遇到了路径问题。我不断收到错误:“没有这样的文件或目录”

我创建了一个名为
test
的简单目标,它使用

Mocha作为本地节点模块安装,因此其可执行文件可在
/node\u modules/.bin/Mocha
中找到。我正在更改中所述的路径,以便将其称为
mocha
,而不是键入完整路径,但似乎有些东西不起作用

以下是我目前掌握的情况:

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

test:
    which mocha
    mocha

.PHONY: test
当我运行
maketest
时,我得到以下输出:

which mocha
node_modules/.bin/mocha
mocha
make: mocha: No such file or directory
make: *** [test] Error 1
正如您可以从输出中看到的,
哪个mocha
正确地打印了mocha可执行文件的路径,但是当我简单地运行
mocha
时,它找不到它

我做错了什么?关于makefile中的变量范围或持久性,是否有我遗漏的更大的图景

如果这很重要的话,我正在使用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

我无法复制您的结果(在GNU/Linux系统上使用GNU make 3.81)。看来,苹果系统的工作方式可能会有一些不同,或者苹果已经对他们提供的GNU make版本进行了某种修补,导致了这个问题

GNU make有两种运行配方的方法:普通方法,它调用一个shell并将配方传递给要运行的shell;以及“快速路径”,如果make看到命令“足够简单”(即如果它不包含shell特殊字符),它将把命令切碎成单词,直接执行命令而不调用shell。后者的速度要快得多,但由于直接调用它,因此它从GNU继承了
PATH
设置,而不是从shell继承

似乎出于某种原因,苹果提供的GNU make版本无法正常工作,因为它没有为GNU make通过“快速路径”直接运行的命令正确设置环境

我有一个非常模糊的回忆,像这样的事情正在讨论的GNU制作邮件列表,但在花了一些时间搜索后,我无法拿出任何东西

通过强制命令使用慢路径,引入一些shell特殊字符(globbing、
、管道等),可以“修复”此问题。也可以使用程序的完全限定路径

或者,你可以去获取GNUMake的源代码并自己构建它;如果这种差异是苹果公司“修复”的结果,那么应该会使它工作得更好。或者使用自制软件或端口安装GNU make,我想这也会为您带来一个具有更多功能的更新版本。

恐怕 尝试使用“局部”变量

NODE_MODULES := node_modules/.bin

test:
    @ $(NODE_MODULES)/mocha

在OSX中,您还需要:

这应该起作用:

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

我在Ubuntu 16.04.4上使用GNU make版本4.1

我也有类似的问题,建议的解决方案都不适合我

当以后进行变量设置时,
PATH
的设置似乎不起作用(至少在本版本的
make

对我来说,有效的解决方案是将早期的
PATH
设置显式地注入用于分配后期make变量的特定子shell中,如下所示:

VW = $(shell env PATH=$(PATH) which vw)
下面的
Makefile
示例演示了有效与无效的情况:

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)'"
再现问题和解决方案:

$ make --version| head -1
GNU Make 4.1

$ make
# -- Doesn't work:
VW_NOT_OK=''
# -- Works:
VW_OK='/usr/local/bin/vw'

根据我读到的文章,你可以做到。既然哪种摩卡咖啡有效,看来它确实适用于那条生产线。另外,如果我打印出PATH变量,它确实包含node_modules位,尽管我不知道这可能只适用于make子进程。链接的SO问题与这个问题无关。的确,子进程不能修改其父进程的环境,但这里并不是这样。这个问题是询问如何让makefile修改其调用者的环境。这个问题是完全不同的:它想要改变它的儿童环境,这是完全合理和受支持的。我明白了,如果你认为它可能误导未来的读者,我准备删除它。是的,如果我使用完整的路径,它确实有效,这是一个奇怪的部分。是的,如果我把代码放进一个文件并运行它,它确实可以工作。如果你能让它在Linux上运行的话,也许它是mac的东西。我觉得这非常奇怪。如果您有兴趣,您可以尝试安装Direct GNU make,可以自己构建(很容易),也可以通过MacPorts或Brew。我想知道苹果是否以某种方式“有益地”修补了他们版本的GNU make,这是一种破坏。另一件需要检查的事情是将您对
摩卡的调用更改为如下所示:
:;摩卡咖啡
。这样做将绕过GNUMake的快速路径处理,并迫使它调用shell。如果这能起作用,那么我更怀疑苹果版GNU make有什么奇怪的地方。它不是一个单一的命令。这是一个简单的命令。为了提高效率,gnumake有一个“快速路径”,它检查要调用的命令,如果其中没有“特殊字符”(定义为需要shell处理的字符),那么它直接调用命令,而不是启动shell。当您使用
/test/*
时,您使用的是需要shell的特殊字符(
*
,用于globbing),就像我使用
时一样。不知何故,苹果版本的GNU make没有设置本地
PATH
环境变量,它只是在子流程中设置
PATH
。如果这个答案更容易找到,那就太好了。我费了一段时间才弄明白为什么导出的
路径
不适用于某些食谱,而适用于其他食谱。责备是微不足道的
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)'"
$ make --version| head -1
GNU Make 4.1

$ make
# -- Doesn't work:
VW_NOT_OK=''
# -- Works:
VW_OK='/usr/local/bin/vw'