我是新来的,来自npm。我正在尝试将它们结合使用,效果非常好。只有make似乎认为它每次都需要运行某个npm命令,但目标文件在那里并保持不变。
我在git中有一个项目的网站。该网站有一个这个项目的git子模块,名为npm。唯一重要的是,我需要在该目录中构建一些文件并将其压缩到网站的根目录。该网站没有package.json,因此npm将无法在该目录中使用。
下面是MakeFile,最后是我的问题。
REPO_FOLDER = npm
MINI_FILES = stream.min.js stream.min.js.map
#STREAM_MINI_FILES := $(REPO_FOLDER)/stream.min.js $(REPO_FOLDER)/stream.min.js.map
STREAM_MINI_FILES := $(MINI_FILES:%=REPO_FOLDER/%) #6.3.1 Substitution References
stream.js.zip: $(STREAM_MINI_FILES)
cd $(REPO_FOLDER); \
npm run zip ../stream.js.zip $(MINI_FILES)
$(STREAM_MINI_FILES): minify
minify:
@cd $(REPO_FOLDER); \
test -d "node_modules" || npm install; \
npm run minify;
update:
@git submodule update --remote
all: update stream.js.zip
.PHONY: minify, update, all
1)即使npm / stream.min.js npm / stream.min.js.map存在,minify目标也始终运行。为什么这样,我如何才能识别这两个文件?
2)@cd
和cd
之间有什么区别?在minify目标中我可以@cd
到npm文件夹并运行npm install
,但是在stream.js.zip目标中,我从npm收到错误,因为它仍然在网站目录中(没有的package.json)。为什么我不在npm目录中,当我在那种情况下执行@cd?
3)我使用npm来压缩两个编译的文件。我已经看到make中有一个ar
命令,但是它可以创建一个zip文件吗?如果是,那该怎么办?
更新
事实证明,我的变量替换是错误的,因此第二个目标也是错误的。 $(STREAM_MINI_FILES)将解析为REPO_FOLDER/stream.min.js
REPO_FOLDER/stream.min.js.map
而不是stream/stream.min.js
stream/stream.min.js.map
。由于第一条规则中的先决条件是 REPO_FOLDER 从不存在,因此每次都会生成第二条规则的食谱。
这是最终的MakeFile:
REPO_FOLDER = stream
MINI_FILES = stream.min.js stream.min.js.map
ZIP_FILE = stream.js.zip
#STREAM_MINI_FILES := $(REPO_FOLDER)/stream.min.js $(REPO_FOLDER)/stream.min.js.map
STREAM_MINI_FILES := $(MINI_FILES:%=$(REPO_FOLDER)/%) #6.3.1 Substitution References
$(ZIP_FILE): $(STREAM_MINI_FILES)
@cd $(REPO_FOLDER); \
npm run zip ../$@ $(MINI_FILES)
$(STREAM_MINI_FILES):
@cd $(REPO_FOLDER); \
test -d "node_modules" || npm install; \
npm run minify;
update:
@git submodule update --remote
clean:
@rm --verbose $(ZIP_FILE) $(STREAM_MINI_FILES)
all: update $(ZIP_FILE)
.PHONY: update, clean, all
答案 0 :(得分:3)
1)minify
被声明为.PHONY
特殊目标的先决条件。每次必须构建另一个依赖于它的目标时,make会重建它,或者使用此目标调用make。如果你使用make
调用make(也就是说,没有指定目标),它将尝试在你的情况下在makefile stream.js.zip
中构建第一个目标。由于它取决于$(STREAM_MINI_FILES)
,因此make会首先检查这些是否是最新的,如果不是,则重建它们。 $(STREAM_MINI_FILES)
本身依赖于minify
,这是.PHONY
的先决条件,因此必须在每种情况下重新制作,即使名为minify
的文件存在并且最多 - 日期。
此外,我怀疑minify
是一个符号目标,并且没有这个名称的真实文件(我错了吗?)。这是make重建它的另一个原因:它不存在但是$(STREAM_MINI_FILES)
需要它。
一种选择是完全删除minify
(包括.PHONY
先决条件)并合并规则:
$(STREAM_MINI_FILES):
@cd $(REPO_FOLDER); \
test -d "node_modules" || npm install; \
npm run minify
仅当$(STREAM_MINI_FILES)
中列出的某个文件丢失时,才应运行该配方。一个缺点是配方将运行多次,因为丢失文件,这是一种浪费。为避免这种情况,您可以保留minify
目标,但要将其设为真实的空文件,以便跟踪已经完成的操作:
$(STREAM_MINI_FILES): minify
minify:
@cd $(REPO_FOLDER); \
test -d "node_modules" || npm install; \
npm run minify
touch $@
这是一个非常常见的技巧,每次你的构建过程都不像“获取一个源文件并构建一个结果文件”时证明非常有用。
2)在配方中使用command
,在执行命令时回显命令。 @command
抑制回声。我想这与你的问题无关。
make配方中的命令列表由make执行,每行有一个单独的进程。所以,如果你:
cd there
pwd
这两行在两个不同的进程中执行,第一行对第二行没有影响。将命令放在同一个bash列表中,即用;
强制分隔命令使得在一个进程中执行它们(\
作为一行的最后一个字符逃脱行尾字符):
cd there; pwd
或:
cd there; \
pwd
是等效的,将在pwd
目录中执行there
命令。在stream.js.zip
食谱中,您只有一个bash列表。因此,它应该按预期工作,列表的第二个成员应该从$(REPO_FOLDER)
目录执行。你的问题来自别的东西。您是否尝试手动运行该命令?您是否检查过\
是否真的是该行的最后一个字符(否则它不会逃脱行尾)。
3)ar
不是make命令。它是一个GNU归档实用程序。不,它不能制作不同格式的zip存档。请注意,make可以在ar
档案的内部操作,就像它们被解压缩一样,这可能很有用。输入man ar
以了解有关ar
的更多信息。