子目录和 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 中的所有内容,它现在也能正常工作。
非常感谢!
/克里斯蒂安
我正在努力处理具有多个子目录的 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
我已经定义了我的 $(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 中的所有内容,它现在也能正常工作。
非常感谢! /克里斯蒂安