RabbitMQ C++客户端SimpleAmqpClient编译总结(32以及64位)

束雅达
2023-12-01

整个过程没有截图,使用为我的“印象笔记”不能传图,所以全是以文字形式描述,各位跟踪我的脚步,一般能走到末尾。

遇到的问题:

1、Cmake必须是2.8版本或以上

2、boost编译方式必须是默认动态编译库,使用静态库编译会报错(最终我重新编译boost库使用完全且默认动态方式:b2 toolset=msvc-14.0 threading=multi );

3、安装vs2015不完全,且编译vs2015要选择“ Visual Studio 14 2015 Win64”,而不是选择“ Visual Studio 15 2017 Win64”(指的是vs2017版本)

4、cmake-gui选择source code为“D:/soft/MQ/SimpleAmqpClient”,选择编译二进制路径“D:/soft/MQ/SimpleAmqpClient/build”

5、配置后configure,选择visual staudio 14 2015后,然后报错找不到boost库,需要配置BOOST_ROOT或BOOST_LIBRARY,这里直接点击按钮《Add Entry》然后添加BOOST_ROOT,选择环境变量类型为PATH,对应值为boost编译的路径,我这里选择的是“D:\boost_1_63_0”

 

编译过程:

1、下载SimpleAmqpClient

git克隆的路径为:https://github.com/alanxz/SimpleAmqpClient.git  

下载压缩包路径:https://codeload.github.com/alanxz/SimpleAmqpClient/zip/master

解压SimpleAmqpClient到: D:\soft\MQ\SimpleAmqpClient

 

2、安装boost库

这里我一直使用的是boost1.63,这里需要注意的是不能使用boost编译的st,也就是静态库,否则cmake编译报错,编译boost:

(1)进入boost解压目录,运行:bootstrap.bat,出现b2.exe和bjam.exe可执行编译工具

(2)打开命令行,进入到boost目录:cmd-->cd D:\boost_1_63_0-->D:

(3)编译boost库:b2 toolset=msvc-14.0 threading=multi,需要1个小时左右

 

3、CMake-gui编译

(1)安装cmake的windows版本,选择下载的版本在2.8以上

(2)打开cmake,选择SimpleAmqpClient中cmake.list所在的目录路径为源码路径

(3)设置编译后路径,在(2)路径基础后添加build即可

(4)选择configure按钮,选中visual studio 14 2015,确定后选择Add Entry添加环境变量设置BOOST_ROOT,类型为PATH,值为D:\boost_1_63_0

(5)选择Generate按钮开始生成。报错找不到 Required library Rabbitmqc NOT FOUND 说明SimpleAmqpClient依赖rabbitmq-c源码和库,故需要编译rabbitmq-c库

 

4、编译rabbitmq-c

(1)下载rabbitmq-c源码包:https://codeload.github.com/alanxz/rabbitmq-c/zip/v0.9.0

(2)下载rabbitmq-codegen源码包:https://codeload.github.com/rabbitmq/rabbitmq-codegen/zip/master 

          我这里下载的稳定版本的分支:https://codeload.github.com/rabbitmq/rabbitmq-codegen/zip/v3.7.x

(3)解压rabbitmq-c和rabbitmq-codegen,并将rabbitmq-codegen解压后重命名为codegen放到rabbitmq-c(原来已经有一个空codegen目录,覆盖即可)

(4)打开CMake-gui,设置源码目录:D:/soft/MQ/rabbitmq-c-0.9.0,设置编译库目录:D:/soft/MQ/rabbitmq-c-0.9.0/build

(5)configure编译选择vs2015,报错:Could NOT find OpenSSL,找不到openssl,这里我们不需要,去掉中间环境变量键值对的ENABLE_OPENSSL_SUPPORT后的复选框去掉;如果需要的话增加环境变量条目:OPENSSL_ROOT_DIR,设置对应路径即可;

        扩展:

        经过测试,只要拷贝对应的openssl到c盘,我这里用的库下载路径:链接:https://pan.baidu.com/s/1u-UrwjyynnjHoOQNQBmesw 密码:92i8

        不需要配置环境变量能自动扫描到openssl,但是生成的工程编译realse报错;

        a. 错误:error LNK2019: 无法解析的外部符号 __iob_func

        解决方法:在rabbitmq工程文件amqp_api.c文件中上方头文件包含目录下添加如下代码:

