我一直在研究一个 Makefile,它将在所有子目录中搜索src
包含源代码文件的目录并编译对象。稍后它会将对象链接到bin
与 Makefile 位于同一目录中的目录中的二进制文件中。每个二进制文件都将以其链接目标文件的子目录命名。对不起,如果这听起来有点混乱......
这是一个图表来说明我的意思:
Makefile
app1-\
src-\
main.c
obj-\
main.o
app2-\
src-\
main.c
obj-\
main.o
bin-\
app1
app2
目前,每当我运行 Makefile 时,它都会很好地编译目标文件,但是在链接它们时,它会尝试将所有这些文件链接到第一个二进制文件中。
错误:
Generating dependencies for problem2.1/src/2-1.c...
Compiling problem2.1/src/2-1.c...
Generating dependencies for problem2.1/src/2-1.c...
Compiling problem2.1/src/2-1.c...
Linking bin/problem2.1...
./problem2.2/obj/2-2.o: In function `main':
/cygdrive/c/Users/Hans/git/opsys/task_01/problem2.1/src/2-1.c:9: multiple definition of `_main'
./problem2.1/obj/2-1.o:/cygdrive/c/Users/Hans/git/opsys/task_01/problem2.1/src/2-1.c:9: first defined here
collect2: ld returned 1 exit status
Makefile:57: recipe for target `bin/problem2.1' failed
make: *** [bin/problem2.1] Error 1
我认为这里的主要问题是我误解了关于 Makefiles 的一些东西,有什么办法可以做我想做的事情吗?
到目前为止,唯一类似的就是使用make的递归功能,这是唯一的方法吗?
我的Makefile:
SRCEXT = c
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SUBDIRS := $(shell find . -type d -name '*$(SRCDIR)*' -exec dirname {} \; | uniq)
SRCDIRS := $(shell find $(SUBDIRS) -name '*.$(SRCEXT)' -exec dirname {} \; | uniq)
OBJDIRS := $(subst src,obj,$(SRCDIRS))
SRCS := $(shell find $(SRCDIRS) -name '*.$(SRCEXT)')
OBJREF := $(subst src,obj,$(SRCS))
OBJS := $(patsubst %.$(SRCEXT),%.o,$(OBJREF))
APPS := $(subst ./,,$(SUBDIRS))
DEBUG = -g
CFLAGS = -Wall -pedantic -ansi -c $(DEBUG) $(INCLUDES)
ifeq ($(SRCEXT), cpp)
CC = $(CXX)
else
CFLAGS += -std=gnu99
endif
.PHONY: all clean distclean
all: $(BINDIR)/$(APPS)
$(BINDIR)/$(APPS): buildrepo $(OBJS)
@mkdir -p `dirname $@`
@echo "Linking $@..."
@$(CC) $(OBJS) $(LDFLAGS) -o $@
$(OBJS): $(SRCS)
@echo "Generating dependencies for $<..."
@$(call make-depend,$<,$@,$(subst .o,.d,$@))
@echo "Compiling $<..."
@$(CC) $(CFLAGS) $< -o $@
clean:
$(RM) -r $(OBJDIRS)
distclean: clean
$(RM) -r $(BINDIR)
buildrepo:
@$(call make-repo)
define make-repo
for dir in $(OBJDIRS); \
do \
mkdir -p $$dir; \
done
endef
# usage: $(call make-depend,source-file,object-file,depend-file)
define make-depend
$(CC) -MM -MF $3 -MP -MT $2 $(CFLAGS) $1
endef