Makefile语法不清楚
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Makefile语法不清楚相关的知识,希望对你有一定的参考价值。
这是我的第一个Makefile,我无法弄清楚使用的一些语法。问题标在下面。
$(BUILD_DIR)/%.o: %.c $(BUILD_DIR)
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
- 依赖项中“$(BUILD_DIR)”的用法是什么?
- 角色中的“$(BUILD_DIR)/ $(notdir $(<:。c = .lst))$ < - $ $”是什么意思?
答案
与大多数计算机语言一样,如果您不知道make的语法,则无法清楚。如果您使用的是GNU,那么GNU make manual就是您的朋友。在下面的解释中,我将假设BUILD_DIR = build
和其中一个源文件是bar/foo.c
。
- 先决条件(依赖项)列表中的
$(BUILD_DIR)
告诉make在执行配方之前必须存在构建目录(应该在哪个目标文件中);逻辑。如果目录尚不存在,则必须在某处创建另一个规则。就像是:$(BUILD_DIR): mkdir -p $@
但除非你忘记复制一个重要角色,否则这种依赖性非常不理想。由于每次内容更改(添加或删除文件或子目录)时目录的最后修改时间都会更改,因此每次目录更改时都会强制重新编译所有源文件,这不是您想要的。更好的依赖是order-only:$(BUILD_DIR)/%.o: %.c | $(BUILD_DIR)
这告诉make只考虑$(BUILD_DIR)
的存在,而不是它的最后修改时间,在决定是否重建时。 $(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
只是制作automatic variables和functions的组合。$<
和$@
分别作为第一个先决条件(bar/foo.c
)和目标(build/bar/foo.o
)扩展。$(<:.c=.lst)
用.c
中的.lst
取代$<
:bar/foo.lst
。$(notdir $(<:.c=.lst))
删除了目录部分:foo.lst
。
总而言之,对于bar/foo.c
源文件和BUILD_DIR = build
,模式规则将等同于:
build/bar/foo.o: bar/foo.c | build
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=build/foo.lst bar/foo.c -o build/bar/foo.o
请注意,有两种不同的情况需要考虑:
- 您的所有源文件都与Makefile位于同一目录中(没有
bar/foo.c
,只有foo.c
)。然后你可以简化你的食谱:$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(<:.c=.lst) $< -o $@
因为$(notdir...)
没用。 - 您的源文件可以位于子目录(
bar/foo.c
)中。然后你需要食谱中的$(notdir...)
。但请注意,如果您有两个具有相同基本名称的源文件(bar/foo.c
和baz/foo.c
),则$(BUILD_DIR)/foo.lst
将出现名称冲突,并且您的Makefile将无法按预期工作。此外,规则的仅限订单的先决条件应该等同于build/bar
(或build/baz
),而不仅仅是build
。如果需要,应该有一个规则来创建它。如果是你的情况,我建议你改变你的模式规则:$(BUILD_DIR)/%.o: %.c mkdir -p $(dir $@) $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
还有其他解决方案(二次扩展......)但是这个已经太长的答案有点太复杂了。
以上是关于Makefile语法不清楚的主要内容,如果未能解决你的问题,请参考以下文章
通过 $(if ...) 在 makefile 中分配变量的语法