简体   繁体   English

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

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

I have two files "create-exercise.cpp" and "exercise.hpp".我有两个文件“create-exercise.cpp”和“exercise.hpp”。 I want to write a makefile to use gnu++17 and g++ to compile them.我想编写一个 makefile 来使用 gnu++17 和 g++ 来编译它们。 exercise.hpp is included in create-exercise.cpp.练习.hpp 包含在 create-exercise.cpp 中。 I only want to get a binary out of create-exercise.cpp.我只想从 create-exercise.cpp 中得到一个二进制文件。 the command I would use is g++ -std=gnu++17 create-exercise.cpp -o create-exercise and it works well.我会使用的命令是g++ -std=gnu++17 create-exercise.cpp -o create-exercise并且它运行良好。 I tried using the following in a make file.我尝试在 make 文件中使用以下内容。

CXXFLAGS=-Wall -std=gnu++17

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

but that generated the following g++ -Wall -std=gnu++17 create-exercise.cpp exercise.hpp -o create-exercise I don't want exercise.hpp to be included in the compilation command.但这生成了以下g++ -Wall -std=gnu++17 create-exercise.cpp exercise.hpp -o create-exercise我不希望exercise.hpp包含在编译命令中。 I also tried to use the following instead.我也尝试使用以下内容。

CXXFLAGS=-Wall -std=gnu++17

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

That generated g++ -Wall -std=gnu++17 -c -o create-exercise.o create-exercise.cpp .生成的g++ -Wall -std=gnu++17 -c -o create-exercise.o create-exercise.cpp I don't want the -c flag.我不想要-c标志。 because when I try to run create-exercise.o that results in permission denied error.因为当我尝试运行create-exercise.o会导致权限被拒绝错误。 I tried the following as well:我也尝试了以下方法:

CXXFLAGS=-Wall -std=gnu++17

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

but when I edit exercise.hpp make says 'create-exercise.o' is up to date.但是当我编辑exercise.hpp make 说'create-exercise.o' is up to date. and doesn't recompile it.并且不重新编译它。 what should I do?我该怎么办?

The rule to write in your makefile would be:在你的 makefile 中写入的规则是:

create-exercise.o: exercise.hpp

This is a rule without a recipe, and it simply adds one more prerequisite ( exercise.hpp ) to the target create-exercise.o , ie, whenever exercise.hpp changes, create-exercise.o should be rebuilt.这是一个没有配方的规则,它只是在目标create-exercise.o添加了更多的先决条件( exercise.hpp ),即,每当exercise.hpp发生变化时,就应该重建create-exercise.o

However, the problem when providing that rule is that GNU Make assumes create-exercise.o is an object file generated from a C source file when building create-exercise .但是,提供该规则时的问题在于,GNU Make 假定create-exercise.o是在构建create-exercise时从 C 源文件生成的目标文件。 Therefore, it doesn't link the C++ library but the C library instead, that's why you are having the liking error of undefined reference to std::cout .因此,它不链接 C++ 库,而是链接 C 库,这就是为什么您会遇到对std::cout的未定义引用的喜欢错误。

GNU Make has the following implicit rule for generating an executable from a C++ source file: GNU Make 有以下隐含规则,用于从 C++ 源文件生成可执行文件:

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

You can use that rule's recipe to build create-exercise from creating-exercise.o and still treat creating-exercise.o as an object file that was generated from a C++ source file:您可以使用该规则的配方从creating-exercise.o构建create-exercise并且仍然将creating-exercise.o视为从 C++ 源文件生成的目标文件:

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

The whole makefile would be then:整个makefile将是:

CXXFLAGS = -Wall -std=gnu++17 

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

create-exercise.o: exercise.hpp

The target create-exercise also becomes the default goal because it's the first rule in the makefile.目标create-exercise也成为默认目标,因为它是 makefile 中的第一条规则。 It's the target to build if you don't specify any to make .如果您没有指定任何 to make它就是要构建的目标。

You can do this:你可以这样做:

CXXFLAGS = -Wall -std=gnu++17

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

create-exercise.o: exercise.hpp

This says: build create-exercise from the object file create-exercise.o , if it's changed.这表示:从目标文件create-exercise.o构建create-exercise create-exercise.o ,如果它已更改。 And it says rebuild create-exercise.o if the header file exercise.hpp changes;如果头文件exercise.hpp发生变化,它会说rebuild create-exercise.o it's not right to modify or rebuild a source file if a header changes.如果标头更改,则修改或重建源文件是不对的。 It's the object file that depends on the header.它是依赖于标头的目标文件

Make has a number of built in rules. Make 有许多内置规则。 Among them are rules that know how to link a program but unfortunately that assumes your object files were built from C files, so if you're using C++ you have to create a specific recipe.其中包括知道如何链接程序的规则,但不幸的是,假设您的目标文件是从 C 文件构建的,因此如果您使用 C++,您必须创建一个特定的配方。 But you can still use GNU make's default variables.但是您仍然可以使用 GNU make 的默认变量。

It also knows how to build a .o file from a .cpp file on its own: you don't need to write that recipe.它还知道如何根据自己的.cpp文件构建.o文件:您不需要编写该配方。

I am not sure, but maybe try to include the .hpp file instead of compiling it with the other file.我不确定,但也许尝试包含 .hpp 文件,而不是用其他文件编译它。 You can do so by using g++ *.cpp -I * .hpp -o output你可以使用 g++ *.cpp -I * .hpp -o output

Try it out and let me know if it works for you.试试看,让我知道它是否适合你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM