仅当文件更改时才进行安装

发布于 2024-09-11 09:21:18 字数 518 浏览 5 评论 0原文

当编写精心设计的 Makefile(保持适当的依赖关系,并且在文件发生更改时只执行所需的最低限度的操作)时,install: 目标似乎经常被忽略。更常见的是,安装目标看起来像这样:

TRG := /trg
BIN_TRG := $(TRG)/bin
ETC_TRG := $(TRG)/etc
BIN_FILES := b1 b2 b3
ETC_FILES := e1 e2 e3

install:
    install $(BIN_FILES) $(BIN_TRG)
    install $(ETC_FILES) $(ETC_TRG)

.PHONY: install

也就是说,一个虚假目标,没有任何依赖项检查。

如果需要填充暂存区域来准备二进制包(例如 RPM 包),或者如果构建的下一阶段依赖于该暂存区域,则此类问题会变得更加严重,而不是简单安装。在这种情况下,洞依赖树在安装阶段之后就会崩溃。

问题是:拥有跟踪依赖项的安装规则的最佳方法是什么?

When writing a well crafted Makefile, one that keeps proper dependencies, and do only the minimum needed if a file has been changed, it seem that the install: target is often overlooked. More often then not the install target looks something like:

TRG := /trg
BIN_TRG := $(TRG)/bin
ETC_TRG := $(TRG)/etc
BIN_FILES := b1 b2 b3
ETC_FILES := e1 e2 e3

install:
    install $(BIN_FILES) $(BIN_TRG)
    install $(ETC_FILES) $(ETC_TRG)

.PHONY: install

That is, a phony target with no dependency checking what so ever.

This kind of problem become more serious if instead of simple install there is a need to populate a staging area to prepare a binary package such as RPM packages, or if the next stage of build depends on that staging area. In this case the hole dependency tree break down after that install stage.

The question is: What is the best approach to have install rule that keeps track of dependencies?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

醉生梦死 2024-09-18 09:21:18

我不熟悉您的“安装”功能,并且您的两个解决方案以不同的方式使用它,但是这样怎么样:

TRG := /trg
BIN_TRG := $(TRG)/bin
ETC_TRG := $(TRG)/etc
BIN_FILES := b1 b2 b3
ETC_FILES := e1 e2 e3
INSTALLS := $(addprefix $(BIN_TRG)/,$(BIN_FILES)) \
        $(addprefix $(ETC_TRG)/,$(ETC_FILES))

install: $(INSTALLS)

$(BIN_TRG)/% $(ETC_TRG)/%: %
    install 
lt; $@

.PHONY: install

编辑: PS如果您希望安装步骤填充暂存区域,或者其他什么,使暂存区域成为具有自己规则的单独目标。

I'm not familiar with your "install" function, and your two solutions use it different ways, but how about this:

TRG := /trg
BIN_TRG := $(TRG)/bin
ETC_TRG := $(TRG)/etc
BIN_FILES := b1 b2 b3
ETC_FILES := e1 e2 e3
INSTALLS := $(addprefix $(BIN_TRG)/,$(BIN_FILES)) \
        $(addprefix $(ETC_TRG)/,$(ETC_FILES))

install: $(INSTALLS)

$(BIN_TRG)/% $(ETC_TRG)/%: %
    install 
lt; $@

.PHONY: install

EDIT: P.S. if you want the install step to populate a staging area, or whatever, make the staging area a separate target with its own rule.

吃兔兔 2024-09-18 09:21:18

我发现有效的一种方法是具体描述安装规则的依赖关系。对于每个文件,我们需要构建一个规则,例如:

trg_dir/my_file: my_file
    install 
lt; $@

要做到这一点,但是需要一些 gmake 魔法:

TRG := /trg
BIN_TRG := $(TRG)/bin
ETC_TRG := $(TRG)/etc
BIN_FILES := b1 b2 b3
ETC_FILES := e1 e2 e3
INSTALLS := $(addprefix $(BIN_TRG)/,$(BIN_FILES)) \
            $(addprefix $(ETC_TRG)/,$(ETC_FILES))

install: $(INSTALLS)

define install_rule
$(1)/$(2): $(2)
    install $(2) $(1)/$(2)
endef

$(foreach file,$(BIN_FILES),$(eval $(call install_rule,$(BIN_DIR),$(file))))
$(foreach file,$(ETC_FILES),$(eval $(call install_rule,$(ETC_DIR),$(file))))

.PHONY: install

我觉得这段代码需要一些解释,这也是我对它的主要抱怨 -
它比这样一个看似常见的任务更复杂:

install: 目标仍然是虚假的,但它现在仅用于检查各个安装规则是否是最新的。

通过评估调用单个规则的宏定义的结果来生成规则。我们使用 $(foreach ...) 函数迭代每个文件,并在 $(call ...)ing install_rule 时给出正确的参数


我把问题和答案放在这里,尽管我似乎已经解决了它,因为我对这个解决方案不满意。任何更优雅的一种都会被热切地接受。

One approach I found to work is to specifically describe the dependencies of the install rule. For each file we need to construct a rule such as:

trg_dir/my_file: my_file
    install 
lt; $@

To do this, however some gmake magic is needed:

TRG := /trg
BIN_TRG := $(TRG)/bin
ETC_TRG := $(TRG)/etc
BIN_FILES := b1 b2 b3
ETC_FILES := e1 e2 e3
INSTALLS := $(addprefix $(BIN_TRG)/,$(BIN_FILES)) \
            $(addprefix $(ETC_TRG)/,$(ETC_FILES))

install: $(INSTALLS)

define install_rule
$(1)/$(2): $(2)
    install $(2) $(1)/$(2)
endef

$(foreach file,$(BIN_FILES),$(eval $(call install_rule,$(BIN_DIR),$(file))))
$(foreach file,$(ETC_FILES),$(eval $(call install_rule,$(ETC_DIR),$(file))))

.PHONY: install

I feel that this code need some explanation, this is also my major gripe with it -
it is more complicated then such a seemingly common task should be:

The install: target stays phony, but it will now only be used to check that the individual install rules, are up-to-date.

The rules are generated with evaluation of the result of calling a macro definition of the individual rule. We use a $(foreach ...) function to iterate over each file, and gives the proper parameters when $(call ...)ing the install_rule.


I put the question and answer here, although I seemingly solved it already, because I am not happy with this solution. Any more elegant one will be eagerly accepted.

橘亓 2024-09-18 09:21:18

由于 make 不支持虚假目标的先决条件,因此您必须在磁盘上创建一个实际的虚拟文件,并在安装目标触发时触摸该文件。

.PHONY: install

install: dummy

dummy: $(FILES_THAT_WERE_CHANGED)  
       install $(BIN_FILES) $(BIN_TRG)  
       install $(ETC_FILES) $(ETC_TRG)  
       touch dummy

Since make doesn't support prerequisites of phony targets, you will have to create an actual dummy file on the disk and touch that file whenever install target triggers.

.PHONY: install

install: dummy

dummy: $(FILES_THAT_WERE_CHANGED)  
       install $(BIN_FILES) $(BIN_TRG)  
       install $(ETC_FILES) $(ETC_TRG)  
       touch dummy
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文