Reputation: 63935
I have the following makefile which seems to work pretty well:
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)
My problem is that if I change a file, such as "vm/x86lib.cpp" then it will relink the final outputs and such, but it will not recompile vm/x86lib.o. I don't know how to express this recompile requirement to the $(CXX_VM_OBJS)
build rule.
How do I fix this so that it will recompile my the source files as well as relink them?
Note: if I put $(CXX_VM_SRC)
as a dependency on $(CXX_VM_OBJS)
, then it will recompile every file anytime a single file changes. Also, I'm only concerned about GNU Make and OSX/Linux environments.
Upvotes: 0
Views: 231
Reputation: 99172
As others have pointed out, the reason your makefile doesn't rebuild any object files when a source changes is that your rule:
$(CXX_VM_OBJS): $(HDRS)
...
doesn't mention that the source files are prerequisites. And the reason the proposed solution of adding them:
$(CXX_VM_OBJS): $(HDRS) $(CXX_VM_SRC)
...
causes Make to rebuild all source files when any source file changes, is that that is exactly what this rule demands. It makes all source files prerequisites of any object file.
The right way to handle this is with a static pattern rule:
$(CXX_VM_OBJS): %.o: %.cpp $(HDRS)
...
And I would recommend the same for your $(CXX_TESTBENCH_OBJS)
rule; even though it applies to only one object file now, it's clear that you are thinking of adding others later.
Upvotes: 4
Reputation: 82
In the dependency list for CXX_VM_OBJS, try to add the source filenames that you want the object to depend on, for example:
$(CXX_VM_OBJS): $(HDRS) vm/x86lib.cpp
$(CXX) $(CXXFLAGS) -c $*.cpp -o $@
Upvotes: 0