Makefile 将在文件更改时链接文件,但不会重新编译更改的源文件

Makefile will link files upon a file change, but not recompile the source file that changed

本文关键字:文件 新编译 编译 源文件 链接 Makefile      更新时间:2023-10-16

我有以下制作文件,它似乎运行良好:

HDRS =  include/config.h include/opcode_def.h include/x86lib.h include/x86lib_internal.h
CXX ?= g++
AR ?= ar

TEST_CC ?= i386-elf-gcc
TEST_CFLAGS ?= -fdata-sections -ffunction-sections

CXX_VM_SRC = vm/x86lib.cpp vm/modrm.cpp vm/device_manager.cpp vm/cpu_helpers.cpp vm/ops/strings.cpp vm/ops/store.cpp vm/ops/maths.cpp 
          vm/ops/groups.cpp vm/ops/flow.cpp vm/ops/flags.cpp vm/ops/etc.cpp
CXX_VM_OBJS = $(subst .cpp,.o,$(CXX_VM_SRC))
CXX_TESTBENCH_SRC = testbench/testbench.cpp
CXX_TESTBENCH_OBJS = $(subst .cpp,.o,$(CXX_TESTBENCH_SRC))

CXXFLAGS ?= -Wall -g3 -fexceptions -fPIC -Wall
CXXFLAGS += -DX86LIB_BUILD -I./include
VERSION=1.1
VM_OUTPUTS = libx86lib.a libx86lib.so.$(VERSION)
OUTPUTS = $(VM_OUTPUTS) x86testbench 
default: build
build: $(OUTPUTS)
libx86lib.a: $(CXX_VM_OBJS) $(CXX_VM_SRC)
    ar crs libx86lib.a $(CXX_VM_OBJS)
libx86lib.so.$(VERSION): $(CXX_VM_OBJS) $(CXX_VM_SRC)
    $(CXX) -shared $(CXX_VM_OBJS) -o libx86lib.so.$(VERSION)
x86testbench: $(CXX_TESTBENCH_OBJS) $(VM_OUTPUTS)
    $(CXX) $(CXXFLAGS) -static -o x86testbench $(CXX_TESTBENCH_OBJS) -lx86lib -L.
$(CXX_TESTBENCH_OBJS): $(HDRS)
    $(CXX) $(CXXFLAGS) -c $*.cpp -o $@
$(CXX_VM_OBJS): $(HDRS)
    $(CXX) $(CXXFLAGS) -c $*.cpp -o $@
clean:
    rm $(CXX_VM_OBJS) $(OUTPUTS) $(CXX_TESTBENCH_OBJS)

我的问题是,如果我更改一个文件,例如"vm/x86lib.cpp",那么它将重新链接最终输出等,但它不会重新编译 vm/x86lib.o。我不知道如何将这种重新编译要求表达到$(CXX_VM_OBJS)构建规则。

如何解决此问题,以便它将重新编译我的源文件并重新链接它们?

注意:如果我$(CXX_VM_SRC)作为对$(CXX_VM_OBJS)的依赖,那么每当单个文件更改时,它都会重新编译每个文件。另外,我只关心GNU Make和OSX/Linux环境。

正如其他人指出的那样,当源更改时,makefile 不会重建任何对象文件的原因是您的规则:

$(CXX_VM_OBJS): $(HDRS)
    ...

没有提到源文件是先决条件。以及添加它们的建议解决方案的原因:

$(CXX_VM_OBJS): $(HDRS) $(CXX_VM_SRC)
    ...

导致 Make 在任何源文件更改时重建所有源文件,这正是此规则所要求的。它使所有源文件成为任何目标文件的先决条件。

处理此问题的正确方法是使用静态模式规则:

$(CXX_VM_OBJS): %.o: %.cpp $(HDRS)
    ...

我会为您的$(CXX_TESTBENCH_OBJS)规则推荐相同的内容;即使它现在仅适用于一个对象文件,但很明显您正在考虑稍后添加其他对象文件。

在CXX_VM_OBJS的依赖项列表中,尝试添加希望对象依赖的源文件名,例如:

$(CXX_VM_OBJS): $(HDRS) vm/x86lib.cpp
    $(CXX) $(CXXFLAGS) -c $*.cpp -o $@