我有一个基于配置文件生成多个 C++ .h 和 .cpp 文件的脚本。该脚本还生成一个名为“Makefile.inc”的文件,该文件包含一个具有所需目标文件名的变量,用于生成的 .cpp 文件。
Makefile.inc 文件示例(所有路径都是绝对路径):
MESSAGE_OBJS = \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/error-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/challenge-request-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/challenge-response-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/login-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/get-game-list-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/game-list-response-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/join-game-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/connect-to-game-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/leave-game-message.o
使用这个问题中的答案作为基础,我创建了以下 Makefile:
# Include the generated makefile for messages.
# This includes a variable with all message targets
include atlarge/messages/Makefile.inc
# Create a variable with all source targets
LIBOBJS = \
atlarge/exceptions.o \
atlarge/message-factory.o \
atlarge/envelope.o \
atlarge/client.o \
atlarge/user.o \
atlarge/atlarge-protocol.o \
atlarge/atlarge-gameserver.o \
$(MESSAGE_OBJS)
CXXFLAGS += -W -Wall -I. -g -O3 -MD \
`pkg-config jansson --cflags` \
`libgcrypt-config --cflags` \
`pkg-config glib-2.0 --cflags` \
-fPIC -DDEBUG -DENABLE_LOGGING
PREFIX = /usr/local
# TODO use pkg-config for jansson
LDLIBS += -lm -ljansson -latlarge-util `libgcrypt-config --libs` `pkg-config glib-2.0 --libs`
LDFLAGS += -shared -L/usr/local/lib
# Include automatically generated dependencies
-include $(LIBOBJS:.o=.d)
all: libatlarge.so
# If the message Makefile doesn't exist yet, generate it
atlarge/messages/Makefile.inc: atlarge/messages/messages.conf
python ../common/messagegen.py -o ./atlarge/messages/ atlarge/messages/messages.conf
libatlarge.so: $(LIBOBJS)
$(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS)
clean:
@rm -f *.o
@rm -f atlarge/*.o
@rm -f atlarge/messages/*.o
@rm -f atlarge/messages/*.cpp
@rm -f atlarge/messages/*.h
@rm -f atlarge/messages/Makefile.inc
@rm -f atlarge/*.d
@rm -f atlarge/messages/*.d
@rm -f *.d
@rm -f ../common/*.d
@rm -f ../common/*.o
@rm -f *.a
@rm -f *.so
@rm -f tags
install: libatlarge.so
@install -m 0644 $^ $(PREFIX)/lib
@install -m 0755 -d $(PREFIX)/include/atlarge
@install -m 0755 -d $(PREFIX)/include/atlarge/messages
@install -m 0644 -D atlarge/*.h $(PREFIX)/include/atlarge
@install -m 0644 -D atlarge/messages/*.h $(PREFIX)/include/atlarge/messages
@ldconfig
@echo "Installed"
.PHONY: all clean install splint messages
如您所见,我首先包含生成的 Makefile.inc。然后定义一个包含所有库目标文件的变量,该变量使用生成的 Makefile.inc 中声明的变量。之后,声明了一些带有编译器标志的变量。
为了使用Makefile remaking,我为生成的 Makefile.inc 添加了一个目标规则,因此如果 Makefile.inc(配置文件)的依赖关系比 Makefile.inc 更新,它会重新生成,并且 Make 将自行重启。
所以这是目标:
- 检查是否需要(重新)生成 Makefile.inc。
- 包括它
- 在主 Makefile 的 $LIBOBJS 变量中使用 Makefile.inc 中的变量。
这实际上有效。如果我更新 messages.conf 文件,Make 会检测到这一点,并将运行 python 脚本。然后它将自行重启,包含新的 Makefile.inc,然后继续编译。
但是这里出现了不起作用的部分:如果我不更新 messages.conf 文件,而只更新 $LIBOBJS 列表中默认的 .h 或 .cpp 文件,Make 将不会继续编译。
例如,如果更改 client.cpp 而没有其他文件,我会收到以下错误:
make: `atlarge/exceptions.o' is up to date.
好吧,很好,你发现 exceptions.o 是最新的,但我更改了 client.cpp,那么你为什么不开始编译那个呢?为什么 make 看到 LIBOBJS 中的第一个目标是最新的后立即退出?
谁知道是什么原因造成的,有什么解决办法?是否有更好的方法来处理使用 makefile 生成代码?
提前致谢。
注意:我也使用 gcc 生成的依赖文件,在我添加代码生成之前工作正常,所以我认为这不是问题。