Makefile命令 - 学习

tech2022-07-10  109

在开发中,源文件依赖于.proto文件编译后的.pb.c文件,通过一次命令就能执行编译.proto文件以及编译源文件的动作:

两步编译proto文件和源文件

1. 编译.proto文件

PROTO_DIR = ./proto OUT_DIR = ./out mkproto: mkout//将./proto/%.proto文件编译成./out/%.pb.h和./out/%.pb.c $(PROTOC) $(PROTOC_OPTS) --proto_path=$(PROTO_DIR) --nanopb_out=$(OUT_DIR) $(PROTO_DIR)/*.proto mkout://没有out目录则创建 mkdir -p $(OUT_DIR)

2. 编译源文件

CSRCS = main.c CSRCS += $(wildcard $(OUT_DIR)/*.pb.c) CSRCS += $(NANOPB_DIR)/pb_decode.c CSRCS += $(NANOPB_DIR)/pb_encode.c CSRCS += $(NANOPB_DIR)/pb_common.c demo : $(CSRCS) $(CC) $(CFLAGS) -o $@ $^

如上先执行make mkproto,然后执行make demo可以成功编译,输出demo文件

一步编译proto文件和源文件

如上是两步不同独立的命令执行,就想着是否可以把两步合成一步来操作,如下:

all: mkproto demo

执行make all命令之后,却出错了,如下:

cc -Wall -Werror -g -O0 -I/nanopb-nanopb-0.3.9.2 -o demo main.c /nanopb-nanopb-0.3.9.2/pb_decode.c /nanopb-nanopb-0.3.9.2/pb_encode.c /nanopb-nanopb-0.3.9.2/pb_common.c//源码定义中并没有.proto文件中生成的.pb.c文件 /tmp/ccZBChYb.o:在函数‘encode_request’中: /nanopb-nanopb-0.3.9.2/examples/demo/main.c:47:对‘Request_fields’未定义的引用 /tmp/ccZBChYb.o:在函数‘decode_request’中: /nanopb-nanopb-0.3.9.2/examples/demo/main.c:67:对‘Request_fields’未定义的引用 collect2: error: ld returned 1 exit status Makefile:29: recipe for target 'demo' failed make: *** [demo] Error 1

说明为CSRCS赋值时out目录下并未生成pb.c文件

方案1

于是换个思路,使用字符串匹配的方式,获取到.pb.c文件路径对应的字符串变量

PB_CSRCS = $(patsubst %.proto, $(OUT_DIR)/%.pb.c, $(notdir $(wildcard $(PROTO_DIR)/*.proto))) CSRCS = main.c CSRCS += $(PB_CSRCS) CSRCS += $(NANOPB_DIR)/pb_decode.c CSRCS += $(NANOPB_DIR)/pb_encode.c CSRCS += $(NANOPB_DIR)/pb_common.c

此时执行make all就可以成功得到输出文件demo了;

完整的Makefile文件1
include ../../extra/nanopb.mk CFLAGS = -Wall -Werror -g -O0 CFLAGS += -I$(NANOPB_DIR) .PHONY: demo clean mkout mkproto $(OUT_DIR)/%.pb.c PROTO_DIR = ./proto OUT_DIR = ./out PB_CSRCS = $(patsubst %.proto, $(OUT_DIR)/%.pb.c, $(notdir $(wildcard $(PROTO_DIR)/*.proto))) CSRCS = main.c CSRCS += $(PB_CSRCS) CSRCS += $(NANOPB_DIR)/pb_decode.c CSRCS += $(NANOPB_DIR)/pb_encode.c CSRCS += $(NANOPB_DIR)/pb_common.c all: mkproto demo demo : $(CSRCS) $(CC) $(CFLAGS) -o $@ $^ mkproto: mkout $(PROTOC) $(PROTOC_OPTS) --proto_path=$(PROTO_DIR) --nanopb_out=$(OUT_DIR) $(PROTO_DIR)/*.proto mkout: mkdir -p $(OUT_DIR) clean: rm -rf $(OUT_DIR) demo
方案1命令log输出:

执行make或make all后命令log输出如下:

mkdir -p ./out protoc --plugin=protoc-gen-nanopb=/nanopb-nanopb-0.3.9.2/generator/protoc-gen-nanopb --proto_path=./proto --nanopb_out=./out ./proto/*.proto cc -Wall -Werror -g -O0 -I/nanopb-nanopb-0.3.9.2 -o demo main.c out/user_info.pb.c out/nanopb.pb.c out/network_request.pb.c /nanopb-nanopb-0.3.9.2/pb_decode.c /nanopb-nanopb-0.3.9.2/pb_encode.c /nanopb-nanopb-0.3.9.2/pb_common.c

方案2

还有一种方案就是将$(OUT_DIR)/%.pb.c作为一个target,如此便可直接执行make 或make demo就能获取到输出

$(OUT_DIR)/%.pb.c: $(PROTO_DIR)/%.proto mkout $(PROTOC) $(PROTOC_OPTS) --proto_path=$(PROTO_DIR) --nanopb_out=$(OUT_DIR) $<
完整的Makefile文件2
include ../../extra/nanopb.mk CFLAGS = -Wall -Werror -g -O0 CFLAGS += -I$(NANOPB_DIR) .PHONY: demo clean mkout $(OUT_DIR)/%.pb.c PROTO_DIR = ./proto OUT_DIR = ./out PB_CSRCS = $(patsubst %.proto, $(OUT_DIR)/%.pb.c, $(notdir $(wildcard $(PROTO_DIR)/*.proto))) CSRCS = main.c CSRCS += $(PB_CSRCS) CSRCS += $(NANOPB_DIR)/pb_decode.c CSRCS += $(NANOPB_DIR)/pb_encode.c CSRCS += $(NANOPB_DIR)/pb_common.c demo : $(CSRCS) $(CC) $(CFLAGS) -o $@ $^ $(OUT_DIR)/%.pb.c: $(PROTO_DIR)/%.proto mkout $(PROTOC) $(PROTOC_OPTS) --proto_path=$(PROTO_DIR) --nanopb_out=$(OUT_DIR) $< mkout: mkdir -p $(OUT_DIR) clean: rm -rf $(OUT_DIR) demo
方案2命令log输出:

执行make 或make demo后命令log输出:

mkdir -p ./out protoc --plugin=protoc-gen-nanopb=/nanopb-nanopb-0.3.9.2/generator/protoc-gen-nanopb --proto_path=./proto --nanopb_out=./out proto/user_info.proto protoc --plugin=protoc-gen-nanopb=/nanopb-nanopb-0.3.9.2/generator/protoc-gen-nanopb --proto_path=./proto --nanopb_out=./out proto/nanopb.proto protoc --plugin=protoc-gen-nanopb=/nanopb-nanopb-0.3.9.2/generator/protoc-gen-nanopb --proto_path=./proto --nanopb_out=./out proto/network_request.proto//$(OUT_DIR)/%.pb.c这个命令是一个.proto文件一个命令 cc -Wall -Werror -g -O0 -I/nanopb-nanopb-0.3.9.2 -o demo main.c out/user_info.pb.c out/nanopb.pb.c out/network_request.pb.c /nanopb-nanopb-0.3.9.2/pb_decode.c /nanopb-nanopb-0.3.9.2/pb_encode.c /nanopb-nanopb-0.3.9.2/pb_common.c

执行以上会在Makefile当前目录下生成demo文件,执行./demo就可以运行你的程序了

测试demo 附件:nanopb-test-demo
参考:

http://c.biancheng.net/view/7112.html

最新回复(0)