Windows下 VS2015编译RocksDB
VS2015编译RocksDB
RocksDB 是一个来自 facebook 的可嵌入式的支持持久化的 key-value 存储系统,也可作为 C/S 模式下的存储数据库,但主要目的还是嵌入式。RocksDB 基于 LevelDB 构建。
1、下载rocksdb源码
git clone https://github.com/facebook/rocksdb.git
2、使用CMAKE生成VS工程
打开cmd窗口(最好使用VS2015开发人员命令提示),进入源码目录,执行下面命令
mkdir msvc14 # 创建构建目录
cd msvc14 # 进入构建目录
# 生成VS项目(D:\Libs\rocksdb是编译后安装路径)
cmake -DCMAKE_INSTALL_PREFIX=D:\Libs\rocksdb -G "Visual Studio 14 Win64" ..
实际上rocksdb源码目录中的CMakeList.txt文件中并没有写INSTALL段的内容,所以这里指定安装路径实际是无效的。
3、编译RocksDB
打开VS2015 x64 本机工具命令提示(或VS2015开发人员命令提示)工具,执行下面命令进行编译64位release版本的RocksDB库
msbuild ALL_BUILD.vcproject /p:configuration=release /maxcpucount:8
因为test项目也都编译了,文件较多,所以这里使用了/maxcpucount:8指定使用的CPU核心数。
如果只编译rocksdb(静态)库,可以使用msbuild rocksdblib.vcproject /p:configuration=release命令
编译动态库使用msbuild rocksdb.vcproject /p:configuration=release命令
编译完成后,通过的做法是使用下面命令进行安装
msbuild INSTALL.vcproject /p:configuration=release
但是这里没有生成INSTALL.vcproject,所以这里的安装需要手动进行。
直接拷贝msvc14/Release目录下的rocksdblib.lib文件和源码目录的include目录即可。
4、编译后续
因为编译出来的是动态库,但是实际上RocksDB的代码中比没有使用__declspec(dllexport)导出函数和类接口,所以在使用的时候会遇到类似如下的问题
rocksdb_test.obj : error LNK2019: 无法解析的外部符号 "public: __cdecl rocksdb::ColumnFamilyOptions::ColumnFamilyOptions(void)" (??0ColumnFamilyOptions@rocksdb@@QEAA@XZ),该符号在函数 "public: __cdecl rocksdb::Options::Options(void)" (??0Options@rocksdb@@QEAA@XZ) 中被引用
rocksdb_test.obj : error LNK2019: 无法解析的外部符号 "public: __cdecl rocksdb::DBOptions::DBOptions(void)" (??0DBOptions@rocksdb@@QEAA@XZ),该符号在函数 "public: __cdecl rocksdb::Options::Options(void)" (??0Options@rocksdb@@QEAA@XZ) 中被引用
rocksdb_test.obj : error LNK2019: 无法解析的外部符号 "public: __cdecl rocksdb::ReadOptions::ReadOptions(void)" (??0ReadOptions@rocksdb@@QEAA@XZ),该符号在函数 main 中被引用
rocksdb_test.obj : error LNK2019: 无法解析的外部符号 "public: static class rocksdb::Status __cdecl rocksdb::DB::Open(struct rocksdb::Options const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class rocksdb::DB * *)" (?Open@DB@rocksdb@@SA?AVStatus@2@AEBUOptions@2@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PEAPEAV12@@Z),该符号在函数 main 中被引用
rocksdb_test.exe : fatal error LNK1120: 4 个无法解析的外部命令
这里可以打开生成的VS工程,将配置类型改为静态库,然后再生成静态库即可。

