我有一个项目,其中我需要使用Makefile使目录层次结构为
[user@machine program]$ ls
bin build CHANGELOG Makefile src
到目前为止,我创建这样一个Makefile的尝试一直没有结果。这是我的想法:
1)定义一些有希望的有用的东西
SRCDIR =$(PWD)/src # Keep multiple *.cpp and *.h files in here
BUILDDIR =$(PWD)/build # Build all appropriate *.o files
BINDIR =$(PWD)/bin # Compile/link all *.o files for final executable
PROJ = program #This is the name of the final executable
然后定义其他内容,如编译器,一些库链接等(我不担心这些)。
2)所有目标:
all: $(BINDIR)/$(PROJ)
3)所有目标的依赖关系:
$(BINDIR)/$(PROJ): $(BUILDDIR)/%.o
$(CPP) $^ -o $@
4)最后,* .cpp文件
$(BUILDDIR)/%.o: $(SRCDIR)/%.cpp $(SRCDIR)/%.h
$(CPP) -c $(CFLAGS) $<
5)究竟发生了什么?
[user@machine program]$ make
make: *** No rule to make target `/home/user/program/build/%.o', needed by `/home/user/program/bin/program'. Stop.
所以我觉得我目前的错误是我的最终可执行文件的规则,但我不确定如何修复它。
对此有何想法?任何输入都非常感谢!
答案 0 :(得分:2)
是的,你是对的。在第三步($(BINDIR)/$(PROJ): $(BUILDDIR)/%.o
)中,您混合了显式和隐式规则。
您必须以某种方式提供将它们链接在一起的对象列表。最常见的方法是将所有现有源文件的名称(请参阅wildcard
函数)转换为相应的目标文件或明确列出它们。
SRCS := $(wildcard $(SRCDIR)/*.cpp)
OBJS := $(SRCS:$(SRCDIR)/%.cpp=$(BUILDDIR)/%.o)
现在您的链接规则应如下所示:
$(BINDIR)/$(PROJ): $(OBJS)
$(CPP) $^ -o $@
通常CPP
变量名代表C PreProcessor,C ++编译器代表CXX
。来自GNU Make manual:
CC
编制C程序的程序;默认‘cc’
。
CXX
编译C ++程序的程序;默认‘g++’
。
CPP
用于运行C预处理器的程序,其结果为标准输出;默认‘$(CC) -E’
。
仅添加$(SRCDIR)/%.h
先决条件并不能保证增量构建的完整性。假设foo.cpp
包括foo.h
,bar.cpp
包括bar.h
和foo.h
。然后修改foo.h
只会触发foo.cpp
的编译,但是您可能会期望bar.cpp
也会被重新编译。不要尝试手动跟踪标头依赖关系,而是使用Advanced Auto-Dependency Generation文章中描述的方法之一。我还在我的earlier answers中描述了其中一个。