first commit
This commit is contained in:
64
CMakeLists.txt
Normal file
64
CMakeLists.txt
Normal file
@@ -0,0 +1,64 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(xrabbitmqclient CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
find_package(Boost REQUIRED)
|
||||
find_package(simpleamqpclient CONFIG REQUIRED)
|
||||
|
||||
# 使用 generate_export_header(${PROJECT_NAME}) 时:
|
||||
# - CMake 会自动生成一个头文件,其中包含导出宏
|
||||
# - 宏名称是 项目名称的大写形式 + _EXPORT 后缀
|
||||
include(GenerateExportHeader)
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 2. 编译封装层为独立库
|
||||
# ---------------------------------------------------------
|
||||
add_library(${PROJECT_NAME}
|
||||
include/RabbitMQClient.h
|
||||
src/RabbitMQClient.cpp
|
||||
)
|
||||
|
||||
generate_export_header(${PROJECT_NAME}
|
||||
EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/include/XRabbitMQClient_export.h
|
||||
)
|
||||
|
||||
# 🌟 新增修复:强制 MSVC 使用 UTF-8 编码编译,彻底消灭 C4819 和乱码导致的玄学报错
|
||||
if(MSVC)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /utf-8)
|
||||
endif()
|
||||
|
||||
|
||||
# 设置头文件搜索路径
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>
|
||||
)
|
||||
# 🌟 修复项:隐藏底层依赖,使用 Conan 声明的准确目标名(小写)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE simpleamqpclient::simpleamqpclient boost::boost)
|
||||
|
||||
# 添加导出宏
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE XRABBITMQCLIENT_LIBRARY)
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 3. 安装规则 (供 Conan 打包提取使用)
|
||||
# ---------------------------------------------------------
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# 安装生成的库文件
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # Windows 下的 .dll
|
||||
)
|
||||
|
||||
# 安装暴露给业务层的头文件 (注意:千万不要把 RabbitMQClient.cpp 安装出去)
|
||||
install(FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/IMessageQueue.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/RabbitMQClient.h
|
||||
${CMAKE_BINARY_DIR}/include/XRabbitMQClient_export.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
91
README_PACKAGE.md
Normal file
91
README_PACKAGE.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# XRabbitMQClient 独立包发布指南
|
||||
|
||||
## 1. 本地构建和测试包
|
||||
|
||||
### 在 XRabbitMQClient 目录下执行:
|
||||
|
||||
```bash
|
||||
cd XRabbitMQClient
|
||||
|
||||
# 安装依赖
|
||||
conan install . --build=missing -s build_type=Release -s compiler.cppstd=17
|
||||
|
||||
# 构建包
|
||||
conan build .
|
||||
|
||||
# 创建本地包(会自动构建并打包)
|
||||
conan create . -s build_type=Release -s compiler.cppstd=17
|
||||
```
|
||||
|
||||
## 2. 发布到 Conan 远程仓库
|
||||
|
||||
### 2.1 配置远程仓库(如果还没有)
|
||||
```bash
|
||||
# 查看已配置的远程仓库
|
||||
conan remote list
|
||||
|
||||
# 添加远程仓库(示例)
|
||||
conan remote add my-conan-repo https://your-conan-server.com
|
||||
```
|
||||
|
||||
### 2.2 上传包
|
||||
```bash
|
||||
# 上传到远程仓库
|
||||
conan upload xrabbitmqclient/1.0.0 --remote=my-conan-repo --all
|
||||
```
|
||||
|
||||
## 3. 在其他项目中使用 xrabbitmqclient
|
||||
|
||||
### 3.1 在你的项目 conanfile.py 中添加依赖:
|
||||
|
||||
```python
|
||||
from conan import ConanFile
|
||||
|
||||
class MyProjectConan(ConanFile):
|
||||
name = "myproject"
|
||||
version = "1.0.0"
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
|
||||
def requirements(self):
|
||||
self.requires("xrabbitmqclient/1.0.0")
|
||||
```
|
||||
|
||||
### 3.2 在 CMakeLists.txt 中使用:
|
||||
|
||||
```cmake
|
||||
find_package(xrabbitmqclient CONFIG REQUIRED)
|
||||
target_link_libraries(your_target PRIVATE xrabbitmqclient::xrabbitmqclient)
|
||||
```
|
||||
|
||||
### 3.3 代码中使用:
|
||||
|
||||
```cpp
|
||||
#include <RabbitMQClient.h>
|
||||
|
||||
int main() {
|
||||
// 使用 XRabbitMQClient
|
||||
auto client = std::make_unique<RabbitMQClient>();
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 项目结构说明
|
||||
|
||||
```
|
||||
XRabbitMQClient/
|
||||
├── conanfile.py # 独立包的 Conan 配置
|
||||
├── CMakeLists.txt # CMake 构建配置
|
||||
├── include/ # 公开头文件
|
||||
│ ├── IMessageQueue.h
|
||||
│ └── RabbitMQClient.h
|
||||
└── src/ # 源代码
|
||||
└── RabbitMQClient.cpp
|
||||
```
|
||||
|
||||
## 5. 版本更新流程
|
||||
|
||||
1. 修改 `conanfile.py` 中的 `version` 字段
|
||||
2. 提交代码变更
|
||||
3. 运行 `conan create .` 创建新版本
|
||||
4. 上传新版本到远程仓库
|
||||
50
conanfile.py
Normal file
50
conanfile.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from conan import ConanFile
|
||||
from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout
|
||||
|
||||
class XRabbitMQClientConan(ConanFile):
|
||||
name = "xrabbitmqclient"
|
||||
version = "1.0.0"
|
||||
description = "A C++ wrapper for RabbitMQ based on Interface and Pimpl."
|
||||
license = "MIT"
|
||||
author = "XDL"
|
||||
topics = ("rabbitmq", "amqp", "message-queue")
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
|
||||
options = {"shared": [True, False], "fPIC": [True, False]}
|
||||
default_options = {"shared": False, "fPIC": True}
|
||||
|
||||
exports_sources = "CMakeLists.txt", "src/*", "include/*"
|
||||
|
||||
def config_options(self):
|
||||
if self.settings.os == "Windows":
|
||||
del self.options.fPIC
|
||||
|
||||
def configure(self):
|
||||
if self.options.shared:
|
||||
self.options.rm_safe("fPIC")
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
|
||||
def requirements(self):
|
||||
self.requires("simpleamqpclient/2.5.1", transitive_headers=True, transitive_libs=True)
|
||||
self.requires("boost/1.78.0")
|
||||
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
tc.generate()
|
||||
deps = CMakeDeps(self)
|
||||
deps.generate()
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
|
||||
def package(self):
|
||||
cmake = CMake(self)
|
||||
cmake.install()
|
||||
|
||||
def package_info(self):
|
||||
self.cpp_info.libs = ["xrabbitmqclient"]
|
||||
self.cpp_info.requires = ["simpleamqpclient::simpleamqpclient", "boost::boost"]
|
||||
19
include/IMessageQueue.h
Normal file
19
include/IMessageQueue.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "XRabbitMQClient_export.h"
|
||||
|
||||
// 纯虚接口:隔离具体的消息队列实现
|
||||
class XRABBITMQCLIENT_EXPORT IMessageQueue
|
||||
{
|
||||
public:
|
||||
virtual ~IMessageQueue() = default;
|
||||
|
||||
// 连接到消息队列服务器
|
||||
virtual bool Connect() = 0;
|
||||
|
||||
// 发送消息
|
||||
virtual bool Publish(const std::string &routing_key, const std::string &message) = 0;
|
||||
|
||||
// 接收消息 (简单阻塞式示例)
|
||||
virtual std::string Consume(const std::string &queue_name) = 0;
|
||||
};
|
||||
25
include/RabbitMQClient.h
Normal file
25
include/RabbitMQClient.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "IMessageQueue.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class XRABBITMQCLIENT_EXPORT RabbitMQClient : public IMessageQueue
|
||||
{
|
||||
public:
|
||||
// 传入必要的连接参数
|
||||
RabbitMQClient(const std::string &host, int port, const std::string &username, const std::string &password);
|
||||
|
||||
// 注意:使用 unique_ptr 配合 Pimpl 时,析构函数必须在 .cpp 中实现
|
||||
~RabbitMQClient() override;
|
||||
|
||||
// 实现接口方法
|
||||
bool Connect() override;
|
||||
bool Publish(const std::string &routing_key, const std::string &message) override;
|
||||
std::string Consume(const std::string &queue_name) override;
|
||||
|
||||
private:
|
||||
// Pimpl 核心:前向声明具体的实现类
|
||||
struct Impl;
|
||||
// 使用 unique_ptr 管理实现类的生命周期
|
||||
std::unique_ptr<Impl> pimpl_;
|
||||
};
|
||||
87
src/RabbitMQClient.cpp
Normal file
87
src/RabbitMQClient.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "RabbitMQClient.h"
|
||||
#include <iostream>
|
||||
|
||||
// 在这里引入第三方库的头文件!
|
||||
// 这样使用该封装类的业务代码就不会被污染
|
||||
#include <SimpleAmqpClient/SimpleAmqpClient.h>
|
||||
|
||||
// 定义内部实现结构体
|
||||
struct RabbitMQClient::Impl
|
||||
{
|
||||
std::string host;
|
||||
int port;
|
||||
std::string username;
|
||||
std::string password;
|
||||
|
||||
AmqpClient::Channel::ptr_t channel;
|
||||
|
||||
Impl(std::string h, int p, std::string u, std::string pwd)
|
||||
: host(std::move(h)), port(p), username(std::move(u)), password(std::move(pwd)), channel(nullptr) {}
|
||||
};
|
||||
|
||||
// 构造函数:初始化 pimpl_
|
||||
RabbitMQClient::RabbitMQClient(const std::string &host, int port, const std::string &username, const std::string &password)
|
||||
: pimpl_(std::make_unique<Impl>(host, port, username, password))
|
||||
{
|
||||
}
|
||||
|
||||
// 析构函数:必须在这里定义,此时 Impl 是完整类型,unique_ptr 才能正确释放它
|
||||
RabbitMQClient::~RabbitMQClient() = default;
|
||||
|
||||
bool RabbitMQClient::Connect()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 创建连接
|
||||
pimpl_->channel = AmqpClient::Channel::Create(
|
||||
pimpl_->host, pimpl_->port, pimpl_->username, pimpl_->password);
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
std::cerr << "RabbitMQ Connection Failed: " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool RabbitMQClient::Publish(const std::string &routing_key, const std::string &message)
|
||||
{
|
||||
if (!pimpl_->channel)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
// 确保队列存在 (实际项目中可能在初始化时统一声明)
|
||||
pimpl_->channel->DeclareQueue(routing_key, false, true, false, false);
|
||||
|
||||
AmqpClient::BasicMessage::ptr_t msg = AmqpClient::BasicMessage::Create(message);
|
||||
pimpl_->channel->BasicPublish("", routing_key, msg);
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
std::cerr << "Publish Failed: " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string RabbitMQClient::Consume(const std::string &queue_name)
|
||||
{
|
||||
if (!pimpl_->channel)
|
||||
return "";
|
||||
|
||||
try
|
||||
{
|
||||
pimpl_->channel->DeclareQueue(queue_name, false, true, false, false);
|
||||
std::string consumer_tag = pimpl_->channel->BasicConsume(queue_name, "");
|
||||
|
||||
// 阻塞等待消息
|
||||
AmqpClient::Envelope::ptr_t envelope = pimpl_->channel->BasicConsumeMessage(consumer_tag);
|
||||
return envelope->Message()->Body();
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
std::cerr << "Consume Failed: " << e.what() << std::endl;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user