gpt4 book ai didi

gnu-make - 如何防止 yarn 安装在Makefile中运行两次?

转载 作者:行者123 更新时间:2023-12-04 23:15:10 27 4
gpt4 key购买 nike

我的Makefile中有这个:

node_modules: yarn.lock
yarn install --production=false
touch node_modules

yarn.lock: package.json
yarn install --production=false
touch yarn.lock


基本上,如果 node_modules目录丢失(或者有人通过添加/删除文件来篡改该目录),或者 yarn.lock已更新,则应运行 yarn install来重建/完整性检查 node_modules目录。

但是,如果缺少 yarn.lock,则可以从 package.json重建它,或者如果 package.json已更新,则它应该安装并重建锁文件。

问题是当 node_modulesyarn.lock都丢失时,相同的命令将运行两次。

我该如何预防?



通过将指令包装在条件中,我几乎可以使它工作:

ifneq ("$(wildcard yarn.lock)","")
node_modules: yarn.lock
@yarn install --production=false
touch node_modules

yarn.lock: package.json
touch yarn.lock
else # yarn.lock does not exist
node_modules: yarn.lock
touch node_modules

yarn.lock: package.json
@yarn install --production=false
endif


现在,如果您 touch package.json然后 make node_modulesyarn.lock存在,那么它将随后 touch yarn.lock进行,这将导致 node_modules重建,就像我想要的那样。

但是,如果先 touch package.json然后 make yarn.lock,从技术上讲,它应该尝试 yarn install,但是不会,因为我从此伪指令中删除了该命令:

yarn.lock: package.json
touch yarn.lock


为了防止它在前一种情况下运行两次。

最佳答案

首先,考虑一下此处所示的方法:

制作文件(1)

.PHONY: all clean

all: yarn.lock

yarn.lock: node_modules package.json
$(MAKE clean)
yarn install --production=false

node_modules:
mkdir -p $@

clean:
rm -fr node_modules yarn.lock


这将永远不会冗余地运行 yarn install,而且要多一些
强大的解决方案,而不是您正在考虑的。我会解释。

问题中的一个来源项目是 package.json。它是唯一的
逻辑上的前提是所有其他事物,而不是要建立的本身。

yarn.lock是一个人工制品,其生产表明
关于快照的 yarn install已成功完成
完成时存在的 package.jsonyarn install
随后,只要 yarn.lock,就认为安装是最新的
存在并且具有根据条件“同意” package.json的内容
在算法中体现在 yarn install中。

因此,从简单的角度来看,此版本的任务只是使 yarn.lock
关于 package.json的最新信息:

yarn.lock: package.json
yarn install --production=false


但这实际上更复杂。 yarn.lock是构建目标,但
它不是唯一的人工制品,甚至也不是
主要价值。当然,这些都是人工制品
node-modules由于运行 yarn install的结果。

因此,主要的仿制品似乎是这种仿制品的副作用,
而实际目标 yarn.lock仅作为代币对我们很重要
不管是什么,主要的人工制品都是最新的
package.json

这是一个脆弱的令牌。代理商可能会弄乱
node_modules-添加不应存在的文件,删除或
修改应该-和 yarn install不会做任何事情
只要它认为 yarn.lockpackage.json是最新的,就可以对其进行纠正,
根据自己的标准。

您在解释建议的食谱时已经注意到了这种脆弱性:

node_modules: yarn.lock
yarn install --production=false
touch node_modules



如果node_modules目录丢失(或有人篡改了该目录)
添加/删除文件),或者yarn.lock已更新,则应该运行yarn
安装以重建/完整性检查node_modules目录。


但是,该规则是由此类篡改触发的错误方法。的
篡改-如果幸运的话-将更新 node_modules的修改时间。
但这会使它比 yarn.lock年轻,而不是老,并且不会触发
食谱。该配方仅对 node_modules不存在的情况有用。

配方可以缓解这种弱点:

yarn.lock: node_modules package.json
$(MAKE) clean
yarn install --production=false


如果 yarn.lock不存在,或者已过期至 node_modules
package_json,我们将从头开始重新制作所有构建工件。

这样做比较好,但是会带来一个引导问题,如果两个
文物 yarn.locknode_modules存在,但 node_modules-这是为了
作为 yarn.lock的副产品填充-也是 yarn.lock的必需品。

但是,这是一个小问题。 yarn.lock的前提是存在
node_modules的值,并且在制作 yarn.lock之前是可以满足的,并且
node_modules的内容,最新-只需添加配方即可:

node_modules:
mkdir -p $@


这样,如果 node_modules不存在,它将被创建为
yarn.lock的先决条件,使其比 yarn.lock更新,并要求
yarn.lock和要制作的主要构件。

但...

此解决方案表示依赖关系本质上是正确的,并且-
结果-显示 yarn install永远不需要冗余运行的方式。和
它纠正了篡改检测逻辑中的错误方式错误。

但是仍未达到强大的篡改检测能力。

我们拥有的篡改检测机制是: node_modules中发生了什么
修改日期晚于 yarn.lock的目录。那
将检测到一些篡改,但不是全部。

