更好地理解makefile——在这种情况下如何生成.o文件
Understanding a makefile better - How the .o file gets generated in this case
我目前有以下makefile(我使用的是一个在线教程的例子),它很有效,但我对此有一些问题:
# *****************************************************
# Variables to control Makefile operation
CXX = g++
CXXFLAGS = -Wall -g
test: main.o car.o student.o house.o
$(CXX) $(CXXFLAGS) -o test main.o car.o student.o house.o
objcopy --only-keep-debug test test.debug
main.o: student.h house.h main.cpp
$(CXX) $(CXXFLAGS) -c main.cpp
car.o: car.h
student.o: student.h car.h
house.o: house.h
clean:
rm -rf *.o test *.debug
这是我对这里发生的事情的理解,如果我错了,请纠正我。当最初调用测试目标时,它会查找第一个依赖项main.o
。它可以是文件,也可以是目标。由于没有名为main.o
的文件,它将查找main.o
作为目标。一旦找到作为目标的main.o,它就会查找依赖项student.h house.h main.cpp
,因为这些依赖项是作为一个文件存在的,然后执行配方(命令),即$(CXX) $(CXXFLAGS) -c main.cpp
。这是我不明白的部分。当出现第二个依赖car.o
turn时,make查找car.h并找到它,但没有命令告诉它生成.o文件。这里是如何生成.o文件的?
make包含几个隐式规则。这意味着make拥有关于如何从.cpp文件创建.o文件的内置知识,而无需明确告诉它如何创建。
来自文件:
编译C++程序
n.o由n.cc、n.cpp或n.C,配方形式为"$(CXX)$(CPPFLAGS)$(CXXFLAGS)-C"。我们鼓励您对C++源文件使用后缀".cc",而不是'.C'
你可能会认为这是一个内置规则,看起来很像:
%.o : %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
点击此处阅读更多关于这些隐含规则的信息。
有一个内置规则,用于从.cpp文件生成.o文件。
你已经告诉它,is对car.h有一个额外的依赖,但不是如何制造car.o,所以它又回到了内置规则,car.h是一个附加的依赖。
你可以更改
main.o: student.h house.h main.cpp
$(CXX) $(CXXFLAGS) -c main.cpp
至
main.o: student.h house.h
它也会使用内置规则来构建它。这里记录了它。
如果您没有同时运行objcopy命令,您也可以使用内置规则使测试成为二进制的。
代替
test: main.o car.o student.o house.o
$(CXX) $(CXXFLAGS) -o test main.o car.o student.o house.o
你可以使用
test: main.o car.o student.o house.o
大多数make
(和类似的)程序都预先定义了隐式规则,用于将源文件(具有许多常见扩展名中的任何一个)转换为对象文件(使用默认扩展名)。
通常,这相当于这样的东西:
.c.o:
$(CC) $(CFLAGS) -o $*.o -c $*.c
.cc.o:
$(CXX) $(CXXFLAGS) -o $*.o -c $*.cc
对于其他常见的扩展有更多,因此它不仅知道如何将大多数典型的扩展(.c、.cc、.cpp、.c等)编译为.o文件,而且还隐式地获取一些变量的内容,您可以将其指定为一组标志,以便在编译器这样做时传递给它。
至于这些规则的细节:像.cc.o:
这样的规则是一个隐式规则——它基本上说"如果你有一个.cc文件,你可以使用这个规则从中创建一个.o文件"。它们被用作一种后盾——如果你有一个明确的规则来告诉你如何创建某个特定的.o文件,make
会优先使用它——但如果没有明确的规则,它可以依靠隐式规则。
$*
是一个内置的宏,它扩展到源文件的基本名称(没有扩展名)。其中有许多仅用于源的基本名称($*
)和源文件的全名($<
)。还有很多其他类似的自动变量,但据我所见,大多数人很少使用它们,以至于他们必须在需要使用它们时查找它们。
- 生成文件不对文件使用隐式规则
- 生成一个生成文件,该生成文件使用Automake在一个步骤中编译和链接所有源文件
- sqlite3 和生成文件中的链接出现问题
- 将生成文件转换为 CMakeLists.txt等效项
- 如何为包含头文件的目标编写生成文件?
- 如何在生成文件中添加多个标头 (HDR) 和对象?
- 生成文件:动态源文件名和对象目录
- C++单个生成文件多个二进制文件
- 递归地将FEATURE_FLAG导出到生成文件、CPP 和头文件
- 如何从构建 libgpio.so 的生成文件构建libgpio.a
- 将共享库的搜索路径更改为生成文件中提供的 rpath
- 修改生成文件以简化框架 #include 路径
- 用于构建 cuda .so 文件(共享库)的生成文件
- 无法从 SO 文件调用 SO 文件的函数 - C++生成文件
- 生成文件:6:目标'all'的配方在 Ubuntu-16.04 上失败
- 生成文件"relink"意味着什么?
- C++ 生成文件未检测到 .h 文件中的更改
- 为什么这不会在当前目录中生成文件?
- 生成文件中隐式规则中的 -c 标志出错
- C++生成文件错误"implicit entry/start for main executable"