生成后即可使用了。但是还会遇到下面的问题
rocksdb.lib(env_win.obj) : error LNK2019: 无法解析的外部符号 __imp_RpcStringFreeA,该符号在函数 "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl rocksdb::Env::GenerateUniqueId(void)" (?GenerateUniqueId@Env@rocksdb@@UEAA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) 中被引用
rocksdb.lib(env_win.obj) : error LNK2019: 无法解析的外部符号 __imp_UuidCreateSequential,该符号在函数 "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl rocksdb::Env::GenerateUniqueId(void)" (?GenerateUniqueId@Env@rocksdb@@UEAA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) 中被引用
rocksdb.lib(env_win.obj) : error LNK2019: 无法解析的外部符号 __imp_UuidToStringA,该符号在函数 "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl rocksdb::Env::GenerateUniqueId(void)" (?GenerateUniqueId@Env@rocksdb@@UEAA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) 中被引用
rocksdb_test.exe : fatal error LNK1120: 3 个无法解析的外部命令
这些函数实际上是在Rpcrt4.lib这个库里面,所以需要链接上才行。可以在使用的时候在代码中添加#pragma comment(lib,"Rpcrt4.lib")来引入。
相关测试代码如下
#include <cassert>
#include <string>
#include <iostream>
#include <chrono>
#include "rocksdb/db.h"
#pragma comment(lib,"Rpcrt4.lib")
#define TEST_FREQUENCY (10000)
char* randomstr()
{
static char buf[1024];
int len = rand() % 768 + 255;
for (int i = 0; i < len; ++i) {
buf[i] = 'A' + rand() % 26;
}
buf[len] = '\0';
return buf;
}
int main()
{
rocksdb::DB* db;
rocksdb::Options options;
options.create_if_missing = true;
// 打开数据库
rocksdb::Status status = rocksdb::DB::Open(options, "./testdb", &db);
assert(status.ok());
srand(2017);
std::string k[TEST_FREQUENCY];
for (int i = 0; i < TEST_FREQUENCY; ++i) {
k[i] = (randomstr());
}
std::string v("壹贰叁肆伍陆柒捌玖拾");
v.append(v).append(v).append(v).append(v).append(v);
// 测试添加
{
auto start = std::chrono::system_clock::now();
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = db->Put(rocksdb::WriteOptions(), k[i], v);
assert(status.ok());
}
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次添加耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
}
// 测试获取
{
auto start = std::chrono::system_clock::now();
std::string v2[TEST_FREQUENCY];
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = db->Get(rocksdb::ReadOptions(), k[i], &v2[i]);
assert(status.ok());
}
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次获取耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
// 验证获取结果是否正确
std::string ss;
for (int i = 0; i < TEST_FREQUENCY; ++i) {
if (v2[i] != v) {
std::cout << "第 " << i << " 个结果不正确" << std::endl;
std::cout << v2[i] << std::endl;
}
}
}
// 测试修改
{
auto start = std::chrono::system_clock::now();
v.append(v);
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = db->Put(rocksdb::WriteOptions(), k[i], v);
assert(status.ok());
}
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次修改耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
}
// 测试删除
{
auto start = std::chrono::system_clock::now();
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = db->Delete(rocksdb::WriteOptions(), k[i]);
assert(status.ok());
}
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次删除耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
}
delete db;
return 0;
}
编译命令如下:
# Debug版本
cl rocksdb_test.cpp /I ..\..\libs\vs140-x64\rocksdb\include ..\..\libs\vs140-x64\rocksdb\Debug\rocksdb.lib /MDd /EHsc \
/GF /TP /Zp8 /Od /Gy /W3 /D "OS_WIN" /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /D "ROCKSDB_LITE" /D "_MBCS" /D "WIN64" /D "NOMINMAX"
# Release版本
cl rocksdb_test.cpp /I ..\..\libs\vs140-x64\rocksdb\include ..\..\libs\vs140-x64\rocksdb\Release\rocksdb.lib /MD /EHsc \
/GF /TP /Zp8 /O2 /Gy /W3 /D "OS_WIN" /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /D "ROCKSDB_LITE" /D "_MBCS" /D "WIN64" /D "NOMINMAX"
注意上面使用了/Zp8和/TP /GF等选项。如果不设置/Zp8(8字节对齐),在运行时候会抛出异常。因为VS编译64位程序的时候,默认就是8字节对齐,而我没有测试32位版本的,所以这里可能不是关键。
后话
Linux下的编译都比较简单,包括LevelDB等,都只需要直接make即可。Linux下编译的时候可能有某些依赖需要安装一下,包括gflags、jemalloc、libsnappy、libbz2、liblz4等。
Windows下 VS2015编译RocksDB的更多相关文章
- Windows下 VS2015编译levelDB(nmake)
VS2015编译levelDB Leveldb是一个google实现的非常高效的kv数据库,非常适合嵌入到程序中.如果有简单的key-value数据库需求,而又想使用一个数据库服务的话,levelDB ...
- Windows下 VS2015编译boost1.62
VS2015编译boost1.62 Boost库是一个可移植.提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一. Boost库由C++标准委员会库工作组成员发起,其中有些内容有 ...
- Windows下 VS2015编译ForestDB
VS2015编译ForestDB ForestDB 是一个快速的 Key-Value 存储引擎,基于层次B +树单词查找树.由 Couchbase 缓存和存储团队开发. 1.下载forestdb源码 ...
- Windows下PythonQt编译(vs2015+Qt5.11.2+PythonQt 3.2)
后记: 由于自己low,没有下载罪行的python3.2导致编译上遇到种种问题,后文可以参考,建议看: <Windows7 VS2015 下编译 PythonQt3.2> https:// ...
- Windows下PythonQt编译(vs2015+Qt5.11.2+PythonQt 3.2)探索
时间:2018年10月20日 笔者最近在做Qt方面的开发工作,需用到脚本程序对程序内部进行扩展,就很自然的想到了PythonQt,下面介绍PythonQt在Windows下的的安装编译心得,水平有限, ...
- 原创 C++应用程序在Windows下的编译、链接:第一部分 概述
本文是对C++应用程序在Windows下的编译.链接的深入理解和分析,文章的目录如下: 我们先看第一章概述部分. 1概述 1.1编译工具简介 cl.exe是windows平台下的编译器,link.ex ...
- 【FFmpeg】Windows下FFmpeg编译
由于FFmpeg是基于Linux开发的开源项目,源代码和Windows下最常见的Visual Studio提供的C/C++编译器不兼容,因此它不能使用MSVC++编译,需要在Windows下配置一个类 ...
- C++应用程序在Windows下的编译、链接(一)概述
C++应用程序在Windows下的编译.链接(一)概述 本文是对C++应用程序在Windows下的编译.链接的深入理解和分析,文章的目录如下: 我们先看第一章概述部分. 1概述 1.1编译工具简介 c ...
- ACE在windows下的编译及配置(VS2010)
ACE在windows下的编译及配置(VS2010) 分类: -[小西南]- 2013-08-06 16:17 2354人阅读 评论( ...
随机推荐
- wim2008 让FTP防火墙可用性配置
转: Win2003和Win2008防火墙导致FTP服务器不能访问的解决方法 这篇文章主要介绍了Win2003和Win2008防火墙导致FTP服务器不能访问的解决方法,需要的朋友可以参考下 由于通过远 ...
- 奇怪吸引子---DequanLi
奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...
- maven-shade-plugin 入门指南
1. Why? 通过 maven-shade-plugin 生成一个 uber-jar,它包含所有的依赖 jar 包. 2. Goals Goal Description shade:help Dis ...
- 5.数字拆分成4段,怎样使得4段的乘积最小【dp】
题目是:给出一个数字(10,000-100,000,000),把这个数字拆分成4段,怎样使得4段的乘积最小.比如12345拆分成1*2*3*45=270, 10000=1*00*0*0=0. 解题分析 ...
- MultipleRegularExpressionAttribute MVC中扩展自定义验证规则
好久都没有写博客,最近工作中没有什么可写的,公司的项目是以业务为重,技术含量实在不咋的.这次sprint中有一个要求就是password必须一些规则,比如给你一些正则表达式必须满足几个,直接看效果吧 ...
- Android -- tools
工具属性 Android 有一个专用的XML命名空间,用于使工具可以记录XML文件里的信息,并且在打包程序的进行把信息剥离到不会带来运行时期和下载大小的负面影响的程度. 这个命名空间的 URI 是 h ...
- Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测
Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测 2017年12月13日 17:39:11 机器之心V 阅读数:5931 近日,Artur Suilin 等人发布了 Kaggl ...
- Netflix推荐系统:从评分预测到消费者法则
http://in.sdo.com/?p=11 原文链接:Netflix recommendations: beyond the 5 stars (Part 1), (Part 2) 原文作者:Xav ...
- 解析oui.txt文件,通过MAC前缀获取Organization
1.前言 OUI是指Organizationally unique identifier (组织唯一标识符),签发给各类组织的唯一标识符.MAC地址共有6个字节48位组成,前3个字节体现了OUI,其 ...
- FPS游戏服务器设计的问题 【转】
一.追溯 去gameloft笔试,有一个题目是说: 叫你去设计一个FPS(第一人称射击游戏),你是要用TCP呢还是要用UDP,说明理由 . 二.学习 这是两篇网上找到的文章,写非常不错. 当时笔试的时 ...