如何为包含头文件的目标编写 makefile?

How to write makefile for a target that includes a header file?

我有两个文件 "create-exercise.cpp" 和 "exercise.hpp"。我想编写一个 makefile 来使用 gnu++17 和 g++ 来编译它们。 exercise.hpp 包含在 create-exercise.cpp 中。我只想从 create-exercise.cpp 中得到一个二进制文件。我将使用的命令是 g++ -std=gnu++17 create-exercise.cpp -o create-exercise 并且效果很好。我尝试在 make 文件中使用以下内容。

CXXFLAGS=-Wall -std=gnu++17

create-exercise: create-exercise.cpp exercise.hpp

但是生成了以下 g++ -Wall -std=gnu++17 create-exercise.cpp exercise.hpp -o create-exercise 我不希望 exercise.hpp 包含在编译命令中。我也尝试使用以下代替。

CXXFLAGS=-Wall -std=gnu++17

create-exercise.o: create-exercise.cpp exercise.hpp

即生成g++ -Wall -std=gnu++17 -c -o create-exercise.o create-exercise.cpp。我不想要 -c 标志。因为当我尝试 运行 create-exercise.o 时会导致权限被拒绝错误。我也尝试了以下方法:

CXXFLAGS=-Wall -std=gnu++17

create-exercise.o: create-exercise.cpp exercise.hpp
    $(CXX) $(CXXFLAGS) create-exercise.cpp -o create-exercise.o

但是当我编辑 exercise.hpp 时,make 说 'create-exercise.o' is up to date. 并且没有重新编译它。我该怎么办?

我不确定,但也许尝试包含 .hpp 文件而不是将其与其他文件一起编译。您可以使用 g++ *.cpp -I *.hpp -o output

试试看,如果它适合你,请告诉我。

在您的 makefile 中编写的规则是:

create-exercise.o: exercise.hpp

这是一个没有配方的规则,它只是在目标create-exercise.o上增加了一个先决条件(exercise.hpp),即,每当exercise.hpp改变时,create-exercise.o 应该重建。

然而,提供该规则时的问题是 GNU Make 假定 create-exercise.o 是在构建 create-exercise 时从 C 源文件生成的目标文件。因此,它不是 link C++ 库,而是 C 库,这就是为什么您遇到对 std::cout.

未定义引用的喜欢错误

GNU Make 具有以下用于从 C++ 源文件生成可执行文件的隐式规则:

%: %.cpp
#  commands to execute (built-in):
   $(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@

您可以使用该规则的配方从 creating-exercise.o 构建 create-exercise,并且仍然将 creating-exercise.o 视为从 C++ 源文件生成的目标文件:

create-exercise: create-exercise.o
    $(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@

整个 makefile 将是:

CXXFLAGS = -Wall -std=gnu++17 

create-exercise: create-exercise.o
    $(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@

create-exercise.o: exercise.hpp

目标 create-exercise 也成为默认目标,因为它是 makefile 中的第一条规则。如果您没有指定 make.

,它就是要构建的目标

你可以这样做:

CXXFLAGS = -Wall -std=gnu++17

create-exercise: create-exercise.o
        $(LINK.cpp) $^ $(LDLIBS) -o $@

create-exercise.o: exercise.hpp

这表示:从 object 文件 create-exercise.o 构建 create-exercise,如果它已更改。如果 header 文件 exercise.hpp 发生变化,它会说重建 create-exercise.o;如果 header 发生变化,则修改或重建 源文件 是不对的。 object 文件 依赖于 header.

Make 有许多内置规则。其中包括知道如何 link 程序的规则,但不幸的是,这些规则假设您的 object 文件是从 C 文件构建的,因此如果您使用 C++,则必须创建一个特定的配方。但是你仍然可以使用 GNU make 的默认变量。

它也知道如何从一个 .cpp 文件自己构建一个 .o 文件:你不需要写那个配方。