C++ 如何使用makefile独立编译和更新一个文件夹中的所有文件
我有一个包含几个.cpp文件的文件夹,例如a.cpp、B.cpp和C.cpp。它们都是相互独立的。我可以将A.cpp编译成A.o,然后再编译成二进制文件A。B.cpp和C.cpp也是如此 我想写一个makefile,可以一次编译所有这些文件。将来,如果有一些新文件(如D.cpp)放入此文件夹,makefile仍然可以自动处理它 我当前的文件是C++ 如何使用makefile独立编译和更新一个文件夹中的所有文件,c++,c,makefile,C++,C,Makefile,我有一个包含几个.cpp文件的文件夹,例如a.cpp、B.cpp和C.cpp。它们都是相互独立的。我可以将A.cpp编译成A.o,然后再编译成二进制文件A。B.cpp和C.cpp也是如此 我想写一个makefile,可以一次编译所有这些文件。将来,如果有一些新文件(如D.cpp)放入此文件夹,makefile仍然可以自动处理它 我当前的文件是 CC=g++ CFLAGS=-c -Wall LDFLAGS= SOURCES=$(wildcard *.cpp) OBJECTS=$(SOURCES:.
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=$(SOURCES:.cpp=)
all: $(SOURCES) $(OBJECTS) $(EXECUTABLE)
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) $(@:.o=.cpp) -o $@
$(EXECUTABLE): $(SOURCES)
$(CC) $(LDFLAGS) $(@:=.o) -o $@
问题是,一旦一个.cpp文件被更改或添加到文件夹中,如果我这样做,所有其他文件都将被更新和重新编译
请让我知道如何解决这个问题
谢谢。将
后缀:.o.cpp
放在所有行的上方
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=$(SOURCES:.cpp=)
.SUFFIXES: .o .cpp
all: $(SOURCES) $(OBJECTS) $(EXECUTABLE)
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) $(@:.o=.cpp) -o $@
$(EXECUTABLE): $(SOURCES)
$(CC) $(LDFLAGS) $(@:=.o) -o $@
附加的
用这个
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=$(SOURCES:.cpp=)
.SUFFIXES: .o .cpp
all: $(EXECUTABLE)
.cpp.o:
$(CC) $(CFLAGS) $(@:.o=.cpp) -o $@
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
您不需要将$(源)或$(对象)放入all
。你必须写在下面
目的地:来源
对于大约.suffix
和.cpp.o
,这是一个特别的例子。它作为.SOURCE.DESTINATION:
您的makefile将每个源文件列为每个可执行文件和每个对象文件的先决条件
它也不喜欢将对象文件作为可执行文件的先决条件(这意味着make无法自动为您构建它们)
这些就是问题所在
所有这些都说明你根本不需要这个makefile中的规则
一个刚刚创建的文件
CC=g++
CXXFLAGS=-c -Wall
将允许您从A.cpp
运行make A
并生成A
(尽管它不需要生成A.o
)。如果您不需要设置CC
或cxflags
(或者不介意在命令行上设置它们),那么从a.cpp
构建a
甚至不需要makefile
$ mkdir test
$ cd test
$ ls
$ touch A.cpp
$ make CC=g++ CXXFLAGS='-c -Wall' A
g++ -c -Wall A.cpp -o A
但是如果你让它做一个o,它会的
$ make CC=g++ CXXFLAGS='-c -Wall' A.o
g++ -c -Wall -c -o A.o A.cpp
此时make将尝试从A.o
构建A
$ make CC=g++ CXXFLAGS='-c -Wall' A
g++ A.o -o A
要恢复对make
构建所有可执行文件的支持,您需要一行代码,如:
all: $(subst .cpp,,$(wildcard *.cpp))
如果您确实希望手动指定所有内容(并强制.o
构建),那么您需要类似的内容(使用and)
然后,您可以编写make
来构建它们,并make
来构建特定的代码。您只需更改all:
行,然后删除它后面的所有其他行
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=$(SOURCES:.cpp=)
all: $(OBJECTS) $(EXECUTABLE)
如果不需要创建.o
文件,还可以从all:
中删除$(对象)
,以及定义它的行。这样就不需要为链接行重新定义$(CC)
,但需要将-Wall
添加到$(cxflags)
给你带来悲伤的两条线是:
$(OBJECTS): $(SOURCES)
$(EXECUTABLE): $(SOURCES)
第一种说法是“每个对象文件都依赖于每个源文件;如果任何源文件发生更改,则每个对象文件都已过时”。第二种说法同样适用于可执行文件
make
知道如何直接从源文件构建可执行文件;您不需要对象文件作为中介
我将从all
行中删除$(OBJECTS)
(因为您实际上不需要对象文件)
然后,您可以删除我标识的行以及它们后面的命令(删除问题中显示的最后四行非空行)
如果仍希望能够创建所有对象文件,请添加:
objects: $(OBJECTS)
并使用生成对象
将它们全部生成
FWIW:创建对象的编译规则应该直接指定-c
,而不是将其包含在$(CFLAGS)
宏中。然后,构建可执行文件的编译规则可以(也应该)使用$(CFLAGS)
(以及$(LDFLAGS)
和$(LDLIBS)
)
对象编译行中的-o$@
基本上是不必要的,至少在我的经验中是这样。无论如何,C编译器都会生成$@
。如果源代码不在当前目录中,这可能很重要,但这并不是您得到的场景
一般来说,最好是简单地使用内置规则,这样你就不必像${:.o=.cpp}
这样的晦涩咒语是正确的。对于大多数版本的make
,内置规则将与我展示的非常相似(使用make-p
找出它们与make
的关系)和GNUmake
有使用%.o:%.cpp
符号的现代规则,而所示的代码没有假设。不,这并不能解决这里的问题。你是说头文件吗?我的意思是$(可执行):$(源代码)
在许多级别上都是错误的。$(对象):$(源代码)
也是错误的。这些都是造成问题的原因。我正在阅读有关后缀规则的链接。感谢您的帮助。此示例仅在“std”make初始化文件可用时有效。并且它不能正确处理头文件中的更改,也不能正确处理用户头文件与c文件位于不同目录中的情况当前目录。如果没有.PHONY:all行,它将抱怨无法创建“all”file@user3629249:我承认这不是makefiles的通用解决方案。它是针对这个特定问题的。。虚假:只有当所有文件存在时,才有必要使用all
来阻止make不做任何事情。make wi如果没有它,我不会给出一个无法创建all
文件的错误…至少在GNU Make 3.81
中,新版本可能会添加该健全性检查。请注意-c
标志的位置和$(CFLAGS
)的使用。在静态规则中使用$*
总是让我措手不及(特别是因为它取决于“可识别后缀”的大小)。@EtanReisner:我想你可能是对的;最好
$(OBJECTS): $(SOURCES)
$(EXECUTABLE): $(SOURCES)
objects: $(OBJECTS)
$(OBJECTS):
$(CC) -c $(CFLAGS) $(@:.o=.cpp) -o $@
$(EXECUTABLE):
$(CC) -o $@ $(CFLAGS) $@.cpp $(LDFLAGS) $(LDLIBS)