引流:个人博客
RocksDB 的编译分为静态
编译和动态
编译,其中,静态编译会在工程目录下生成librocksdb.a
静态链接库,动态编译则会在工程目录下生成librocksdb.so.${version}
动态链接库。不管是哪种方式,编译完成后只需要按照 g++ 的链接方式使用对应的库即可。
这里演示 RocksDB 的静态编译和使用过程,并将踩的坑记录下来。
依赖
RocksDB 默认使用了很多依赖,包括用于统计、压缩等等的库。
安装 gcc、g++ 以及 make:
sudo apt-get install build-essential
安装 gflags:
sudo apt-get install libgflags-dev
安装 snappy:
sudo apt-get install libsnappy-dev
安装 zlib:
sudo apt-get install zlib1g-dev
安装 bzip2:
sudo apt-get install libbz2-dev
安装 lz4:
sudo apt-get install liblz4-dev
安装 zstandard:
sudo apt-get install libzstd-dev
安装 cmake:
略了,网上找教程
静态编译
官方是这么说的:
- [recommended]
make static_lib
will compile librocksdb.a, RocksDB static library. Compiles static library in release mode.
按照官方来就行了,编译失败的话多半是依赖没装好,按照报错提示一个一个装就行。
cd rocksdb
sudo make static_lib -j 8 #8线程编译
成功后,就会在当前目录下生成librocksdb.a
:
zyh@zyh ~/ysy/rocksdb (main)$ ls | grep librocksdb.a
librocksdb.a
zyh@zyh ~/ysy/rocksdb (main)$ pwd
/home/zyh/ysy/rocksdb
接下来就是使用它了,这里按照最返璞归真的 g++ 命令行来演示。
使用
第一,当前最新的 RocksDB 需要 C++17,因此:
g++ -std=c++17
第二,需要链接 librocksdb.a 静态库。注意,不同于动态库的链接需要 -L
指定,静态库直接作为 flag,不用且不能使用 -L 来指定,直接在命令行上写上 .a 文件路径即可。
g++ xxx /home/zyh/ysy/rocksdb/librocksdb.a xxx
第三(可选),指定头文件。RocksDB 的头文件为 include/,g++ 指定头文件的方式为 -I
后跟头文件的路径,因此:
g++ xxx -I -I /home/zyh/ysy/rocksdb/include xxx
第四,链接上各种依赖:
-lpthread -luring -ldl -lrt -lsnappy -lgflags -lz -lbz2 -llz4 -lzstd
四步结合起来,程序使用 RocksDB 的编译命令为:
g++ -std=c++17 demo.cpp -o demo /home/zyh/ysy/rocksdb/librocksdb.a -I /home/zyh/ysy/rocksdb/include -lpthread -luring -ldl -lrt -lsnappy -lgflags -lz -lbz2 -llz4 -lzstd
写一个测试 demo.cpp:
#include <cstdio>
#include <string>
#include <iostream>
#include "rocksdb/db.h"
#include "rocksdb/slice.h"
#include "rocksdb/options.h"
#include "rocksdb/iostats_context.h"
#include "rocksdb/perf_context.h"
#include <pthread.h>
#include <unistd.h>
using namespace std;
using namespace rocksdb;
const std::string PATH = "/tmp/rocksdb_tmp";
DB* db;
Options options;
int main() {
options.create_if_missing = true;
Status s = DB::Open(options, PATH, &db);
assert(s.ok());
s = db->Put(WriteOptions(),"key01","value");
assert(s.ok());
std::string value;
s = db->Get(ReadOptions(),"key01", &value);
cout << value << endl;
return 0;
}
编译并运行:
# 编译
zyh@zyh ~/ysy $ g++ -std=c++17 demo.cpp -o demo /home/zyh/ysy/rocksdb/librocksdb.a -I /home/zyh/ysy/rocksdb/include -lpthread -luring -ldl -lrt -lsnappy -lgflags -lz -lbz2 -llz4 -lzstd
# 运行
zyh@zyh ~/ysy $ ./demo
value
踩坑记录
flag 没加全
flag 一定要加全,不然客户端编译的时候就会报错 undefined reference to 'xxx'
,比如我刚开始没有加 -luring
,编译的时候就出错了:
...
/home/zyh/ysy/rocksdb/librocksdb.a(io_posix.o): In function `rocksdb::CreateIOUring()':
/home/zyh/ysy/rocksdb/./env/io_posix.h:272: undefined reference to `io_uring_queue_init
...
那怎么知道需要链接什么库,用 Linux 的 man
就可以了,只要查到函数所在的头文件,flag 一般就能确定了,比如 man io_uring_queue_init
显示该函数的手册,其中就有其所在的头文件名:
可以看到,lib 库名为 liburing。一般而已,lib 库链接时 flag 的形式均为 -l${name}
,因此可以推断出 flag 为 -luring
,当然,上网查也行。
依赖的 flag 加全了,lib 库的路径写对了,c++ 版本用对了,基本不会编译失败的。