protoc初识
参考资料
https://blog.csdn.net/qq_46637011/article/details/135085568
https://blog.csdn.net/qq_39400324/article/details/134172333
一 前期准备
windows查看proto是否安装好及版本号
protoc --version
windows查看路径下文件
dir
想在124.50机器上安装protobuf,执行build.sh脚本的时候报错:
configure.ac:109: error: possibly undefined macro: AC_PROG_LIBTOOL
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
使用如下安装命令报错
apt-get install libtool
-bash: apt-get: command not found
百度查到这个指令,用于centOS系统
sudo yum install libtool
安装成功
二、实现功能
2.1 124.43实现效果
在124.43上实现了proto的反序列化
但是过程很曲折,甚至反序列化成功的时候我还是懵的,而且感觉其中还是有问题,但是聊胜于无,
root@0002:~/zhuyfTest/protobuf/myFirstTest/bu# ./myFirstTest
10, man, lucy, 32
ʹ▒▒<windows.h>ͷ▒ļ▒▒▒▒▒▒ļ▒
ʹ▒▒<dirent.h>ͷ▒ļ▒▒▒▒▒▒ļ▒
Hello, World!
CMakeList.txt文件
下面有
main函数
void test() {
//对象初始化
Person p;
p.set_id(10);
p.set_age(32);
p.set_sex("man");
p.set_name("lucy");
// 序列化对象 p,最终得到一个字符串
std::string output;
p.SerializeToString(&output);
// 反序列化数据
Person pp;
pp.ParseFromString(output);
std::cout << pp.id() << ", " << pp.sex() << ", " << pp.name() << ", " << pp.age() << std::endl;
}
int main() {
test();
//std::string outputPath = "D:\\AppData\\CLion\\myFirstTest";
std::string outputPath = "/data2/test/";
std::cout << "使用<windows.h>头文件遍历文件" << std::endl;
//findFiles(outputPath);
std::cout << "使用<dirent.h>头文件遍历文件" << std::endl;
direntPrint(outputPath);
//GetAllFileNames(outputPath);
std::cout << "Hello, World!" << std::endl;
return 0;
}
2.2 解决两个报错
下面描述一下整个过程
首先我在Clion上调试失败了,都找不到远程服务器了。直接本地调试报错
D:\APP\CLion\CLion 2023.2.2\bin\mingw\bin/ld.exe: cannot find -lprotobuf: No such file or directory
D:\APP\CLion\CLion 2023.2.2\bin\mingw\bin/ld.exe: cannot find -lprotoc: No such file or directory
collect2.exe: error: ld returned 1 exit status
我就直接在124.50机器上直接cmake,但是报错
/usr/bin/ld: CMakeFiles/main.cpp.dir/main.cpp.o: in function
test()': /data2/myFirstTest/main.cpp:172: undefined reference to
google::protobuf::MessageLite::SerializeToString(std::__cxx11::basic_string<char, std::char_traits, std::allocator >*) const’
/usr/bin/ld: /data2/myFirstTest/main.cpp:176: undefined reference togoogle::protobuf::MessageLite::ParseFromString(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' /usr/bin/ld: /data2/myFirstTest/main.cpp:175: undefined reference to
Person::~Person()’
/usr/bin/ld: /data2/myFirstTest/main.cpp:164: undefined reference toPerson::~Person()' /usr/bin/ld: /data2/myFirstTest/main.cpp:175: undefined reference to
Person::~Person()’
/usr/bin/ld: /data2/myFirstTest/main.cpp:164: undefined reference to `Person::~Person()’
我已查看protoc --version,查不到版本号,我试着用protobuf的编译脚本编译protobuf,编译好了查看版本号还是没有版本号,还是不行。
#!/bin/bash
set -ex
PREFIX_INC_PATH=$(cd "$(dirname "$0")";pwd)
mv protobuf-21.9 protobuf
chmod -R 777 protobuf
cd protobuf
./autogen.sh
./configure --prefix=$PREFIX_INC_PATH/install --with-pic
make -j 32
make install
export LD_LIBRARY_PATH=${PREFIX_INC_PATH}/install/lib:$LD_LIBRARY_PATH
我就跑到124.43上试试,因为124.43上可以查到protoc版本号
protoc --version
libprotoc 3.21.9
我执行cmake编译,有报错,而且报错也和124.50差不多,找不到定义
undefined reference to
google::protobuf::MessageLite::SerializeToString(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const' /usr/local/bin/ld: /root/zhuyfTest/protobuf/myFirstTest/main.cpp:176: undefined reference to
google::protobuf::MessageLite::ParseFromString(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&)’
/usr/local/bin/ld: /root/zhuyfTest/protobuf/myFirstTest/main.cpp:175: undefined reference toPerson::~Person()' /usr/local/bin/ld: /root/zhuyfTest/protobuf/myFirstTest/main.cpp:164: undefined reference to
Person::~Person()’
/usr/local/bin/ld: /root/zhuyfTest/protobuf/myFirstTest/main.cpp:175: undefined reference toPerson::~Person()' /usr/local/bin/ld: /root/zhuyfTest/protobuf/myFirstTest/main.cpp:164: undefined reference to
Person::~Person()’
但是编译出可执行文件了,我一执行,成功打印出信息。
现在起码是看到效果了,再继续看看。
目前的代码情况是虽然打印出结果了,但是还是有报错信息,报错信息如下
/usr/local/bin/ld: DWARF error: could not find variable specification at offset 2094
/usr/local/bin/ld: DWARF error: could not find variable specification at offset 20f0
/usr/local/bin/ld: DWARF error: could not find variable specification at offset 2158
/usr/local/bin/ld: DWARF error: could not find variable specification at offset e83f
/usr/local/bin/ld: DWARF error: could not find variable specification at offset e84b
...
...
CMakeFiles/main.cpp.dir/main.cpp.o: in function `test()':
/root/zhuyfTest/protobuf/myFirstTest/main.cpp:172: undefined reference to `google::protobuf::MessageLite::SerializeToString(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const'
/usr/local/bin/ld: /root/zhuyfTest/protobuf/myFirstTest/main.cpp:176: undefined reference to `google::protobuf::MessageLite::ParseFromString(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/local/bin/ld: /root/zhuyfTest/protobuf/myFirstTest/main.cpp:175: undefined reference to `Person::~Person()'
/usr/local/bin/ld: /root/zhuyfTest/protobuf/myFirstTest/main.cpp:164: undefined reference to `Person::~Person()'
/usr/local/bin/ld: /root/zhuyfTest/protobuf/myFirstTest/main.cpp:175: undefined reference to `Person::~Person()'
针对第一个问题,/usr/local/bin/ld: DWARF error: could not find variable specification at offset 2094
解决办法是将CMakeList.txt语句
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -D_DEBUG")
//改成
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -D_DEBUG")
原因不知道,参考:https://blog.csdn.net/chen134225/article/details/126316536
第二个问题的原因是我的CmakeList问题,
有误版CmakeList
cmake_minimum_required(VERSION 3.16.5)
get_filename_component(ProjectId ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(REPLACE " " "_" ProjectId ${ProjectId})
project(${ProjectId} CXX)
#set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++11 -pthread")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -D_DEBUG")
if (PLATFORM STREQUAL WINDOWS OR PLATFORM STREQUAL windows)
SET(PLATFORM windows)
add_definitions(
-DWIN32
)
else ()
SET(PLATFORM linux)
add_definitions(
-Dlinux
)
endif()
include_directories(../myFirstTest/3rd/protobuf/auto/include)
include_directories(../myFirstTest/3rd/protobuf/src)
include_directories(../myFirstTest/include)
aux_source_directory(../myFirstTest/3rd/protobuf/auto/src protobufSrc)
link_directories(../myFirstTest/3rd/protobuf/lib/linux)
file(GLOB files "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
foreach(file ${files})
get_filename_component(name ${file} NAME)
add_executable(${name} ${file}
include/protobufProtocal.h)
endforeach()
add_executable(myFirstTest
${protobufSrc}
main.cpp)
TARGET_LINK_LIBRARIES(myFirstTest protobuf protoc)
成功版本
project(${ProjectId} CXX)
#set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++11 -pthread")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -D_DEBUG")
if (PLATFORM STREQUAL WINDOWS OR PLATFORM STREQUAL windows)
SET(PLATFORM windows)
add_definitions(
-DWIN32
)
else ()
SET(PLATFORM linux)
add_definitions(
-Dlinux
)
endif()
include_directories(../myFirstTest/3rd/protobuf/auto/include)
#include_directories(../myFirstTest/3rd/protobuf/src/google/protobuf)
include_directories(../myFirstTest/3rd/protobuf/src)
include_directories(../myFirstTest/include)
aux_source_directory(../myFirstTest/3rd/protobuf/auto/src protobufSrc)
link_directories(../myFirstTest/3rd/protobuf/lib/linux)
#file(GLOB files "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
#foreach(file ${files})
# get_filename_component(name ${file} NAME)
# add_executable(${name} ${file})
#endforeach()
add_executable(myFirstTest
${protobufSrc}
main.cpp)
TARGET_LINK_LIBRARIES(myFirstTest protobuf protoc)
问题出现在这里
file(GLOB files "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
foreach(file ${files})
get_filename_component(name ${file} NAME)
add_executable(${name} ${file})
endforeach()
注释掉这些语句,然后重新cmake,再make,就能编译成功了,执行./myFirstTest,执行成功
root@0002:~/zhuyfTest/protobuf/myFirstTest/buildTest# ./myFirstTest
10, man, lucy, 32
Hello, World!
2.4 windows环境Clion远程调试实现效果
以上就是在linux环境下将protobuf序列化和反序列化实现。然后就回到一开始出现的问题,windows环境Clion没有执行成功。
报错
D:\APP\CLion\CLion 2023.2.2\bin\mingw\bin/ld.exe: CMakeFiles/myFirstTest.dir/3rd/protobuf/auto/src/firstVersion.pb.cc.obj: in function
Person::Person(Person const&)': D:/AppData/CLion/myFirstTest/3rd/protobuf/auto/src/firstVersion.pb.cc:112: undefined reference to
google::protobuf::internal::ArenaStringPtr::Set(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&, google::protobuf::Arena*)’
D:\APP\CLion\CLion 2023.2.2\bin\mingw\bin/ld.exe: D:/AppData/CLion/myFirstTest/3rd/protobuf/auto/src/firstVersion.pb.cc:120: undefined reference togoogle::protobuf::internal::ArenaStringPtr::Set(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, google::protobuf::Arena*)' D:\APP\CLion\CLion 2023.2.2\bin\mingw\bin/ld.exe: CMakeFiles/myFirstTest.dir/3rd/protobuf/auto/src/firstVersion.pb.cc.obj: in function
Person::Clear()‘:
D:/AppData/CLion/myFirstTest/3rd/protobuf/auto/src/firstVersion.pb.cc:175: undefined reference togoogle::protobuf::internal::ArenaStringPtr::ClearToEmpty()' D:\APP\CLion\CLion 2023.2.2\bin\mingw\bin/ld.exe: D:/AppData/CLion/myFirstTest/3rd/protobuf/auto/src/firstVersion.pb.cc:176: undefined reference to
google::protobuf::internal::ArenaStringPtr::ClearToEmpty()’
D:\APP\CLion\CLion 2023.2.2\bin\mingw\bin/ld.exe: CMakeFiles/myFirstTest.dir/3rd/protobuf/auto/src/firstVersion.pb.cc.obj: in function `Person::_InternalParse(char const*, google::protobuf::internal::ParseContext*)':
这时候如果把下面的语句注释掉,
link_directories(../myFirstTest/3rd/protobuf/lib/linux)
则不出现上述报错,出现下述报错
显示信息
D:\APP\CLion\CLion 2023.2.2\bin\mingw\bin/ld.exe: cannot find -lprotobuf: No such file or directory
D:\APP\CLion\CLion 2023.2.2\bin\mingw\bin/ld.exe: cannot find -lprotoc: No such file or directory
我认为这边是因为linux环境下无法使用.a文件,需要配置lib静态库文件导致的。
然后我又想到再试下远程调试,还是不能远程调试。我把setting里面的Cmake反复切换也是不行,然后突然想到是不是应该把工程中的几个名称如[cmake-build-debug-*]等文件夹删掉?
删除文件夹试了一下,可以远程调试,执行成功,成功打印出反序列化数据。
2.5 windows环境CLion本地实现效果
2.5.1 安装cmake
cmake安装参考教程:https://blog.csdn.net/jlm7689235/article/details/131087421
windows编译protobuf静态库文件参考教程:https://blog.csdn.net/g9208/article/details/102640357
下载cmake:https://cmake.org/download/网址
安装cmake后在cmd.exe中查看版本号:
C:\Users>cmake --version
cmake version 3.26.0
cmake安装成功
2.5.2 cmake编译protobuf
开始windows平台安装protobuf,cmake编译方法如下
cmake编译protobuf,编译报错
Could NOT find ZLIB (missing: ZLIB_LIBRARY ZLIB_INCLUDE_DIR)
CMake Error at cmake/tests.cmake:13 (message):
Cannot find third_party/googletest directory that’s needed to build tests.
If you use git, make sure you have cloned submodules:
处理上述问题参考教程:https://jingyan.baidu.com/article/c843ea0b588a5636931e4aa8.html
https://blog.csdn.net/junxuezheng/article/details/129823728
2.5.3 安装protobuf依赖组件zlib
帖子中说要安装Zlib,安装zlib下载源码:http://www.zlib.net/zlib-1.3.1.tar.xz
打开cmd,进入zlib源码路径,指向包含CMakeList.txt文件夹路径,依次执行一下指令
cmake -B build或者cmake . //构建
cmake --build build //编译
cmake install //安装,但是报错了
安装教程中的方法,我也用vs打开zlib.sln文件,右击INSTALL-生成,但是程序出错。所以现在的问题卡在zlib windows编译。
而且我试着全局搜索zlib.lib文件,很多工程中都有。然后我不得不联想,protobuf是依赖zlib的,但是实际上我看了protobuf的编译脚本,没有zlib的语句?难道zilb需要在protobuf之前编译?看工程是这样的,zlib在protobuf前编译的,但是是不是一定这样?也不确定。
windows安装zlib:https://blog.csdn.net/Strive_For_Future/article/details/134080450
https://blog.csdn.net/weixin_43779276/article/details/122221288
安装zlib也是使用cmake编译,cmake版本3.26.0,vs版本2017,zlib版本3.13.0。编译过程分为分为三步:
第一步cmake-gui执行Configure
第二步执行generate
第三步打开vs2017, ALL_BUILD执行生成。
第三步出了问题报错
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 LNK1104 无法打开文件“Debug\zlibd.lib” example E:\trafficLight\protobuf\windowsLib\install-zlib\zlib-new\zlib-1.3.1\build\LINK 1
错误 LNK1104 无法打开文件“Debug\zlibd.lib” minigzip E:\trafficLight\protobuf\windowsLib\install-zlib\zlib-new\zlib-1.3.1\build\LINK 1LNK1104 无法打开文件“debug\zlib.lib”
错误 RC1004 unexpected end of file found zlib C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Auxiliary\VS\include\unistd.h 5错误 RC1004 unexpected end of file found
解决办法:修改unistd.h文件,增加一行空行。修改后可以对ALL_BUILD执行生成。编译出zlib.lib文件
再执行INSTALL报错
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 MSB3073 命令“setlocal
解决办法:用管理员权限打开vs2017,再次执行INSTALL生成即可。参考链接:https://blog.csdn.net/Strive_For_Future/article/details/134093160
------ 已启动生成: 项目: INSTALL, 配置: Debug x64 ------
1>-- Install configuration: “Debug”
1>-- Installing: C:/Program Files/zlib/lib/zlibd.lib
1>-- Installing: C:/Program Files/zlib/bin/zlibd.dll
1>-- Installing: C:/Program Files/zlib/lib/zlibstaticd.lib
1>-- Installing: C:/Program Files/zlib/include/zconf.h
1>-- Installing: C:/Program Files/zlib/include/zlib.h
1>-- Installing: C:/Program Files/zlib/share/man/man3/zlib.3
1>-- Installing: C:/Program Files/zlib/share/pkgconfig/zlib.pc
========== 生成: 成功 1 个,失败 0 个,最新 6 个,跳过 0 个 ==========
根据安装打印信息,zlib被成功安装。安装路径:C:\Program Files\zlib。
安装这个教程https://blog.csdn.net/weixin_43779276/article/details/122221288配置zlib环境变量
以上步骤进行完成后,对系统变量作如下设置:
1、添加系统变量:OSG_FILE_PATH,变量值为D:\OSG\OpenSceneGraph-Data(OSG所用Data)。
2、在PATH变量中添加:编译目录下的bin目录。
EMMM,Zlibwindows平台好像不需要配置环境变量
2.5.4 继续cmake编译protobuf
下面继续windows平台上cmake编译protobuf组件
cmake版本3.26.0, protobuf版本3.21.9
执行报错:
CMake Error at cmake/tests.cmake:13 (message):
Cannot find third_party/googletest directory that’s needed to build tests.
解决办法:修改protobuf的CmakeList.txt文件,修改以下语句
option(protobuf_BUILD_TESTS "Build tests" ON)
改为
option(protobuf_BUILD_TESTS "Build tests" OFF)
修改后可以正常编译。修改后需要重启Cmake。参考链接:https://blog.csdn.net/qq_31841023/article/details/133776635
继续编译protobuf,我又查了这篇帖子:https://blog.csdn.net/baidu_39630688/article/details/134376761
里面提及到
我选择了x64,根据自己的项目需求,选择x64 Win32 ARM之一
protobuf_BUILD_SHARED_LIBS:需选中该选项,则可编译动态链接库
protobuf_WITH_ZLIB:取消选中该选项
中间出错,取消选中ZLIB后正常。
尤其是里面提及的,protobuf_WITH_ZLIB:取消选中该选项。原来zlib编译依赖还可以取消选中。。。。
cmake编译后使用vs2017打开工程,执行生成报错
报错信息如下:
gzip_stream.obj : error LNK2019: 无法解析的外部符号 _deflate,该符号在函数 “private: int __thiscall google::protobuf::io::GzipOutputStream::Deflate(int)” (?Deflate@GzipOutputStream@io@protobuf@google@@AAEHH@Z) 中被引用
2>gzip_stream.obj : error LNK2019: 无法解析的外部符号 _deflateEnd,该符号在函数 “public: bool __thiscall google::protobuf::io::GzipOutputStream::Close(void)” (?Close@GzipOutputStream@io@protobuf@google@@QAE_NXZ) 中被引用
2>gzip_stream.obj : error LNK2019: 无法解析的外部符号 _inflate,该符号在函数 “private: int __thiscall google::protobuf::io::GzipInputStream::Inflate(int)” (?Inflate@GzipInputStream@io@protobuf@google@@AAEHH@Z) 中被引用
2>gzip_stream.obj : error LNK2019: 无法解析的外部符号 _inflateEnd,该符号在函数 “public: virtual __thiscall google::protobuf::io::GzipInputStream::~GzipInputStream(void)” (??1GzipInputStream@io@protobuf@google@@UAE@XZ) 中被引用
百度提及可能和zlib有关
error LNK2019: 无法解析的外部符号 _deflate,该符号在函数 "public: bool __this
错误解释:
error LNK2019: 无法解析的外部符号 _deflate
表示链接器在尝试创建最终的执行文件时找不到名为
_deflate的函数定义。这通常发生在使用了某个函数,但链接器在所有提供该函数的库中都找不到其实现。
_deflate` 函数通常与 zlib 库相关,它是一种广泛使用的数据压缩库。解决方法:
确保你的项目包含了 zlib 的库文件。如果你使用的是 Visual Studio,你可以通过项目属性中的链接器设置来添加 zlib 的库文件。
如果你使用的是预编译的 zlib 库文件,确保路径正确,并且库文件被正确地添加到项目中。
如果你是从源代码构建 zlib,确保 zlib 的源代码被编译并且生成的库文件能被链接器找到。
确保你的项目中包含了正确的头文件,这样编译器才能正确识别
_deflate
函数的声明。如果你在使用第三方库或者框架,确保遵循了它们的文档来正确地链接库文件。
简而言之,你需要确保 zlib 库被正确地添加到项目中,并且库文件能在链接时被找到和加载。
我尝试在vs工程配置zlib包含目录,但是还是会报错。
然后重新cmake,取消protobuf_WITH_ZLIB,重现编译可以成功。所以大概原因是zlib库没配置好。
2.5.6 Clion在windows环境实现protobuf功能
将protobuf的.lib拷贝到工程路径下,修改cmakeList.txt文件,运行失败。原因不确定。
2.5.6.1 曲线救国(先使用vs验证lib有效性)
vs使用protobuf静态库文件lib参考教程:https://blog.csdn.net/m0_55725535/article/details/134483603
1、新建vs工程,将3.21.9版本protobuf的源文件拷贝到工程路径下,以及将lib文件拷贝到工程路径下,配置工程
2、配置工程
C/C++常规 | 附件包含目录:添加需要用到的头文件 | |
---|---|---|
链接器常规 | 附件包含目录:添加lib文件路径 | |
链接器输入 | 附加依赖项:添加lib文件名 | |
3、生成解决方案报错
error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MT_StaticRelease”不匹配值“MD_DynamicRelease”(firstVersion.pb.obj 中)
解决方法:属性页——C/C++——代码生成——运行库——多线程MT改成多线程MD,修改后编译,运行成功。
10, man, lucy, 32
使用<windows.h>头文件遍历文件
使用<dirent.h>头文件遍历文件
Hello, World!
解决办法链接:https://blog.csdn.net/m0_55725535/article/details/134483603
所以lib文件没问题,就是自己CLion的CmakeList的配置有问题。
然后我又折腾了好一会Clion在windows平台上链接静态库运行,还是失败,先搁置再议吧。
2.5.7 Clion在windows平台上链接静态库运行
未完待续