C++ 防止GNU Make在每次生成时生成protobuf代码

C++ 防止GNU Make在每次生成时生成protobuf代码,c++,protocol-buffers,gnu-make,C++,Protocol Buffers,Gnu Make,我有下面的Makefile,它在一些proto文件上运行Google的proto,生成代码并构建库 除了在每次运行make时生成代码外,一切都正常,尽管proto文件或其他文件没有任何更改。我如何防止这种情况 GEN_FLAG:=$(PROJECT_ROOT)/build/.etcd_protocols_gen ETCD=$(PROJECT_ROOT)/ext/etcd/ PROTOCOLS=$(ETCD)proto/ PROTO_FILES=$(shell find $(PROTOCOLS

我有下面的Makefile,它在一些
proto
文件上运行Google的
proto
,生成代码并构建库 除了在每次运行
make
时生成代码外,一切都正常,尽管
proto
文件或其他文件没有任何更改。我如何防止这种情况

GEN_FLAG:=$(PROJECT_ROOT)/build/.etcd_protocols_gen

ETCD=$(PROJECT_ROOT)/ext/etcd/
PROTOCOLS=$(ETCD)proto/

PROTO_FILES=$(shell find $(PROTOCOLS) -name \*.proto)
FILES=$(wildcard *.cc)
OBJS=$(patsubst %.cc,%.o,$(FILES))
LIB=$(BUILD_LIB_DIR)/libetcdclient.so

DIRS=proto

.PHONY: all
all: etcd-gen $(LIB)

-include $(FILES:.cc=.d)

.PHONY: etcd-gen
etcd-gen:
    $(Q)echo "Generating ETCD gRPC C++ sources"
    @ln -sf $(PROTOBUF_DIR)/libprotoc.so.16.0.0 $(PROTOBUF_DIR)/libprotoc.so.16
    @ln -sf $(PROTOBUF_DIR)/libprotobuf.so.16.0.0 $(PROTOBUF_DIR)/libprotobuf.so.16
    @LD_LIBRARY_PATH=$(PROTOBUF_DIR) $(PROTOBUF_DIR)/protoc -I $(PROTOCOLS) --cpp_out=. $(PROTO_FILES)
    @LD_LIBRARY_PATH=$(PROTOBUF_DIR) $(PROTOBUF_DIR)/protoc -I $(PROTOCOLS) --grpc_out=. --plugin=protoc-gen-grpc=$(PROJECT_ROOT)/ext/grpc/bin/grpc_cpp_plugin $(PROTO_FILES)
    @touch $(GEN_FLAG)

%.o: %.cc
    @echo "CC $<"
    $(Q)$(CC) $(CFLAGS) -c -o $@ $< -ldl
    $(Q)$(CC) -MM $(CFLAGS) -MF $*.d -MT $*.o $*.cc

$(LIB): $(OBJS)
    @echo "LD $@"
    $(Q)$(CXX) $(CXXFLAGS) -shared -Wl,-soname,$(notdir $(LIB)) -o $(LIB) $(OBJS) $(LFLAGS) -L$(PROTOBUF_DIR) -l:libprotobuf.so.16

clean:
    $(Q)rm -f *.d *.o *.pb.cc *.pb.h
    $(Q)rm -f $(BUILD_LIB_DIR)/libetcdclient.so
    $(Q)rm -f GEN_FLAG
GEN\u标志:=$(PROJECT\u ROOT)/build/.etcd\u protocols\u GEN
ETCD=$(项目根)/ext/ETCD/
协议=$(ETCD)协议/
PROTO_文件=$(shell查找$(协议)-名称\*.PROTO)
文件=$(通配符*.cc)
OBJS=$(patsubst%.cc、%.o、$(文件))
LIB=$(BUILD\u LIB\u DIR)/libetcdclient.so
DIRS=proto
冒牌货:全部
全部:etcd gen$(LIB)
-包括$(文件:.cc=.d)
.冒牌货:etcd gen
etcd-gen:
$(q)回波“生成ETCD GRPC C++源”
@ln-sf$(PROTOBUF_DIR)/libprotoc.so.16.0.0$(PROTOBUF_DIR)/libprotoc.so.16
@ln-sf$(PROTOBUF_DIR)/libprotobuf.so.16.0.0$(PROTOBUF_DIR)/libprotobuf.so.16
@LD_LIBRARY_PATH=$(PROTOBUF_DIR)$(PROTOBUF_DIR)/protoc-I$(协议)--cpp_out=$(原始文件)
@LD_LIBRARY_PATH=$(PROTOBUF_DIR)$(PROTOBUF_DIR)/protoc-I$(协议)——grpc_out=--plugin=protoc gen grpc=$(PROJECT\u ROOT)/ext/grpc/bin/grpc\u cpp\u plugin$(PROTO\u文件)
@触摸$(GEN_标志)
%.o:%.cc

@echo“CC$
make
将目标视为要生成的文件。因此,任何时间戳的比较都是依赖项与目标的依赖项的比较,以确定是否重建该文件

在您的案例中,make正在检查不存在的文件
etcd gen
的时间戳,并且由于该文件不存在或与源没有任何关系(源未列为依赖项),因此每次都会触发重建


您可以改为重新构造makefile,使您的
proto
源是
$(GEN\u标志)
的依赖项,并且
$(GEN\u标志)
的内容是一个目标。然后您可以声明
$(GEN\u标志)
etcd gen的依赖项

make
将目标视为要生成的文件。因此,对时间戳进行任何比较以确定是否重建该文件都是对依赖项与目标的依赖项进行比较

在您的案例中,make正在检查不存在的文件
etcd gen
的时间戳,并且由于该文件不存在或与源没有任何关系(源未列为依赖项),因此每次都会触发重建


您可以改为重新构造makefile,使您的
proto
源是
$(GEN\u标志)
的依赖项,并且
$(GEN\u标志)
的内容是一个目标。然后您可以声明
$(GEN\u标志)
etcd-gen的依赖项

实际上,
etcd-gen
被正确地标记为a,并且它的规则在每次不查找文件的情况下都会被调用,但是你对结果的判断当然是对的。实际上,
etcd-gen
被正确地标记为a,并且它的规则在每次不查找文件的情况下都会被调用,但是你是对的结果当然是对的。