// VS2015下解决32位系统编译错误:error LNK2019: 无法解析的外部符号 __iob_func 

#if _MSC_VER>=1900

#include "stdio.h"

_ACRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned);

#ifdef __cplusplus

extern "C"

#endif

FILE* __cdecl __iob_func(unsigned i) {

       return __acrt_iob_func(i);

}

#endif /* _MSC_VER>=1900 */

        b. 错误:error LNK2019: 无法解析的外部符号 __vsnwprintf

        在linker中添加依赖库:legacy_stdio_definitions.lib

        c. 错误:error LNK2019: 无法解析的外部符号 __imp__CertFreeCertificateContext@4

        openssl静态库缺少密码学库,在linker中添加依赖库:Crypt32.lib

 

(6)再次点击configure,然后点击Generate即可

(7)使用vs2015打开build目录下的工程目录,全部编译即可生成21个项目库;

          库路径生成在build目录:build/librabbitmq/Debug/librabbitmq.4.lib

 

5、编译SimpleAmqpClient

(1)已经解决第三步中我们出现错误,打开CMake选择SimpleAmqpClient的源码目录和库目录;

        源码目录:D:/soft/MQ/SimpleAmqpClient

        编译目录:D:/soft/MQ/SimpleAmqpClient/build

(2)设置boost库目录:添加entry环境变量,设置path值为,BOOST_ROOT:D:\boost_1_63_0

(3)配置编译configure,选择vs2015,然后选择Generate生成vs2015解决方案;

(4)报错,找不到rabbitmq-c库,添加编译选项(rabbitmqc头文件目录和库目录-点击Add Entry按钮):

         Rabbitmqc_INCLUDE_DIR 路径值:D:/soft/MQ/rabbitmq-c-0.9.0/librabbitmq

         Rabbitmqc_LIBRARY           路径值:D:/soft/MQ/rabbitmq-c-0.9.0/build/librabbitmq/Release/librabbitmq.4.lib

(5)重新configure(两次红色消失),然后generate即可生成工程文件,vs2015打开解决方案

(6)编译报错,原因是因为依赖openssl库,将vs2015依赖的openssl配置到工程SimpleAmpqClient属性中:

        vc++目录:

        包含目录:C:\openssl_lib\win32-release\include

        库目录   :C:\openssl_lib\win32-release\lib

        连接器:输入添加openssl和密码学库以及vs2015连接静态库bug解决库:

                      libssl.lib

                      libcrypto.lib

                      Crypt32.lib

                      legacy_stdio_definitions.lib

(7)同样配置Realse和其他版本,然后选择对应版本(如Release版本)编译即可一次通过编译!

         最终在build/Release(根据选择定)目录下生成SimpleAmqpClient.2.dll和SimpleAmqpClient.2.lib

 

6、编译64

(1)编译openssl64位库

(2)编译64位动静态库rabbitmq-c-0.9.0,设置cmake的库输出路径:D:/soft/MQ/rabbitmq-c-0.9.0/build64

(3)编译64位impleAmqpClient动静态库,设置cmake的库输出路径:D:/soft/MQ/SimpleAmqpClient/build64

 

关于64位版本使用情况(cmake选择Visual Studio 14 2015 Win64,编译32bit则选择Visual Studio 14 2015):

(1)编译64位版本的openssl 1.1.x行不通-32位的可以,具体见我的文章,openssl1.0.x编译和openssl1.1.x编译的步骤和区别,所以此处更改为openssl1.0.x版本

(2)编译好后的openssl不是标准目录结构,标准目标是openssl的根目录下有include和lib两个文件夹,所以需要将openssl的inc32改为include,将out32改lib(用32为则改out32为lib,有空64则改out64为lib)

(3)boost编译输出到与32默认不同的stage/lib,目录,SimpleAmqpClient编译必须重新在连接器中设置boost库的目录,或临时更改成stage/lib(32的改成其他)--在linker的lib目录中修改,输入中也得修改;

(4)SimpleAmqpClient的依赖库必须设置openssl的库重新设置libssl.lib、libcrypto.lib、Crypt32.lib然后重新编译;

 

