Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用makefile独立编译和更新一个文件夹中的所有文件_C++_C_Makefile - Fatal编程技术网

C++ 如何使用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:.

我有一个包含几个.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:.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
的关系)和GNU
make
有使用
%.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)