Skip to content

Reconsider promoting Conan as a consumption route: profile-vs-toolchain mismatch is a silent ABI trap, especially for the C++ binding #38

Description

@AndreaLanfranchi

The repository now ships a Conan recipe (conanfile.py, added in 1bb10689). The recipe itself is carefully done: the MDBX_* build options are modeled, compiler.libcxx participates in the binary hash, and packages rebuild on option changes. My concern is not the recipe's quality but what packaging libmdbx as a prebuilt Conan binary invites, and I'd like to suggest de-emphasizing it in favor of source-level consumption (amalgamated sources or CMake subproject/FetchContent), or at least fencing it with warnings and safer defaults.

The core problem: Conan is profile-sticky, and the profile is not the consumer's toolchain. Conan resolves, builds and caches binaries according to the active profile, typically the default one auto-detected once by conan profile detect and cached forever after. Nothing ties that profile to the compiler the consumer's project is actually built with. On any multi-compiler machine (system gcc plus clang, or several gcc majors, which describes every developer workstation and most CI images) it is entirely routine to end up with libmdbx compiled by the profile's compiler while the consuming program is compiled by another. Conan will not flag this: the profile is internally consistent, the binary hash matches the profile, find_package(mdbx) succeeds, and the mismatch surfaces only at runtime.

Why this bites libmdbx harder than a typical C library. For the pure-C core the risk is modest, since the platform C ABI is stable across gcc/clang. But the default packaging is shared=True with mdbx.build_cxx=Default (which resolves to ON), so the package ships the C++ binding: mdbx.h++ is compiled by the consumer's compiler while its out-of-line definitions and extern template instantiations (src/mdbx.c++, e.g. mdbx::default_buffer) live in the package's binary, compiled by the profile's compiler. That splits one C++ API across two toolchains and couples the two sides tightly:

None of these are Conan bugs. They are the cost of consuming a header-heavy C++ library as a prebuilt binary selected by a profile rather than by the consumer's actual toolchain. The failure modes are the worst kind: no link error, no diagnostic, just misbehavior or aborts at runtime.

Why source-level consumption avoids the whole class. libmdbx already provides a first-class answer: the amalgamated source for direct embedding, and clean CMake for add_subdirectory/FetchContent. In both cases the library and the application are compiled by the same toolchain with the same flags in the same build, so profile drift is structurally impossible and the MDBX_* option set is decided by the consumer, visibly, at configure time.

Suggestions, in decreasing order of strength; any subset would help:

  1. Document (README / packaging notes) that source-level consumption is the recommended route, and that the Conan package is provided as a convenience with an explicit warning: the active Conan profile must match the consumer's real compiler, stdlib and build type, especially when the C++ binding is used.
  2. Consider defaulting mdbx.build_cxx to False in the recipe: a C-only package is robust against compiler mixing thanks to the stable C ABI, while C++ users, who are exactly the ones exposed to the trap, would opt in consciously or, better, embed the sources.
  3. Have package_info()/validate() emit a Conan warning when the C++ portion is enabled in a shared package, pointing at the toolchain-match requirement.

To be clear: this is not "remove the recipe". ConanCenter carries an independent libmdbx recipe anyway, so users who want Conan will use it regardless. The ask is that this repository not silently endorse a consumption route whose sharpest edge (profile-vs-toolchain drift on multi-compiler systems) is invisible until it corrupts a debugging session, or a database.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions