0

我是 Makefile 的新手。在尝试编写一个可以在我的大多数项目中使用且修改最少的通用 Makefile 时,我遇到了一个问题(简化如下):

我的“项目”看起来像:

proj/
    src1.cpp
    subdir1/
        src2.cpp
    Makefile

部分Makefile

OBJ := bin/src1.o bin/subdir1/src2.o
OBJ_DIR := bin/ bin/subdir1/
PROGRAMS := prog1
define compile_template =
$(1)/%.o: %.cpp
    mkdir -p $$(@D)
    $$(CXX) $$(CXXFLAGS) -c $$< -o $$@
endef

define PROGRAM_template =
$(1): $$(OBJ)
    $$(CXX) $$(LDFLAGS) $$^ -o $$@ $$(LDLIBS)
endef

$(foreach odir,$(OBJ_DIR),$(eval $(call compile_template,$(odir))))
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))

错误是:

gmake: *** No rule to make target `bin/src1.o', needed by `proj1'.  Stop.

另一个问题是,如果我只在特定机器上编译(所以我可以控制编译器、操作系统……),我应该编写自己的 Makefile 还是使用 automake 等?

4

1 回答 1

3

调试此类问题(eval 的问题)的最佳方法是将$(eval ...)函数替换为调用$(info ...). 这将打印出 make 正在解析的文本,通常很明显您的问题是什么。如果您将 eval 行重写为:

$(foreach odir,$(OBJ_DIR),$(info $(call compile_template,$(odir))))
$(foreach prog,$(PROGRAMS),$(info $(call PROGRAM_template,$(prog))))

(并修复您明显的语法错误,第一行之间的空格:=您会看到:

bin//%.o: %.cpp
        mkdir -p $(@D)
        $(CXX) $(CXXFLAGS) -c $< -o $@
bin/subdir1//%.o: %.cpp
        mkdir -p $(@D)
        $(CXX) $(CXXFLAGS) -c $< -o $@
prog1: $(OBJ)
        $(CXX) $(LDFLAGS) $^ -o $@ $(LDLIBS)

从这里你可以看到prog1depends on bin/src1.oand bin/subdir1/src2.oso make想要构建bin/src1.o它会查看您的规则,但由于额外的斜杠,make 的内部匹配语法bin//%.o不匹配。bin/src1.o

更改您的分配以删除尾部斜杠,它应该会更好地工作:

OBJ_DIR := bin bin/subdir1
于 2013-07-16T20:52:16.283 回答