speedb-io / speedb

A RocksDB compliant high performance scalable embedded key-value store
https://www.speedb.io/
Apache License 2.0
919 stars 72 forks source link

Can't use precompiled release due to missing CXX11 ABI symbols #863

Open Jean-Lessa opened 3 months ago

Jean-Lessa commented 3 months ago

Describe the bug Using the precompiled library in a project I'm working at doesn't work because it (apparently) lacks the CXX11 ABI symbols of certain functions. I'm getting around this by compiling the library from source, but it's a hacky approach that doubles the compile time overall.

To Reproduce

  1. Create an isolated folder (e.g. speedb-test), download the release from Github, extract the include folder and the libspeed.a to it, rename it to libspeed_pre.a (for discerning)
  2. Compile Speedb from source at the same version with cmake -DCMAKE_BUILD_TYPE=Release -DROCKSDB_BUILD_SHARED=OFF -DWITH_TESTS=OFF -DWITH_BENCHMARK_TOOLS=OFF -DWITH_CORE_TOOLS=OFF -DWITH_TOOLS=OFF and copy libspeedb.a to the folder
  3. Copy-paste this minimal test program that simply opens a database, inserts and reads a value, then compile it with g++ -std=c++23 -o test main.cpp -I./include ./<LIB> -lz -lbz2 -lzstd -lsnappy -llz4 (replace <LIB> with each respective lib, one at a time):
#include <iostream>
#include "rocksdb/db.h"

int main() {
  rocksdb::Options opts;
  opts.create_if_missing = true;
  rocksdb::DB* db;
  rocksdb::Status st;
  bool found = false;

  st = rocksdb::DB::Open(opts, "DB", &db);
  if (st.ok()) {
    rocksdb::Slice key = "123";
    rocksdb::Slice val = "abc";
    st = db->Put(rocksdb::WriteOptions(), key, val);
    if (st.ok()) {
      rocksdb::Iterator* it(db->NewIterator(rocksdb::ReadOptions()));
      for (it->Seek(key); it->Valid(); it->Next()) {
        if (it->key().ToString() == key) { found = true; break; }
      }
      if (!found) std::cout << "key not found\n";
    } else std::cout << "failed to insert\n";
  } else std::cout << "failed to open db\n";

  delete db;
  db = nullptr;
  return 0;
}

Expected behavior libspeedb.a (the manually compiled one) links successfully. libspeedb_pre.a (the precompiled one) gives me an undefined reference error:

/usr/bin/ld: /tmp/ccOmVFUd.o: in function "main":
main.cpp:(.text+0x7f): undefined reference to "rocksdb::DB::Open(rocksdb::Options const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rocksdb::DB**)"
/usr/bin/ld: main.cpp:(.text+0x22d): undefined reference to "rocksdb::Slice::ToString[abi:cxx11](bool) const"
collect2: error: ld returned 1 exit status

Checking each library with nm confirms what I suspected - the precompiled version is missing the CXX11 ABI symbol:

$ nm ./libspeedb.a | grep "T .*Slice.*ToString\|t .*Slice.*ToString"
0000000000000ac0 T _ZNK7rocksdb5Slice8ToStringB5cxx11Eb
000000000000007c t _ZNK7rocksdb5Slice8ToStringB5cxx11Eb.cold
$ nm ./libspeedb_pre.a | grep "T .*Slice.*ToString\|t .*Slice.*ToString"
0000000000001bf0 T _ZNK7rocksdb5Slice8ToStringEb
0000000000000176 t _ZNK7rocksdb5Slice8ToStringEb.cold

Unless I'm missing some really dumb concept here, I expected the linker to just find the symbols from the precompiled lib, regardless of them being CXX11 or not, and link them properly to the executable. Instead it seems to be forcefully looking for the CXX11 symbols which don't exist at all.

System (please complete the following information):

Additional context I can't compile the lib with C++23, doing so gives me a plethora of compilation errors about conflicting declarations, template usage within extern "C"(???), and template deprecations. I can't drop C++23 either, it's a hard requirement for the project.