【Protoc】VS2019 (VS平台) 使用 CMake 编译安装、使用 Protobuf 库
背景:工作中需要使用到 protobuf,看了一些教程,感觉都不是很适合,便自己总结一些
开发环境:
- Win 10
- VS2019
- CMake 3.24.2
- Protobuf 3.21.12 (Protoc 版本必须于 Protobuf 版本一致)
MinGW 版本的编译在之后有空再研究。
https://stackoverflow.com/questions/9243816/how-to-build-googles-protobuf-in-windows-using-mingw
Update: 2023.09.05
使用 Vcpkg 进行统一包管理
请按照官网文档搭建本地的 vcpkg,or 参考本篇博客:Here
# Poweshell 切换到 vcpkg 根目录下
.\vcpkg install protobuf:x64-windows
.\vcpkg install protobuf:x86-windows
# CMakeLists
# 保存可能会有 warning, 不必在意
find_package(protobuf CONFIG REQUIRED)
target_link_libraries(Test PRIVATE protobuf::libprotoc protobuf::libprotobuf protobuf::libprotobuf-lite)
# 接下来的操作如出一辙
# 即 使用 proto 生成 .cc .h 文件, main 中调用
前期工作准备
-
下载 Protobuf
到
Protobuf
Github 的Release
下载 \(Protobuf\ cpp\) 版本:https://github.com/protocolbuffers/protobuf/releases/tag/v21.12
(注意,最新的版本可能不包含cpp版本,此处选择了版本3.21.12,如果下载最新all版本,按照以下流程走可能会在CMake configure时因为cmake文件夹中缺少CMakeLists.txt而报错。)
到上述链接找到Protocol Buffers v21.12,下载名为protobuf-cpp-3.21.12.zip文件解压,将文件夹protobuf-3.21.12移动到 D盘 (盘符根据自己实际情况)。
-
下载 Protoc 并配置环境变量
protoc是.proto文件的编译器,它可以将.proto文件生成你想要语言对应的类。如果protoc版本和protobuf版本不一致将会导致错误,因此还是到上述官方Repo下载protoc-21.12-win64.zip:
https://github.com/protocolbuffers/protobuf/releases/tag/v21.12
下载完毕后解压将其 bin 目录添加至 Path
# CMD 验证 $ protoc --version libprotoc 3.21.12
-
CMake 下载安装
本文不涉及,但其操作也很简单,去找到安装包下载即可
# CMD 验证 $ cmake --version cmake version 3.24.2 CMake suite maintained and supported by Kitware (kitware.com/cmake).
使用 CMake 生成 Probuf 依赖库(Libs)
-
打开 CMake GUI (如果熟悉 CMake 命令也可自行编译)
选择 Probuf 项目位置和编译结果存放位置
-
点击下方的configure,选择Visual Studio的版本2019以及平台 x64,并点击Finish。
这里请根据每个人的实际情况选择,
比如 VS2015、VS2017;
Win32、X64
-
如果出现Configuration done则表示配置成功(警告可忽略),
-
然后点击Generate,没有出错的话会出现如下信息:
Generating done
在上述设置过的输出目录
D:/DevFile/protobuf-3.21.12/build
下会出现 protobuf.sln,使用自己选择的IDE版本打开。双击打开它,在Solution Explorer中依次找到
libprotobuf libprotoc protoc # 并右击 Build # Key 此处我们在Debug x64模式下 # 有需要的请切换成 Release x64 # 或者自己选定的 win32
编译完成以后将在 sln
文件的同级输出目录 Debug
中找到编译成功的 lib
等文件
博主个人将其 CV 到合适的位置
至此,所需的 Protobuf
库就准备好了。
在测试项目中使用 Protobuf
使用 IDE (这里使用 VS2019)中创建一个 C++ 空项目,在其文件夹下新建一个 .proto 文件并命名为 addressbook.proto
。 文件内容来自 Google 官网文档:Here
syntax = "proto2";
package tutorial;
message Person {
optional string name = 1;
optional int32 id = 2;
optional string email = 3;
enum PhoneType {
PHONE_TYPE_UNSPECIFIED = 0;
PHONE_TYPE_MOBILE = 1;
PHONE_TYPE_HOME = 2;
PHONE_TYPE_WORK = 3;
}
message PhoneNumber {
optional string number = 1;
optional PhoneType type = 2 [default = PHONE_TYPE_HOME];
}
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
编译.proto文件
此处使用 .proto
文件编译器 protoc
编译文件以生成相应的类,可供项目使用(ptotoc的安装以及环境变量配置此处未提及)。
# CMD
cd ${项目文件夹路径PWD}
# 生成addressbook.proto相应的类addressbook.pb.h和addressbook.pb.cc在同一目录下
protoc --cpp_out=./ addressbook.proto
# 注意其中的空格代表同目录下生成
# 指令中cpp表示生成C++类,也可替换成python或者java等
由于 VS2019 并不会自动添加文件,需要自己手动添加生成的 .h 和 .cc 文件
设置项目属性
Key:首先保证自己的IDE环境是和编译环境一致,即使用 Debug 模式下 x64
接下来的属性配置也是如此
打开项目属性管理器,在 Debug | x64 右键编辑属性
- C/C++ -> 代码生成 -> 运行库:使用
多线程调试 DLL(/MDd)
- C/C++ -> 预处理器 -> 预处理器定义:新增
_SCL_SECURE_NO_WARNINGS
- 链接器 -> 常规 -> 附加库目录:新增编译得到 Debug 目录(其中有 Libs 文件),
D:\Soft\Language\protobuf-3.21.12\VC142\debug
- 链接器 -> 输入 -> 附件依赖项:新增
libprotobufd.lib
将 Protobuf 安装目录下的 google
文件夹 D:\DevFile\protobuf-3.21.12\src\google
复制到项目文件夹下
为了区分,我放在了 Google
中
- C/C++ -> 常规 -> 附加包含目录:新增
D:\Coding\VS2019\Project2\Project2\Google
至此,点击OK项目属性页面就设置完成了。
编写并运行测试代码
// main.cpp
// 代码来源:https://www.cnblogs.com/windsun/p/12543066.html
#include <iostream>
#include <fstream>
#include "addressbook.pb.h"
using namespace std;
int main(int argc, char** argv) {
tutorial::Person p1;
p1.set_id(1);
p1.set_name("Jerry");
p1.set_email("jerry@mail.com");
// serialization
string resultAfterSerialization;
p1.SerializeToString(&resultAfterSerialization);
cout << "after serialization: " << resultAfterSerialization << endl;
tutorial::Person p2;
if (!p2.ParseFromString(resultAfterSerialization)) {
cerr << "failed to parse Person." << endl;
return -1;
}
cout << "after deserialization: " << endl;
cout << "id: " << p2.id() << endl;
cout << "name: " << p2.name() << endl;
cout << "email: " << p2.email() << endl;
}
代码写好以后点击运行即可看到如下输出: