如何为包含头文件的目标编写 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
文件:你不需要写那个配方。
我有两个文件 "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
文件:你不需要写那个配方。