最后附上我最终编译出来的静态库链接,包含了rabbitmq-0.9.0c的静态库和openssl静态库以及对应的32和64的版本:

https://download.csdn.net/download/lixiang987654321/10557090

 

后增:为了解决SimpleAmqpClient.2.dll跨组件内存释放问题,解决方法如下:

由于SimpleAmqpClient封装的库用到了string等变量作为导出类接口,如果编译成DLL,在主进程调用改DLL的
时候,会出现组件内存申请与释放问题,会有如下情况发生:
(1)如果SimpleAmqpClient.DLL的多线程类型为/MD,主进程为/MD,那么DLL内存与主进程内存用的是主进行的内容,不存在这边申请,那边释放问题,所以进程不会出现崩溃问题;
(2)如果SimpleAmqpClient.DLL的多线程类型为/MT,则要求SimpleAmqpClient导出类不能有string等基本类型库,但是实际代码却已经写死,不便修改,MT进程调用MD会崩溃;
(3)如果SimpleAmqpClient为MT,主进程为MT,那么按道理说不会存在崩溃,但是实际测试结果:主进程为Debug模式,出现断言错误,确定后仍然不会有问题,主进程为Release模式则正常;

为了避免(1)和(2)的问题,解决方法是:
(1)主进程或调用SimpleAmqpClient.DLL进程多线程都设置为MT且为Release(测试可以通过且无错误提示框蹦出来-->header==xxx断言)
(2)主进程或调用进程为MD且只能调用多线程也为MD的SimpleAmqpClient.DLL,这种情况会导致主进程依赖很多vc库文件
(3)把SimpleAmqpClient编译成静态库的MT,然后主进程调用


动态库使用include头文件声明,静态库使用include-static里的头文件,原因件最后

使用方式:
(1)动态库

// 标准库
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string>
using namespace std;

// Boost库
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/serialization/singleton.hpp>
#include <boost/unordered_map.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/date_time.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/serialization/singleton.hpp>
#include <boost/chrono.hpp>
#include <boost/thread/condition.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/shared_array.hpp>

#include <SimpleAmqpClient/SimpleAmqpClient.h>
#pragma comment(lib, "SimpleAmqpClient.2.lib")

 

(2)静态库【重点注意,不是添加头文件就可以了,32bit编译不通过,64bit没有问题,原因是dll工程转static库工程问题】

// 标准库
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string>
using namespace std;

// Boost库
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/serialization/singleton.hpp>
#include <boost/unordered_map.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/date_time.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/serialization/singleton.hpp>
#include <boost/chrono.hpp>
#include <boost/thread/condition.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/shared_array.hpp>

#include <SimpleAmqpClient/SimpleAmqpClient.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "Crypt32.lib")
#pragma comment(lib, "libeay32.lib")
#pragma comment(lib, "ssleay32.lib")
#pragma comment(lib, "librabbitmq.4.lib")
#pragma comment(lib, "SimpleAmqpClient.2.lib")

重点问题:
dll工程转static工程方法
(1)将项目-->属性-->常规-->配置类型(父项:项目默认值)更改为静态库lib
(2)将项目-->属性-->常规-->目标文件扩展名(父项:常规)更改为.lib
(3)重点在这里:将dll类或函数的导出声明去掉,随意找到一个类,跳转到导出宏定义声明,这里找到的定义在
     \src\SimpleAmqpClient\Util.h
(4)更改宏定义为:
        #ifdef WIN32
        #ifdef SimpleAmqpClient_EXPORTS
        #define SIMPLEAMQPCLIENT_EXPORT /*__declspec(dllexport)*/
        #else
        #define SIMPLEAMQPCLIENT_EXPORT /*__declspec(dllimport)*/
        #endif
        #else
        #define SIMPLEAMQPCLIENT_EXPORT
        #endif
(5)最后编译生成静态库即可,否则报错提示dllimport,改关键字仅仅适用于dll,也就是存在改关键字会让vs误以为是动态库导入,所以不会以静态库方式导入,这样就会发生变异错误,提示找不到导出来构造函数。

 

快来成为我的朋友或合作伙伴,一起交流,一起进步!
QQ群:961179337
微信:lixiang6153
邮箱:lixx2048@163.com
公众号:IT技术快餐
更多资料等你来拿!

 

 类似资料: