Support RocksDB shared library and new unique_ptr DB::Open API

Some distributions (e.g. Fedora) ship only a shared RocksDB that exports
RocksDB::rocksdb-shared rather than RocksDB::rocksdb. The CMake target
selection now falls back to the shared target when the static one is absent.

Newer RocksDB also changed DB::Open and DB::OpenForReadOnly to take
std::unique_ptr<DB>* instead of DB**. IfcFile.cpp uses SFINAE tag dispatch
to build against both old and new APIs without version detection.
This commit is contained in:
Bruno Postle
2026-06-04 22:31:02 +01:00
committed by Thomas Krijnen
parent eacff93945
commit 365be8fb52
2 changed files with 35 additions and 5 deletions
+7 -3
View File
@@ -258,10 +258,14 @@ if(WITH_ROCKSDB)
set(ROCKSDB_LIBRARIES "IFCOPENSHELL_RocksDB")
target_compile_definitions(IFCOPENSHELL_RocksDB INTERFACE IFOPSH_WITH_ROCKSDB)
set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_ROCKSDB)
# Shared binaries for `rocksdb` only support limited API (only `c.h`), but we use `db.h` API.
# So rocksdb supported only as a static library.
# See https://github.com/facebook/rocksdb/issues/981.
target_link_libraries(IFCOPENSHELL_RocksDB INTERFACE RocksDB::rocksdb)
if(TARGET RocksDB::rocksdb)
target_link_libraries(IFCOPENSHELL_RocksDB INTERFACE RocksDB::rocksdb)
elseif(TARGET RocksDB::rocksdb-shared)
target_link_libraries(IFCOPENSHELL_RocksDB INTERFACE RocksDB::rocksdb-shared)
else()
message(FATAL_ERROR "RocksDB found but neither RocksDB::rocksdb nor RocksDB::rocksdb-shared target exists")
endif()
if(WITH_ZSTD)
# @todo do we actually need the zstd include dir or rather just pass
+28 -2
View File
@@ -7,6 +7,8 @@
#endif
#include <fstream>
#include <memory>
#include <utility>
#include <sys/types.h>
#include <sys/stat.h>
@@ -410,6 +412,26 @@ IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::assert_existance(s
}
namespace {
#ifdef IFOPSH_WITH_ROCKSDB
// Newer RocksDB releases (e.g. the one shipped by Fedora rawhide) changed
// DB::Open / DB::OpenForReadOnly to take a std::unique_ptr<DB>* and removed
// the raw DB** overloads. These helpers select whichever signature the
// installed RocksDB exposes, so the code builds against both old and new
// headers. The int/long tag prefers the unique_ptr form when both exist.
template <typename Fn>
auto rocksdb_open(Fn&& open, rocksdb::DB*& db, int)
-> decltype(open(std::declval<std::unique_ptr<rocksdb::DB>*>())) {
std::unique_ptr<rocksdb::DB> owned;
auto status = open(&owned);
db = owned.release();
return status;
}
template <typename Fn>
auto rocksdb_open(Fn&& open, rocksdb::DB*& db, long)
-> decltype(open(std::declval<rocksdb::DB**>())) {
return open(&db);
}
#endif
rocksdb::DB* init_db(const std::string& filepath, bool readonly) {
rocksdb::DB* db = nullptr;
#ifdef IFOPSH_WITH_ROCKSDB
@@ -446,9 +468,13 @@ namespace {
rocksdb::Status status;
if (readonly) {
status = rocksdb::DB::OpenForReadOnly(options, filepath, &db);
status = rocksdb_open([&](auto* dbptr) -> decltype(rocksdb::DB::OpenForReadOnly(options, filepath, dbptr)) {
return rocksdb::DB::OpenForReadOnly(options, filepath, dbptr);
}, db, 0);
} else {
status = rocksdb::DB::Open(options, filepath, &db);
status = rocksdb_open([&](auto* dbptr) -> decltype(rocksdb::DB::Open(options, filepath, dbptr)) {
return rocksdb::DB::Open(options, filepath, dbptr);
}, db, 0);
}
if (!status.ok()) {
return nullptr;