作为文件系统对象,对目录进行了修改-并修改了修改时间
-当且仅当添加,删除或重命名直接子对象时。所以
篡改检测机制不了解任何子目录中的所有事件
node_modules以及对该文件的现有文件或子目录的任何修改
node_modules,但重命名除外。这就给混乱留下了足够的空间
node_modules

有鉴于此,您可能会决定:



薄弱的篡改检测总比没有好。我不想用任何
比这更贵。

但是您可能不会。更可能的选择:



脆弱的篡改检测总比没有好,所以我将回到:

yarn.lock: package.json
yarn install --production=false


我会将不当的篡改视为我的构建的范围。如果发生这种情况,将会破裂
我会注意到的, make clean,然后重试。

事前

我想要强大的篡改检测功能。

强大的篡改检测功能可以使举升变得更重-但不算太大。
您是否需要强制执行干净的 yarn install,具体取决于
node_modules内容的完整清单之间的新旧比较-
表现出足够的信息性,任何实质性的差异都会显现出来。

清单,详细列出其中每个文件的路径名和修改时间
node_modules是最佳候选人。此清单将包含 make
如果难以理解的主要伪像,将需要知道并从文件系统中获取
可以对此版本进行详细说明,并且该信息相对于
它的最后记录状态是重做一切的可靠触发。从而:

制作文件(2)

RM := rm -fr
MANIFEST_DIR := .manifest
LAST_MANIFEST := $(MANIFEST_DIR)/node_modules.last
NEW_MANIFEST := $(MANIFEST_DIR)/node_modules.peek
GEN_MANIFEST := find node_modules/ -exec stat -c '%n %y' {} \;

$(shell mkdir -p $(MANIFEST_DIR) node_modules)
$(if $(wildcard $(LAST_MANIFEST)),,$(shell touch $(LAST_MANIFEST)))
$(shell $(GEN_MANIFEST) > $(NEW_MANIFEST))
$(shell cmp -s $(LAST_MANIFEST) $(NEW_MANIFEST) || touch node_modules)

.PHONY: all clean

all: $(LAST_MANIFEST)

yarn.lock: node_modules package.json
$(RM) yarn.lock node_modules
yarn install --production=false

$(LAST_MANIFEST): yarn.lock
$(GEN_MANIFEST) > $@

clean:
$(RM) yarn.lock node_modules $(MANIFEST_DIR)


这主要是用无条件执行的设备来开发Makefile(1)
在顶部,-


确保(与以前一样)以 node_modules目录开头,即使该目录为空。
确保我们从隐藏目录( .manifest)开始工作
并保留 node_modules的最新清单。 (类似于
隐藏的 .deps目录,通常用于持久保存自动依赖文件
在C / C ++中)。
确保我们从一个持久清单(即使为空)开始。
生成一个新的,真实的清单快照,其内容如下: find node_modules/ -exec stat -c '%n %y' {} \;
<filename> <modification_time>下为每个项目写 node_modules
此快照对 node_modules而言是正确的,但不一定正确
应该是 node_modules的。 (是否应该遵循符号链接?- find -L ...
否。因为 make不会遵循目标或先决条件的符号链接)。
将新的真实快照与持久清单进行比较,如果
有任何区别,然后触摸 node_modules


这相当于将更新修改的构建序言
是否通过强大的篡改检测测试确定 node_modules的时间。然后
该构建与以前一样,只是其目标不再
yarn.lock,但是新的持久清单 $(LAST_MANIFEST)始终是
yarn-install后立即快照,因此取决于
yarn.lock

Makefile的锻炼(2)

对于 lab-rat package.json
我将使用:

{
"name": "node-js-sample",
"version": "0.2.0",
"description": "A sample Node.js app using Express 4",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "^4.13.3"
},
"engines": {
"node": "4.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/heroku/node-js-sample"
},
"keywords": [
"node",
"heroku",
"express"
],
"author": "Mark Pundsack",
"contributors": [
"Zeke Sikelianos <zeke@sikelianos.com> (http://zeke.sikelianos.com)"
],
"license": "MIT"
}


从头开始

$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.17s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last


不变并重新制作

$ make
make: Nothing to be done for 'all'.


仅触摸 node_modules

$ touch node_modules/
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.01s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last


仅触摸 package.json

$ touch package.json 
imk@imk-ThinkPad-T420:~/develop/so/make_prob$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.22s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last


触摸 node_modulespackage.json

$ touch package.json node_modules/
imk@imk-ThinkPad-T420:~/develop/so/make_prob$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.05s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last


触摸 yarn.lock

$ touch yarn.lock 
$ make
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last


删除 yarn.lock

$ rm yarn.lock 
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.17s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last


更改 package.json中的依赖项

$ sed -i 's/4\.13\.3/4.15.3/' package.json
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.03s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last


撤消更改

$ sed -i 's/4\.15\.3/4.15.3/' package.json
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 2.35s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last


触摸 node_modules子目录中的现有文件

$ ls node_modules/vary/
HISTORY.md index.js LICENSE package.json README.md
$ touch node_modules/vary/README.md
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.02s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last


将文件添加到 node_modules的子目录

$ touch node_modules/vary/interloper
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.20s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last


node_modules的子目录中删除文件

$ rm node_modules/vary/README.md 
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.16s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last

关于gnu-make - 如何防止 yarn 安装在Makefile中运行两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44036997/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com