Makefile语法不清楚

问题描述 投票:-1回答:1

这是我的第一个Makefile,我无法弄清楚使用的一些语法。问题标在下面。

$(BUILD_DIR)/%.o: %.c  $(BUILD_DIR) 
  $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
  1. 依赖项中“$(BUILD_DIR)”的用法是什么?
  2. 角色中的“$(BUILD_DIR)/ $(notdir $(<:。c = .lst))$ < - $ $”是什么意思?
makefile
1个回答
0
投票

与大多数计算机语言一样,如果您不知道make的语法,则无法清楚。如果您使用的是GNU,那么GNU make manual就是您的朋友。在下面的解释中,我将假设BUILD_DIR = build和其中一个源文件是bar/foo.c

  1. 先决条件(依赖项)列表中的$(BUILD_DIR)告诉make在执行配方之前必须存在构建目录(应该在哪个目标文件中);逻辑。如果目录尚不存在,则必须在某处创建另一个规则。就像是: $(BUILD_DIR): mkdir -p $@ 但除非你忘记复制一个重要角色,否则这种依赖性非常不理想。由于每次内容更改(添加或删除文件或子目录)时目录的最后修改时间都会更改,因此每次目录更改时都会强制重新编译所有源文件,这不是您想要的。更好的依赖是order-only$(BUILD_DIR)/%.o: %.c | $(BUILD_DIR) 这告诉make只考虑$(BUILD_DIR)的存在,而不是它的最后修改时间,在决定是否重建时。
  2. $(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@只是制作automatic variablesfunctions的组合。 $<$@分别作为第一个先决条件(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

请注意,有两种不同的情况需要考虑:

  1. 您的所有源文件都与Makefile位于同一目录中(没有bar/foo.c,只有foo.c)。然后你可以简化你的食谱: $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(<:.c=.lst) $< -o $@ 因为$(notdir...)没用。
  2. 您的源文件可以位于子目录(bar/foo.c)中。然后你需要食谱中的$(notdir...)。但请注意,如果您有两个具有相同基本名称的源文件(bar/foo.cbaz/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 $@ 还有其他解决方案(二次扩展......)但是这个已经太长的答案有点太复杂了。
© www.soinside.com 2019 - 2024. All rights reserved.