Shared Library Contract

OpenMeta supports static and shared C++20 libraries. The shared library is a C++ ABI artifact, not a stable C ABI. A consumer must use a compatible compiler, C++ standard library, compiler runtime, and build mode.

Build and Consume

Build a runtime package with only the shared library:

cmake -S . -B build-shared -G Ninja -DCMAKE_BUILD_TYPE=Release \
  -DOPENMETA_BUILD_STATIC=OFF -DOPENMETA_BUILD_SHARED=ON
cmake --build build-shared
cmake --install build-shared --prefix /opt/openmeta

The package is installed under ${CMAKE_INSTALL_LIBDIR}/cmake/OpenMeta. Consumers that require dynamic linkage should select the explicit target:

find_package(OpenMeta CONFIG REQUIRED)
target_link_libraries(my_program PRIVATE OpenMeta::openmeta_shared)

ABI and Runtime

The package publishes OpenMeta_ABI_VERSION, currently 4. This is an unfrozen development label: public C++ layouts and APIs may change while it stays 4. Rebuild consumers against matching headers and libraries when they change; the label does not guarantee binary compatibility across snapshots. ELF/macOS use ABI major 4; Windows uses openmeta-4.dll. The initial local 0.7.0 build used label 5; 0.7.1 returns to 4 by project policy.

The package uses SameMajorVersion for minimum-version discovery. For example, find_package(OpenMeta 0.7 CONFIG REQUIRED) accepts 0.8.0. Newer minimums are rejected, and EXACT or version ranges can constrain selection further. A future 1.x package will not satisfy a 0.x request under this policy.

This selects a package for rebuilding source; it does not establish binary compatibility or guarantee that experimental APIs remain unchanged. Rebuild with matching headers and libraries and check the APIs used by the application. See Migrating to OpenMeta 0.8.

When OpenMeta is built with OPENMETA_USE_LIBCXX=ON, the package requires a Clang consumer and propagates -stdlib=libc++ for compilation and linking. For all other builds, use the same compiler family, C++ runtime, and compatible runtime settings as the package producer.

On MSVC, select the runtime library through CMAKE_MSVC_RUNTIME_LIBRARY when configuring OpenMeta. The installed targets propagate that selection to CMake consumers, and the package publishes it as OpenMeta_MSVC_RUNTIME_LIBRARY. For example, use MultiThreaded with an /MT dependency prefix and MultiThreadedDLL with an /MD dependency prefix. The default is /MD in Release and /MDd in Debug.

Shared implementation dependencies are private, so a shared-only package does not require zlib, Brotli, Expat, OpenSSL, or the optional DNG SDK CMake packages merely to configure a consumer. Static targets continue to export their link closure.

On ELF, static implementation archives are excluded from the dynamic symbol table. On macOS, OpenMeta rejects a static implementation dependency for a shared build because it could otherwise become a public dylib symbol; provide a dynamic dependency package or disable that optional feature.

On Windows, the static archive is openmeta_static.lib, the shared import archive is openmeta_shared.lib, and the runtime DLL is openmeta-4.dll. Deploy that DLL next to the application or follow the normal Windows DLL search policy. Unix shared builds hide implementation symbols. Windows uses CMake’s generated DLL export table until the C++ API has a separately frozen per-symbol export surface.

Verification

The openmeta_gate_shared_install target stages the configured package, then configures, builds, and runs an independent CMake consumer against the staged OpenMeta::openmeta_shared target:

cmake --build build-shared --target openmeta_gate_shared_install

With OPENMETA_BUILD_TESTS=ON, CTest exposes the same check as openmeta_shared_library_install_consumer. Linux and Windows shared-only gates run in public CI; macOS package validation is a release check.