我必须为包含多个文件夹的程序编写一个“好”的makefile: bin,inc,obj,src。这是我的make文件。如果我输入make只是说虽然程序根本没有编译,但什么也做不了。猜猜我在某个地方有错误,但我真的找不到它。 (ps我很擅长制作)。 非常感谢你的帮助!
bin文件夹中的makefile:
vpath %.o ../obj/
$(prog): $(objs)
$(cc) $(ccflags) -o $@ $^ $(ldflags)
obj文件夹中的makefile:
vpath %.c ../src
vpath %.h ../inc
all: $(objs)
%.o: %.c %.h
$(cc) $(ccflags) -c $<
-include *.d
一般makefile:
export prog := inv_svn
export objs := $(patsubst %.c, %.o, $(wildcard src/*.c)))
export src_dir := src
export inc_dir := inc
export obj_dir := obj
export bin_dir := bin
export cc := gcc
export ccflags := -I $(PWD)/$(inc_dir) -MMD -g -Wall
export ldflags := -lcurses -lgdbm
test := ./$(prog)
all: $(prog)
$(prog): $(bin_dir)
$(bin_dir): $(obj_dir)
$(bin_dir):
make -C $@
$(obj_dir):
make -C $@
.PHONY: clean
clean:
rm -f $(obj_dir)/*.[od]$(prog)
答案 0 :(得分:0)
这里有太多问题需要立即修复。让我们开始小而简单,并建立起来。
首先,当你真的不需要时,你正在使用Make递归。之后,你应该重新考虑这个设计。现在,让我们看看我们是否可以obj/makefile
工作。
其次,子makefile依赖于从调用makefile传递下来的变量(如objs
),变量也可以构造自己。这是糟糕的设计。我们会将作业放在obj/makefile
:
objs := $(patsubst %.c, %.o, $(wildcard ../src/*.c))
(请注意,我删除了额外的)
,这些事情搞得一团糟。)
第三,当我们测试这个时,我们得到../src/foo.o ../src/bar.o
,这可能不是我们想要的;我们想在obj/
中构建对象,而不是src/
(主makefile中的赋值具有相同的问题)。所以我们改变它:
objs := $(patsubst ../src/%.c, %.o, $(wildcard ../src/*.c))
(有更多优雅的方式,但现在不要紧。)
第四,我相信您可以对bin/makefile
进行类似的更改。
第五,在主Makefile中,你将子目录当作目标,当它们确实不是;这些规则的要点不是构造子目录,而是在其中运行Make。如果它们已经存在(他们这样做),则表示满意,并得出结论:$(prog)
和all
无需重建。我们可以通过一些PHONY目标解决这个问题:
.PHONY: RUN_IN_$(obj_dir) RUN_IN_$(bin_dir)
$(prog): RUN_IN_$(bin_dir)
RUN_IN_$(bin_dir): RUN_IN_$(obj_dir)
RUN_IN_$(bin_dir):
make -C $(bin_dir)
RUN_IN_$(obj_dir):
make -C $(obj_dir)
粗暴但有效。
这应该足以让你离开地面。