diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a1872e..58497e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -250,6 +250,24 @@ if(NOT USE_SQLITE3 AND NOT USE_POSTGRESQL AND NOT USE_LEVELDB AND NOT USE_REDIS) message(SEND_ERROR "No database backends are configured, or none could be found") endif(NOT USE_SQLITE3 AND NOT USE_POSTGRESQL AND NOT USE_LEVELDB AND NOT USE_REDIS) +# Determine whether there is a libstdc++ ABI incompatibility. +# Currently only needed for leveldb. +set(CPP_ABI_STDSTRING_OK 1) +if(USE_LEVELDB) + # try_compile does not remove the temporary build directory, so put it in CMakeFiles... + # Also: use absolute paths; cmake chokes on relative paths :-( + # AARGH! try_compile does not understand the INCLUDE_DIRECTORIES directive. + try_compile(CPP_ABI_STDSTRING_RESULT + "${CMAKE_HOME_DIRECTORY}/CMakeFiles/CMakeTmp/abi-stdstring-test" + "${CMAKE_HOME_DIRECTORY}/cmake/abi-stdstring.cpp" + LINK_LIBRARIES ${LEVELDB_LIBRARY}) + #INCLUDE_DIRECTORIES ${LEVELDB_INCLUDE_DIR} + if(NOT CPP_ABI_STDSTRING_RESULT) + set(CPP_ABI_STDSTRING_OK 0) + message(STATUS "C++ library ABI mismatch for std::string. Enabling workaround - this may affect functionality") + endif(NOT CPP_ABI_STDSTRING_RESULT) +endif(USE_LEVELDB) + include_directories( "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" diff --git a/Changelog b/Changelog index 028c3ef..2535fd5 100644 --- a/Changelog +++ b/Changelog @@ -11,6 +11,8 @@ - Fixed failure to compile with gcc 6 - Fixed failure to compile when rpm is not installed (e.g. on non-rpm systems...) + - Workaround to allow compilation with clang when using leveldb. + This is broken due to libstdc++ ABI incompatibility [31 May 2016] Features: - Support for postgresql backend added diff --git a/MSVC/gen-build-config.bat b/MSVC/gen-build-config.bat index 9d2d6dd..1dc4d69 100644 --- a/MSVC/gen-build-config.bat +++ b/MSVC/gen-build-config.bat @@ -285,6 +285,7 @@ EXIT /B %$EXITVAL% SET $LINE=!$LINE:@VERSION_MINOR@=%$VERSION_MINOR%! SET $LINE=!$LINE:@PACKAGING_FLAT@=%$PACKAGING_FLAT%! SET $LINE=!$LINE:@INSTALL_PREFIX@=%$INSTALL_PREFIX%! + SET $LINE=!$LINE:@CPP_ABI_STDSTRING_OK@=1! ECHO %$INDENT%%$LINE% >> %$OUTPUT% ENDLOCAL diff --git a/build_config.h.in b/build_config.h.in index 8549154..6298d5d 100644 --- a/build_config.h.in +++ b/build_config.h.in @@ -21,5 +21,7 @@ #define PACKAGING_FLAT @PACKAGING_FLAT@ #define INSTALL_PREFIX "@INSTALL_PREFIX@" +#define CPP_ABI_STDSTRING_OK @CPP_ABI_STDSTRING_OK@ + #endif diff --git a/cmake/abi-stdstring.cpp b/cmake/abi-stdstring.cpp new file mode 100644 index 0000000..0ee642c --- /dev/null +++ b/cmake/abi-stdstring.cpp @@ -0,0 +1,7 @@ +#include +#include +int main(void) { + leveldb::Status status; + std::string str = status.ToString(); + return 0; +} diff --git a/db-leveldb.cpp b/db-leveldb.cpp index 9492c2f..e865e6a 100644 --- a/db-leveldb.cpp +++ b/db-leveldb.cpp @@ -1,6 +1,7 @@ #include "db-leveldb.h" #include #include +#include "build_config.h" #include "types.h" inline int64_t stoi64(const std::string &s) { @@ -26,7 +27,16 @@ DBLevelDB::DBLevelDB(const std::string &mapdir) : options.create_if_missing = false; leveldb::Status status = leveldb::DB::Open(options, mapdir + "map.db", &m_db); if(!status.ok()) + #if CPP_ABI_STDSTRING_OK throw std::runtime_error(std::string("Failed to open Database: ") + status.ToString()); + #else + throw std::runtime_error(std::string("Failed to open Database: ") + + ( status.ok() ? "Ok (??? how is this possible ???"")" // "" is needed to prevent interpretation as trigraph -shudder- + : status.IsNotFound() ? "NotFound" + : status.IsCorruption() ? "Corruption" + : status.IsIOError() ? "IOError" + : "Cannot determine error type - could be NotSupported or InvalidArgument or something else")); + #endif } DBLevelDB::~DBLevelDB() {