gpt4 book ai didi

c - Makefile递归地包含目标文件列表

转载 作者:太空宇宙 更新时间:2023-11-03 23:58:14 26 4
gpt4 key购买 nike

我使用 Linux 内核已经有一段时间了,我对调整那里使用的 Makefile 结构很感兴趣。我想通过在每个子目录中创建一组 Makefile 来实现类似的目的,这些子目录仅包含我在构建项目时真正想要编译的文件的名称。在 Linux 内核中实现的一个典型的类似示例如下所示:

obj-y += file1.o
obj-y += file2.o
obj-y += file3.o
obj-y += file4.o
# ...
obj-d += somesubdir

现在,在构建我的项目时,我使用根目录中的 Makefile 递归地将每个 Makefile 包含在各个子目录中,并将其附加到 obj-y 变量的列表中。我目前的方法是定义一个递归函数来处理包含 Makefile 并自动遍历每个子目录:

OBJS :=

objtree := .
srctree := .

# ...

define build_subdir
objtree := $$(objtree)/$(1)
srctree := $$(srctree)/$(1)

obj-y :=
obj-d :=

include $$(srctree)/Makefile

OBJS += $$(patsubst %,$$(objtree)/%,$$(obj-y))

$$(foreach subdir,$$(obj-d),$$(eval $$(call build_subdir,$$(subdir))))

srctree := $$(patsubst %/$(1),%,$$(srctree))
objtree := $$(patsubst %/$(1),%,$$(objtree))
endef

# ...

$(eval $(call build_subdir,src))
$(eval $(call build_subdir,src/subdir))

在遍历所有子目录时,我将各个文件添加到 OBJS 变量中,该变量随后用于编译文件。但是,OBJS 变量仅包含目标文件(即目标)的名称,而不是实际源文件的名称。这是有问题的,因为我项目中的源文件不仅包含 .c,还包含一些汇编文件 (.S)。因此我无法定义如下所示的食谱:

define compile_file
$(1): $$(patsubst %.o,%.c,$(1))
$(CC) $< -o $@ $(CFLAGS)
endef

在我的例子中,编译器总是相同的,所以保持 $(CC) 变量不变是没有问题的。 $(CFLAGS) 变量也是如此。

有没有一种类似于 Linux 内核的方法来实现这一点?

这是我的Makefile当前的相关内容:

objtree  := .
srctree := .

.PHONY: all
all: real-all

OBJS :=

define build_subdir
objtree := $$(objtree)/$(1)
srctree := $$(srctree)/$(1)

obj-y :=
obj-d :=

include $$(srctree)/Makefile

OBJS += $$(patsubst %,$$(objtree)/%,$$(obj-y))

$$(foreach subdir,$$(obj-d),$$(eval $$(call build_subdir,$$(subdir))))

srctree := $$(patsubst %/$(1),%,$$(srctree))
objtree := $$(patsubst %/$(1),%,$$(objtree))
endef

# $(eval $(call build_subdir, src))
$(eval $(call build_subdir,src/arch/$(ARCH)))

define compile_file
$(1): $$(patsubst %.o,%.S,$(1))
@echo "Compiling file $$< to file $$@"
endef

$(foreach file,$(OBJS),$(eval $(call compile_file,$(file))))

.PHONY: real-all
real-all: $(OBJS)
@echo "real-all"

当前输出:

Compiling file src/arch/x86/a20.S to file src/arch/x86/a20.o
make: *** No rule to make target 'src/arch/x86/acpi.S', needed by 'src/arch/x86/acpi.o'. Stop.

最后一行显然失败了,因为没有 src/arch/x86/acpi.S 文件。相反,实际文件是 src/arch/x86/acpi.c。这就是我之前解决的问题,因为源文件可以是 .c.S 文件。

最佳答案

我通过以下方式使用 $(wildcard) 函数解决了这个问题:

define compile_file

srcbase := $$(basename $(1))
srcfile := $$(wildcard $$(srcbase).*)

$(1): $$(srcfile)
@echo "[ CC ] $$@"
endef

由于 $(1) 包含文件的路径,srcfile 通过查找带有 $(wildcard $$(basename $ (1)).*).

现在,我可以轻松编译所有文件。

关于c - Makefile递归地包含目标文件列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56001646/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com