通过代码生成,使文件目标始终是最新的
Makefile target always up to date with code generation
我有一个基于配置文件生成多个c++ .h和.cpp文件的脚本。这个脚本还生成一个名为"Makefile"的文件。,该文件包含一个变量,其中包含生成的.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重新生成,我为生成的Makefile包含了一个目标规则。因此,如果依赖于Makefile。. inc(配置文件)比Makefile更新。inc .,它会重新生成,Make会重新启动自己。这就是目标:
- 检查是否Makefile。需要(重新)生成inc .
- 包含它
- 在Makefile中使用变量。 在Makefile的$LIBOBJS变量中。
这实际上是可行的。如果我更新messages.conf文件,Make会检测到,并将运行python脚本。然后它将重新启动自己,包括新的Makefile。,然后继续编译。
但是这里有不工作的部分:如果我不更新messages.conf文件,而只更新$LIBOBJS列表中默认的。h或。cpp文件,Make将不会继续编译。
例如,如果alter client.cpp而没有其他文件,我会得到以下错误:
make: `atlarge/exceptions.o' is up to date.
嗯,是的,很好,你发现了例外。o是最新的,但是我修改了client.cpp,所以你为什么不开始编译那个呢?为什么make在看到LIBOBJS中的第一个目标是最新的后立即退出?
谁知道是什么原因造成的,有什么解决办法呢?也许有一个更好的方法来处理代码生成与makefiles?
提前感谢。
注意:我也使用由gcc生成的依赖文件,在我添加代码生成之前,它工作得很好,所以我不认为这是一个问题。
您需要将all
目标移动到include
之前。Make总是构建它在makefile中看到的第一个目标,除非您在命令行中给出了一个特定的目标。由于include
出现在任何目标之前,因此在Makefile.inc
中定义的第一个目标将是默认目标,当您运行make
时,它将被构建。这就是为什么它试图构建exceptions.o
,然后停止。如果您显式地运行make all
,它将按照您的期望工作。
目标文件对源文件的依赖关系还是头文件?是一个隐式规则如果.cpp
文件在同一文件中,则选择依赖项目录设置为.o
,但如果不是,则必须设置提供您自己的,或使用VPATH(参见手册中的§4.5.1)。和您还需要为包含生成依赖项,参见手册中§4.1.4。
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- C++A*算法并不总是在路径中具有目标节点
- 基于树莓pi的tensorflow lite量化ssd目标检测
- 为测试目标创建具有不同源文件夹的文件
- 使用源向量作为目标
- 原子读取是否保证读取最新值
- 是否可以用C++/WinRT将windows 10.0.14393作为目标
- 在 CMake 中为每个目标设置编译器/链接器标志
- qmake:检测目标位宽(32 位或 64 位)
- 如何在 CMake 中对目标依赖项进行分组?
- 我的目标是编写一个程序来计算和存储字符串在字符数组中出现的位置
- 如何为包含头文件的目标编写生成文件?
- 线性优化目标函数中的绝对值
- 制作文件:没有规则来制定目标:如何设置正确的规则?
- 字符串函数在目标C++上运行时C++返回空
- 如何定义自定义生成配置类型,其中通常是.exe的目标改为 DLL
- 请求最简单的 OpenMP 目标 GPU 示例
- LLVM 编译:目标的配方 '../lib/IR/Release+Asserts/Intrinsics.gen.tmp' failed
- 当目标指针不是基类的类型时,为什么允许dynamic_cast为多态类生成 null 指针?
- 通过代码生成,使文件目标始终是最新的