所以我试图破解我的一个makefile变得更简单(更简单,好像没有定义很多规则如何将子目录转换为.deb)。
build-if-need-status-vars:
@if [ ! -f debs/1.deb ]; then \
$(eval STATUS_REBUILD=1) \
echo "component: file not found: 1"; exit;\
else \
if [ $(shell find sources/ -newer debs/1.deb 2>/dev/null | wc -l) -gt 0 ]; then \
$(eval STATUS_REBUILD=1) echo "component: newer files exists: 1"; exit;\
else \
$(eval STATUS_REBUILD=0) echo "component: no newer files: 0"; \
fi;\
fi
@echo "status $(STATUS_REBUILD)"
actual-target: build-if-need-status-vars
ifeq ($(STATUS_REBUILD), 1)
@echo first status: 1
else
@echo second status: 0
@echo different action
endif
all: actual-target
.PHONY: actual-target
测试:
mkdir -p test/{sources,debs}; touch test/debs/1.deb; sleep 2; touch test/sources/1.src;
(在那里创建makefile并运行)
结果:
组件:找不到文件:1
状态0
第二个状态:0
无论执行什么条件块,STATUS_REBUILD
将始终为0(最后评估值),请尝试:touch test / debs / 1.deb
所以似乎总是使用最后一个$(eval)..如何避免这种行为并保持正确的赋值(从build-if-need-status-var中的第一个匹配)?
答案 0 :(得分:2)
$(eval)
是一个制作级功能。在配方扩展阶段的配方中,它会在您的配方中进行扩展。
在makefile解析的第二阶段(在手册here中简要讨论)中扩展了配方的内容。
我相信,但不能肯定地说(没有测试),食谱在它们即将运行之前不会扩展(但是为了这里的目的,不会改变任何方式)。
所以你的问题是所有 $(eval)
调用在make运行你的shell脚本时被扩展,所以你总是看到最后一行有效的最后一个值运行
所有人都说你实际上并不需要需要一个make-level变量。你的食谱只有两个shell执行。
您可以在与第一行(拆分)相同的执行中包含最后一行,并使用shell变量。
build-if-need-status-vars:
@if [ ! -f debs/1.deb ]; then \
STATUS_REBUILD=1; \
echo "component: file not found"; \
else \
if [ $(shell find sources/ -newer debs/1.deb 2>/dev/null | wc -l) -gt 0 ]; then \
STATUS_REBUILD=1; echo "component: newer files exists"; \
else \
STATUS_REBUILD=0; echo "component: no newer files"; \
fi;\
fi; \
echo "status $$STATUS_REBUILD"
请注意,我需要移除exit
件才能使其正常工作。如果真正的makefile中有必要(因为这是一个精简的样本),那么你可以通过将if
包装在子shell中和/或重写配方来保留它们。