这是我的制作文件:
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
它。
有没有办法实现我想要的?
首先是子公司的障碍。从以下方面来看:
$(wildcard src/**/*.js)
似乎您希望此函数执行递归通配, 返回src
或任何子目录中存在的所有*.js
文件 其中。
我不知道你有什么外壳,但他们并不都这样做 违约。linuxbash
shell没有,尽管从bash
4.0开始 如果设置了外壳选项globstar
,它将执行此操作。
无论如何,$(wildcard ...)
不会这样做(除非,可能, 操作外壳默认这样做,我无法做到这一点 结帐)。所以你不能可靠地使用$(wildcard ...)
目的。你需要make
调用一个递归的 shell。 启用通配**
,然后调用:
$(shell ls src/**/*.js)
这就是我现在要做的,展示如何解决你的问题 一个简单的例子。我有:
src/
one.js
a/
two.js
c/
four.js
b/
three.js
我只想将每个*.js
文件从下面复制到src
dist
下相同的相对名称,确保dist
和所有 必要时存在必要的子目录。(当然,这个 所有这些都可以用cp
一次完成)。下面是一个生成文件:
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
在该生成文件中,
| $(DESTDIRS)
使每个$(DESTDIRS)
都成为仅限订单的先决条件 任何目标dist/%.js
.在确定其是否 应该制定目标,但如果确定要制定目标,那么 将首先满足仅订单先决条件。