持久化Makefile变量

持久化Makefile变量,makefile,Makefile,我希望我的Makefile被如下调用: make x11 oss bin 这将导致编译文件:main.c x11.c oss.c,并将它们链接到一个可执行文件bin 调用它的另一种方法是: make x11 alsa bin 除了使用main.c x11.c alsa.c 这是我的生成文件: bin: $(OBJ) main.o $(CC) $(LDFLAGS) $(OBJ) main.o $(LDLIBS) x11: set OBJ += bsd.o oss: se

我希望我的Makefile被如下调用:

make x11 oss bin
这将导致编译文件:
main.c x11.c oss.c
,并将它们链接到一个可执行文件
bin

调用它的另一种方法是:

make x11 alsa bin
除了使用
main.c x11.c alsa.c

这是我的生成文件:

bin: $(OBJ) main.o
    $(CC) $(LDFLAGS) $(OBJ) main.o $(LDLIBS)
x11:
    set OBJ += bsd.o
oss:
    set OBJ += oss.o
alsa:
    set OBJ += alsa.o
.c.o:
    $(CC) $(CFLAGS) -c $<
OBJ := $(filter-out bin,${MAKECMDGOALS})
bin:$(OBJ)main.o
$(CC)$(LDFLAGS)$(OBJ)main.o$(LDLIBS)
x11:
设置OBJ+=bsd.o
开放源码软件:
设置OBJ+=oss.o
alsa:
设置OBJ+=alsa.o
.c.o.:
$(CC)$(CFLAGS)-c$<
但似乎OBJ变量的内容在整个配方中并不持久。有什么建议吗?

OBJ是持久的,但您还有另一个问题:

  • make首先完全解析Makefile。因此$OBJ在此阶段仍为未设置/空。因此,bin目标只获取
    main.o
    作为依赖项,因为在此阶段所有变量都被替换为它们的值
  • 接下来,使用命令行上的给定目标更新OBJ的内容。但是OBJ不再用于bin目标,因为make已经完成了依赖项的构建。(Makefile通常不会第二次解析)
诀窍是在解析之前填充OBJ变量。一个简单的解决方案是使用以下方法调用Makefile:

make "OBJ=x11 oss" bin
并稍微修改Makefile,以添加
.o
-部分(或仅将它们添加到make命令中):

bin:$(patsubst%,%.o,$(OBJ))main.o
$(CC)$(LDFLAGS)$(OBJ)main.o$(LDLIBS)
.c.o.:
$(CC)$(CFLAGS)-c$<
注意:我说“Makefile通常不会被第二次解析”。可以多次递归地使用Makefile。这是一个非常复杂的问题,可能99%的情况下都不需要这样做。这种“制造虐待”的一个例子是。是Makefile自身多次调用的一个示例。

OBJ是持久的,但您还有另一个问题:

  • make首先完全解析Makefile。因此$OBJ在此阶段仍为未设置/空。因此,bin目标只获取
    main.o
    作为依赖项,因为在此阶段所有变量都被替换为它们的值
  • 接下来,使用命令行上的给定目标更新OBJ的内容。但是OBJ不再用于bin目标,因为make已经完成了依赖项的构建。(Makefile通常不会第二次解析)
诀窍是在解析之前填充OBJ变量。一个简单的解决方案是使用以下方法调用Makefile:

make "OBJ=x11 oss" bin
并稍微修改Makefile,以添加
.o
-部分(或仅将它们添加到make命令中):

bin:$(patsubst%,%.o,$(OBJ))main.o
$(CC)$(LDFLAGS)$(OBJ)main.o$(LDLIBS)
.c.o.:
$(CC)$(CFLAGS)-c$<
注意:我说“Makefile通常不会被第二次解析”。可以多次递归地使用Makefile。这是一个非常复杂的问题,可能99%的情况下都不需要这样做。这种“制造虐待”的一个例子是。是一个Makefile被自己多次调用的例子。

这有点像黑客

将以下内容添加到Makefile的顶部:

bin: $(OBJ) main.o
    $(CC) $(LDFLAGS) $(OBJ) main.o $(LDLIBS)
x11:
    set OBJ += bsd.o
oss:
    set OBJ += oss.o
alsa:
    set OBJ += alsa.o
.c.o:
    $(CC) $(CFLAGS) -c $<
OBJ := $(filter-out bin,${MAKECMDGOALS})
现在,当您键入
make x11 oss bin
make时,会解析以下内容:

OBJ := x11 oss
对于
makex11alsa-bin
,它将看到

OBJ := x11 alsa
您可能必须删除x11等的shell命令,因为
set OBJ+=bsd.o
不是有效的shell。

这有点像黑客攻击

将以下内容添加到Makefile的顶部:

bin: $(OBJ) main.o
    $(CC) $(LDFLAGS) $(OBJ) main.o $(LDLIBS)
x11:
    set OBJ += bsd.o
oss:
    set OBJ += oss.o
alsa:
    set OBJ += alsa.o
.c.o:
    $(CC) $(CFLAGS) -c $<
OBJ := $(filter-out bin,${MAKECMDGOALS})
现在,当您键入
make x11 oss bin
make时,会解析以下内容:

OBJ := x11 oss
对于
makex11alsa-bin
,它将看到

OBJ := x11 alsa

您可能必须删除x11等的shell命令,因为
set OBJ+=bsd.o
不是有效的shell。

这根本不是调用标准makefile的方式(尽管可以对其进行调整)。写一个脚本,比如说,
create
,它是按你的方式调用的,并且按惯例调用,不是更好吗?我是一个极简主义者,我认为一个只需要一个文件的解决方案比一个需要两个文件的解决方案要好,而且我不介意它是否不是正常的工作方式。这根本不是调用标准makefiles的方式(尽管它可能会很混乱)。写一个名为
create
的脚本不是更好吗?它是按您的方式调用的,并且按惯例进行调用。我是一个极简主义者,我认为一个只需要一个文件的解决方案比需要两个文件的解决方案更好,并且不介意它是否不是通常的处理方式。