子目录和 Makefile?

Subdirectories and Makefile?

我正在努力处理具有多个子目录的 C 项目,其中 .o 文件应位于子目录“obj/”中。像这样:

/hzg/src/
/hzg/src/adaemon
/hzg/src/adaemon/obj
/hzg/src/bdaemon
/hzg/src/bdaemon/obj
/hzg/src/notrelateddir

C 文件在 *daemon/ 中,匹配 .o 文件在 *daemon/obj 中。 一个主 Makefile 应该驻留在 /hzg/src 中并且每个 /hzg/src/*daemon

中应该有一个 Makefile

我已经定义了我的 $(SOURCES) 并用 $(subst...) 导出了 $(OBJECTS)

我正在苦苦挣扎的是在正确定义的规则中获得先决条件...

这是我目前的情况:

(子)守护进程中的 Makefile:

[...]
SOURCES         =       $(wildcard *.c)
OBJECTS         =       $(patsubst %.c, obj/%.o, $(SOURCES))

all: $(OBJECTS)

$(OBJECTS):  obj/%.o : %.c $(HEADERS)
        $(CC) $(CLFAGS) -c $< -o $@

这很有魅力。我苦苦挣扎的是“大师”Makefile。我如何告诉 make 从 obj/ 目录中获取 .o 并搜索匹配的 .c 文件?

生成文件

[...]
SUBDIRS         :=      common:hzgd:masterd:mqttd:

SOURCES         =       $(wildcard $(subst :,/*.c , $(SUBDIRS)))
OBJECTS         =       $(subst /,/obj/,$(patsubst %.c,%.o,$(SOURCES)))

BIN             =       hzgmasterd 

all             :       $(BIN)

$(BIN)          :       $(OBJECTS)
        $(CC) $(CFLAGS) -rdynamic -o $(BIN) $(OBJECTS) $(LIBS)
        @echo "Server done."

$(OBJECTS)      :       obj/%.o : %.c $(HEADERS)
        $(CC) $(CFLAGS) -c $< -o $@

哦,我不介意使用“make -C”命令,但在这种情况下,它应该只在 .o 文件需要重新编译时进入目录。

这是构建 top-level makefile 的一种方法:

SUBDIRS := common hzgd masterd mqttd

SOURCES := $(wildcard $(addsuffix /*.c ,$(SUBDIRS)))
OBJECTS := $(filter %.o,$(foreach D,$(SUBDIRS),$(patsubst $D/%.c,$D/obj/%.c,$(SOURCES))))

BIN      =  hzgmasterd 

all : $(BIN)

$(BIN) : $(OBJECTS)
        $(CC) $(CFLAGS) -rdynamic -o $@ $^ $(LIBS)
        @echo "Server done."

$(OBJECTS): $(SUBDIRS) ;

$(SUBDIRS):
        $(MAKE) -C $@

.PHONY: $(SUBDIRS)

我实际上并没有尝试过这个,但我认为它会起作用。通过添加分号,这些是实际规则,make 将检查目标上的时间戳。

如果你想在每个子目录中创建一个库,你会定义一个规则来做到这一点,可能在它所在的目录之后命名库,列出所有对象作为先决条件,然后在这个 makefile 中你' d 列出每个子目录一个库作为先决条件。

感谢@MadScientist。 一些小故障和类型(即 foreach 不起作用),我现在有一个可行的解决方案。

“大师”-Makefile:

SUBDIRS     :=  common hzgd masterd mqttd
CSUBDIRS    :=  client

CFLAGS      =   -Wall
LIBS        :=  -lconfig -lcurl -ljson-c -lm -lmodbus -lmosquitto -lownet -lpthread -lsystemd -lical

SOURCES     :=  $(wildcard $(addsuffix /*.c ,$(SUBDIRS)))
OBJECTS     :=  $(subst /,/obj/,$(subst .c,.o,$(SOURCES)))
HEADERS     :=  $(wildcard *h)

CSOURCES    :=  $(wildcard $(addsuffix /*.c ,$(CSUBDIRS)))
COBJECTS    :=  $(subst /,/obj/,$(subst .c,.o,$(CSOURCES)))
CHEADERS    :=  $(wildcard client/*h)

BIN         :=  hzgmasterd
CBIN        :=  client/hzgclnt

all     :   $(BIN) $(CBIN)
server      :   $(BIN)
client      :   $(CBIN)

#====================== Master ============================
$(BIN)      :   $(OBJECTS)
    $(CC) $(CFLAGS) -rdynamic -o $@ $^ $(LIBS)
    @echo "Server done."

$(OBJECTS)  :   $(SUBDIRS) ;

.PHONY: $(SUBDIRS)
$(SUBDIRS)  :
    $(MAKE) -C $@


#====================== Client ============================
.PHONY: $(CBIN)
$(CBIN)     :   $(CSUBDIRS)/
    $(MAKE) -C $<


#====================== Aufräumen ============================
.PHONY      :   clean
clean       :
    rm -f $(BIN) $(OBJECTS) $(COBJECTS)

“子”-Makefiles:

[...]
SOURCES     =   $(wildcard *.c)
HEADERS     =   $(wildcard ../*h)
OBJECTS     =   $(patsubst %.c, obj/%.o, $(SOURCES))

all: $(OBJECTS)
#==================================================
$(OBJECTS):  obj/%.o : %.c $(HEADERS)
    $(CC) $(CLFAGS) -c $< -o $@

#====================== Aufräumen ============================
.PHONY: clean
clean:
    rm -f *.o obj/*.o

现在有一个小故障 make 进入每个子目录并执行另一个 make 进程来确定目标是否是最新的。 我知道这是设计使然,尽管它会导致额外的步骤....但是,即使我不理解您发布的 Makefile 中的所有内容,它现在也能正常工作。

非常感谢! /克里斯蒂安