如何为dist文件创建目录?

时间:2017-05-11 16:45:02

标签: gnu-make

这是我的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

有没有办法达到我想要的目的?

1 个答案:

答案 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。在确定是否存在时,不考虑仅订单的先决条件 应该制定目标,但如果确定要制造目标,那么 仅订购先决条件。