Makefile objects 在不同的文件夹中使用通配符 & headers (模块化编译)?

Makefile objects in different folders with wildcard & headers (modular compile)?

更新#04:

一切都在编译。将保持答案简洁,所以这里有一些中间步骤。

基本上规则只部分起作用,因为 objects 仍在他们自己的文件夹中制作。创建新的本地 object Rules 后编译。但是,由于它们现在位于自己的目录中,因此模块化编译无法 assemble objects 并正常工作(当 运行 时程序会出错) .

答案是一个新的 patsubst 模式(当然),但我最终通过反复试验找到了一个允许使用 wildcard[=54 输出的模式=] + 原始的 Rules + Recipes(用于使用多个 targets 进行模块化编译)。 查看下面的答案

更新#03:

模块化通配符编译现在可以通过按以下顺序尝试模式和规则并仅在失败时更改它们来为客户端工作。但是,我现在无法从客户端 objects 编译服务器并得到一堆 .c:(.text+0xb28): undefined reference to My_Func_Call 类型错误。我已经放弃尝试将 object 移动到另一条路径,因为 Make 只是拒绝正确遵循规则或编译(稍后会回来)。

任何人都知道为什么 objects/refs 现在不能从客户端重用于服务器或关于什么可能有效的任何想法?

# Pattern 1:
CODE = $(wildcard $(PATH)/*.c)
OBJS += $(CODE)

# Pattern 2:
CODE = $(wildcard $(PATH)/*.c)
CODE_OBJS = $(CODE:%.c=%.o)
OBJS += $(CODE_OBJS)

# Pattern 2 & Rule:
CODE = $(wildcard $(PATH)/*.c)
CODE_OBJS = $(CODE:%.c=%.o)
OBJS += $(CODE_OBJS)

$(BPATH)/%.o: $(PATH)/%.c $(PATH)/%.h $(COMMON_PATH)/%.h 
  %.o: %.c 
  $(DO_CC)

更新#02:

我继续实施这种通配其他子目录的模式,只是忽略了 object 的存储位置,但现在新编译的子目录似乎引起了冲突。之前的 header 变量丢失了(即使我在之前的编译代码中没有做任何更改)。这是由于我猜测有多个嵌套的 %o: %c 规则(所以这意味着我不能再做子目录了)。

我非常愿意接受有人向我指出可能与此问题相关的模式或资源?我所看到的大部分内容都是这些简单的 Makefile,它们一遍又一遍地具有相同的解决方案(non-modular 编译)。

否则,我想我要去下载 GNU Make 并开始逐行评论它以弄清楚数据发生了什么。一件事是阅读有关词干的内容,另一件事是了解 Make 实际上需要不破坏的语法或结构。

更新#01:

需要一个 Makefile,其中 object 位于不同的文件夹中并与 header 一起使用。我让它在一个路径设置中工作,但使用不同的路径需要更多代码才能找到 headers 并且无法将 objects 放在不同的文件夹中。

这基本上就是最小示例中发生的事情——有什么想法吗?:

CODE00 = $(wildcard $(PATH00)/*.c)
OBJ00 = $(CODE00:%.c=%.o)

OBJS = $(OBJ00)

CODE = $(wildcard $(PATH)/*.c)
HEADER = $(wildcard $(PATH)/*.h) $(wildcard $(COMMON_PATH)/*.h) # Alt header.
#OBJ = $(patsubst %.c, %.o, $(CODE)) # Also works.
OBJ = $(CODE:%.c=%.o)

OBJS += $(OBJ)

############
# RULES:
############

# Works:
$(BPATH00)/%.o: $(PATH00)/%.c $(PATH00)/%.h $(PATH01)/%.h # Objs in folder/headers work.
    $(DO_CC)

# Broken:
$(BPATH)/%.o: $(PATH)/%.c $(PATH)/%.h $(COMMON_PATH)/%.h # Requires more before DO_CC?
  #%.o: %.c # Works but .o in source folder, fails without.
  #%.o: %.c ${HEADER} # Works but .o in source folder, fails without.
  $(BPATH)/%.o: %.c # Fails with missing header vars.
  #$(BPATH)/%.o: %.c ${HEADER} # Fails with missing header vars.
    $(DO_CC)

############
# LINK:
############

define DO_CC
gcc $(OBJS) $(CFLAGS) -o $@ -c $< 
endef

这是通配符的工作模式和具有多个目标的模块化编译。

注意:您必须删除 header includes 或冲突的 %.o: %o.c 同一文件夹 objects 需要规则。否则,当您更改 Rule 顺序时,它会导致许多奇怪的缺失目标错误发生变化(这只会浪费您的时间并且令人困惑)。

HOST_CODE := $(wildcard $(HOST_PATH)/*.c)
HOST_OBJECTS = $(patsubst $(HOST_PATH)/%.c, $(HOST_BPATH)/%.o, $(HOST_CODE))
CLIENT_OBJECTS = $(patsubst $(HOST_PATH)/%.c, $(CLIENT_BPATH)/%.o, $(HOST_CODE))

# Or to append:

HOST_CODE := $(wildcard $(HOST_PATH)/*.c)
HOST_OBJECTS += $(patsubst $(HOST_PATH)/%.c, $(HOST_BPATH)/%.o, $(HOST_CODE))
CLIENT_OBJECTS += $(patsubst $(HOST_PATH)/%.c, $(CLIENT_BPATH)/%.o, $(HOST_CODE))

# Rules (includes/headers will break your compile):

$(HOST_BPATH)/%.o: $(HOST_PATH)/%.c
    $(DO_HOST_CC)

$(CLIENT_BPATH)/%.o: $(HOST_PATH)/%.c
    $(DO_CLIENT_CC)


您不需要header包含规则。但是如果你想测试一下你的 headers 是否工作,我推荐这个 non-conflicting 模式(许多模式很容易冲突并破坏你的 Makefile,所以你需要要非常小心):

INCLUDES = $(shell find . -name '*.d')

include $(INCLUDES)