0%

leveldb静态编译及snappy支持

由于服务器依赖比较老旧,因此需要重新安装各种依赖

leveldb依赖安装

1
2
sudo yum update
sudo yum install cmake gcc g++

如果cmake无法安装到3.9以上的版本,可以从官网下载,然后直接解压到项目目录下,之后直接使用绝对路径或相对路径调用cmake,gcc和g++推荐使用7.5

snappy编译

1
2
3
4
5
6
7
git clone https://github.com/google/snappy.git
cd snappy
git submodule update --init
git checkout 1.1.9
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ../
make

leveldb编译

使用--recurse-submodules下载subgit中的内容,使用git tag查看tag,选择最新的release,最后使用git checkout切换到最新的release版本上

1
2
3
4
git clone --recurse-submodules https://github.com/google/leveldb.git
cd leveldb
git tag
git checkout 1.23
1
2
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build .

执行测试检查编译是否成功

1
./db_bench

snappy支持

修改leveldb/CMakeLists.txt, 在check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)语句前后添加依赖

其中/home/someone/project/snappy/home/someone/project/snappy/build需要替换成自己的snappy源码目录和build目录
添加后形式如下:

1
2
3
4
5
6
# 之前添加依赖
link_directories("/home/someone/project/snappy/build")
include_directories("/home/someone/project/snappy" "/home/someone/project/snappy/build")
check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)
# 之后强制开启HAVE_SNAPPY
set(HAVE_SNAPPY ON)

重新编译和测试

1
2
3
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build .
./db_bench

静态编译leveldb

因为服务器环境问题,需要静态编译leveldb, 尤其是静态编译libgcc和libg++

check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)语句前后添加link_libraries标签配置所有的目标静态链接gcc和g++

1
link_libraries(-static-libgcc -static-libstdc++)

执行ldd db_bench可以看到已经不再依赖gcc和g++了

执行strings /lib64/libstdc++.so.6 | grep GLIBCXX可以查看目前支持的版本

可能会遇到如下报错:

  1. 找不到成员

    这种情况是由于gcc、g++版本太低导致的,需要升级版本

    1
    2
    3
    leveldb/third_party/googletest/googletest/include/gtest/gtest-matchers.h:414:12: error: ‘is_trivially_copy_constructible’ is not a member of ‘std’
    std::is_trivially_copy_constructible<M>::value &&
    ^

    使用如下命令检查版本

    1
    2
    gcc -v
    g++ -v
  2. /bin/c++ /bin/cc缺失

    这种情况是软链缺失导致的,报错如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CMake Error at CMakeLists.txt:7 (project):
    The CMAKE_CXX_COMPILER:

    /bin/c++

    is not a full path to an existing compiler tool.

    Tell CMake where to find the compiler by setting either the environment
    variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
    to the compiler, or to the compiler name if it is in the PATH.

    此时需要手动恢复软链,使用which gccwhich g++确定安装位置,然后使用ln设置软链

    1
    2
    ln -s /usr/local/bin/g++ /bin/c++
    ln -s gcc /bin/cc
  3. /lib64/libstdc++.so.6: version `GLIBCXX_3.4.22’ not found

建议使用静态链接

demo

编写一个简单的测试demo, 放在与leveldb根目录同级的目录下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <string>
#include <assert.h>
#include "leveldb/db.h"

using namespace std;

int main(void)
{
leveldb::DB *db;
leveldb::Options options;
options.create_if_missing = true;

// open
leveldb::Status status = leveldb::DB::Open(options, "testdb", &db);
assert(status.ok());

string key = "name";
string value = "shane";

cout << "write:" "("<< key << ")" "=>" "(" << value << ")" << endl;
// write
status = db->Put(leveldb::WriteOptions(), key, value);
assert(status.ok());

// read
status = db->Get(leveldb::ReadOptions(), key, &value);
assert(status.ok());

cout << "read:" "("<< key << ")" "=>" "(" << value << ")" << endl;

// delete
status = db->Delete(leveldb::WriteOptions(), key);
assert(status.ok());
cout << "delete:" "("<< key << ")" << status.ToString() << endl;

status = db->Get(leveldb::ReadOptions(), key, &value);
if (!status.ok()) {
cout << "read error: " << status.ToString() << "("<< key << ")" << endl;
} else {
cout << "read:" "("<< key << ")" "=>" "(" << value << ")" << endl;
}

//close
delete db;

return 0;
}

执行命令, 编译leveldb需要使用-Ileveldb/include引入头文件,-Lleveldb/build设置链库地址, -lleveldb -lpthread 指定要链接的库, -o leveldbtest 指定输出名字

1
2
g++ leveldbtest.cc -Ileveldb/include -Lleveldb/build -lleveldb -lpthread -o leveldbtest
./leveldbtest

运行结果如下

1
2
3
4
write:(name)=>(shane)
read:(name)=>(shane)
delete:(name)OK
read error: NotFound: (name)