C++ Makefile不';t检查头文件中的更新

C++ Makefile不';t检查头文件中的更新,c++,makefile,compilation,header-files,C++,Makefile,Compilation,Header Files,我认为我的makefile很好,但后来我尝试只更新一个头文件并重新编译我的库,但它没有改变任何东西 如何使其工作并重新编译h文件中的代码 我的生成文件: SHELL=/bin/sh 源文件目录=-I./../frmwrk/-I./../Utils/ CXX=g++ CXXFLAGS=$(源文件目录)-std=c++17-rdynamic-fPIC-g-Wall LDFLAGS=-shared LIBS_DIR=../../LIBS/ LIB_NAME=libIni.so 目标=$(库目录)$(库

我认为我的makefile很好,但后来我尝试只更新一个头文件并重新编译我的库,但它没有改变任何东西

如何使其工作并重新编译h文件中的代码

我的生成文件:

SHELL=/bin/sh
源文件目录=-I./../frmwrk/-I./../Utils/
CXX=g++
CXXFLAGS=$(源文件目录)-std=c++17-rdynamic-fPIC-g-Wall
LDFLAGS=-shared
LIBS_DIR=../../LIBS/
LIB_NAME=libIni.so
目标=$(库目录)$(库名称)
源=$(shell echo*.cpp)
标题=$(shell echo*.h)
对象=$(源:.cpp=.o)
LINK_LIBS=-lFrmwrk-lUtils
前缀=$(DESTDIR)/usr/local
BINDIR=$(前缀)/bin
全部:$(目标)
$(目标):$(对象)$(标题)
$(CXX)$(CXXFLAGS)-L$(LIBS_DIR)$(LDFLAGS)-o$(TARGET)$(OBJECTS)$(HEADERS)$(LINK_LIBS)
清洁:
rm-f*.o$(目标)/*.so
rm-rf$(目标)
这仅在头文件更改时强制重新链接<代码>使不知道,C++源文件包含哪个头文件。code>make只知道头文件中明确声明的依赖项。此处所述的唯一依赖项是可执行文件
$(TARGET)
,它依赖于头文件

例如,为了在包含
声明.h
时强制重新编译
main.o
,因为
main.cpp
包含
声明.h
,您必须明确:

main.o: declarations.h
这将指示
make
declarations.h
发生更改时,从
main.cpp
重新生成
main.o

手动跟踪由于头文件不可缩放的更改而需要重建的对象模块<代码>当然,对任何与C++相关的知识都不了解,因此,您必须手动跟踪所有依赖项,但这又不可缩放。


这里的解决方案是迁移到一些更高级别的构建工具,如GNU autoconf和automake,它们将为您编写
Makefile
,完成一系列使用编译器标志转储依赖项的规则,并为您自动更新规则。您可以始终使用相同的编译器标志(有一些标志,没有autoconf和automake,你可以自己构建所有的脚手架。但是为什么要麻烦呢,autoconf automake什么时候可以为你做呢?

你更改了哪个标题?我个人更喜欢为每个文件提供更详细或明确的标题依赖项列表。每个文件都不会有相同的标题文件依赖项(或者不太可能)。您声明所有对象都具有相同的头文件依赖项,这可能不是真的。如果您希望makefile只生成已更改的文件,则需要单独列出对象及其依赖项。否则,您就失去了makefile的用处(即,如果一个头文件发生更改,您将重建所有内容,而不仅仅是包含头文件的CPP文件)。Sams答案提供了很多细节,但只是为了非常清楚,当您编写类似于
$(目标):$(OBJECTS)$(HEADERS)
的规则时,它告诉您要创建特定的目标,
$(TARGET)如果
$(对象)
$(标题)
中的任何文件较新,则应重新生成
。但这只是重新链接二进制文件。该规则没有说明需要重新生成对象文件(重新编译源代码)如果有任何头更改。为此,您必须声明对象及其头之间的依赖关系。比
SOURCES=$(shell echo*.cpp)
更有效的是
SOURCES:=$(通配符*.cpp)
我同意autoconf/automake将为您完成所有这些工作,但它们的工作并不是微不足道的。另一个简单的自动相关性计算选项,只需GCC或clang即可完成,不需要额外的工具:
main.o: declarations.h