这是我的Makefile:
dist/%.js: src/%.js node_modules
$(NM)/babel $< -o $@
build: $(patsubst src/%,dist/%,$(wildcard src/**/*.js))
它运行如下命令:
node_modules/.bin/babel src/deep/foo.js -o dist/deep/foo.js
问题是,如果dist/deep
不存在,则会出错:
错误:ENOENT:没有这样的文件或目录,打开'dist / deep / foo.js'
所以我想要做的是在目录上添加一个额外的依赖项,我希望我可以用这样的东西:
dist/%.js: src/%.js $(dir dist/%) node_modules
$(NM)/babel $< -o $@
dist/%/:
mkdir -p $@
build: $(patsubst src/%,dist/%,$(wildcard src/**/*.js))
但它不起作用。 $(dir dist/%)
并不像我希望的那样%
。运行make --trace
会产生:
Makefile:10: update target 'dist/deep/foo.js' due to: src/deep/foo.js dist/ node_modules
即,你可以看到它依赖于dist/
,但我希望它依赖于dist/deep/
,这样我才能mkdir -p
。
有没有办法达到我想要的目的?
答案 0 :(得分:1)
首先是一个附属障碍。来自:
$(wildcard src/**/*.js)
似乎你希望这个函数执行递归通配,
返回*.js
或任何子目录中存在的所有src
个文件
物。
我不知道你有什么外壳,但他们并不都是这样做的
默认。虽然从bash
4.0开始,但linux bash
shell没有
如果设置了shell选项globstar
,它就会这样做。
无论如何,$(wildcard ...)
不会这样做(除非,可能是
有效的shell默认情况下会这样做,我无法做到这一点
查看)。所以你不能可靠地使用$(wildcard ...)
目的。您需要make
来调用递归的shell
启用**
globbing,然后调用:
$(shell ls src/**/*.js)
这就是我现在要做的就是如何解决你的问题 一个简单的例子。我有:
src/
one.js
a/
two.js
c/
four.js
b/
three.js
我只想将每个*.js
文件从src
下方复制到。{
dist
下的相对相对名称,确保dist
和所有
必要时存在必要的子目录。 (当然,这个
可以用cp
)一次完成。这是一个makefile:
SHELL := /bin/bash
.SHELLFLAGS := -O globstar -c
SRCS := $(shell ls src/**/*.js)
DISTS := $(patsubst src/%,dist/%,$(SRCS))
DESTDIRS := $(dir $(DISTS))
.PHONY: all clean
all: $(DISTS)
dist/%.js: src/%.js | $(DESTDIRS)
cp $< $@
$(DESTDIRS):
mkdir -p $@
clean:
rm -fr dist
的运行方式如下:
$ make
mkdir -p dist/a/c/
mkdir -p dist/b/
cp src/a/c/four.js dist/a/c/four.js
cp src/a/two.js dist/a/two.js
cp src/b/three.js dist/b/three.js
cp src/one.js dist/one.js
在那个makefile中,
| $(DESTDIRS)
使每个$(DESTDIRS)
成为order-only prerequisite
任何目标dist/%.js
。在确定是否存在时,不考虑仅订单的先决条件
应该制定目标,但如果确定要制造目标,那么
仅订购先决条件。