我想创建一个 Makefile 来强制设置变量(如果不正确则失败)。
已阅读 从命令行传递附加变量到 make 和 Makefile -- 如果未设置变量则出错 和 如果未设置变量如何中止 makefile? 和 目标内 Makefile 中的条件,我知道有两个明显的选择:
make
条件函数,例如$(if condition,then-part[,else-part])
,以及“全局”条件,例如ifndef variable-name
。
我的理解是,全局条件实际上是这样的:
.PHONY: all, clean
OBJS=lorem.o ipsum.o
ifndef LIBUV_LIB
$(error LIBUV_LIB not set)
endif
all: liblorem.so libipsum.so
liblorem.so: lorem.o
$(CC) -shared -o $@ $^ -L $(LIBUV_LIB) -luv
libipsum.so: ipsum.o
$(CC) -shared -o $@ $^ -L $(LIBUV_LIB) -luv
clean:
rm -f $(OBJS) liblorem.so libipsum.so
...即
LIBUV_LIB
的存在是“全局”评估的,我可以通过将其作为 make
参数传递来设置它:
$ make
Makefile:6: *** LIBUV_LIB not set. Stop.
$
$ make LIBUV_LIB=/usr/local/libuv1.45.0
cc -c -o lorem.o lorem.c
cc -shared -o liblorem.so lorem.o -L /usr/local/libuv1.45.0 -luv
cc -c -o ipsum.o ipsum.c
cc -shared -o libipsum.so ipsum.o -L /usr/local/libuv1.45.0 -luv
$
这完成了工作,它只是有一个恼人的效果,需要为
clean
目标进行设置,而它并不真正相关:
$ make clean
Makefile:6: *** LIBUV_LIB not set. Stop.
$ make LIBUV_LIB=/usr/local/libuv1.45.0 clean
rm -f lorem.o ipsum.o liblorem.so libipsum.so
$
探索条件函数,我想出了这个Makefile:
.PHONY: all, clean
OBJS=lorem.o ipsum.o
all: liblorem.so libipsum.so
liblorem.so: lorem.o
$(if $(LIBUV_LIB),,$(error LIBUV_LIB not set))
$(CC) -shared -o $@ $^ -L $(LIBUV_LIB) -luv
libipsum.so: ipsum.o
$(if $(LIBUV_LIB),,$(error LIBUV_LIB not set))
$(CC) -shared -o $@ $^ -L $(LIBUV_LIB) -luv
clean:
rm -f $(OBJS) liblorem.so libipsum.so
这也能完成工作:
$ make
cc -c -o lorem.o lorem.c
Makefile:8: *** LIBUV_LIB not set. Stop.
$
$ make LIBUV_LIB=/usr/local/libuv1.45.0
cc -shared -o liblorem.so lorem.o -L /usr/local/libuv1.45.0 -luv
cc -c -o ipsum.o ipsum.c
cc -shared -o libipsum.so ipsum.o -L /usr/local/libuv1.45.0 -luv
$
...但似乎需要为
LIBUV_LIB
目标指定 clean
来规避我的不满:
$ make clean
rm -f lorem.o ipsum.o liblorem.so libipsum.so
$
我现在的抱怨是重复
$(if $(LIBUV_LIB),,$(error LIBUV_LIB not set))
声明,因为这感觉像是违反了 DRY 原则。
我的问题是:是否有一种(n)(惯用的)方法来编写一个Makefile,强制(如果不正确则失败)为除
clean
目标之外的所有目标设置变量?
您可以通过查看
$(MAKECMDGOALS)
变量来检查调用了哪些目标。如果指定了除 clean
以外的任何目标 other,您可能希望失败,因为您想要正确处理诸如
make clean all
之类的事情。
所以你可以这样做:
ifndef LIBUV_LIB
ifneq ($(MAKECMDGOALS),clean)
$(error LIBUV_LIB not set)
endif
endif