protoc初识

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 to google::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 to Person::~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 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: /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 to google::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 to google::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 1

LNK1104 无法打开文件“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 库相关,它是一种广泛使用的数据压缩库。

解决方法:

  1. 确保你的项目包含了 zlib 的库文件。如果你使用的是 Visual Studio,你可以通过项目属性中的链接器设置来添加 zlib 的库文件。

  2. 如果你使用的是预编译的 zlib 库文件,确保路径正确,并且库文件被正确地添加到项目中。

  3. 如果你是从源代码构建 zlib,确保 zlib 的源代码被编译并且生成的库文件能被链接器找到。

  4. 确保你的项目中包含了正确的头文件,这样编译器才能正确识别 _deflate 函数的声明。

  5. 如果你在使用第三方库或者框架,确保遵循了它们的文档来正确地链接库文件。

简而言之,你需要确保 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平台上链接静态库运行

未完待续

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值