Skip to content

Expose a single canonical flatbuffers::flatbuffers target - #9208

Open
alexreinking wants to merge 1 commit into
google:masterfrom
alexreinking:areinking/canonical-flatbuffers-target
Open

Expose a single canonical flatbuffers::flatbuffers target#9208
alexreinking wants to merge 1 commit into
google:masterfrom
alexreinking:areinking/canonical-flatbuffers-target

Conversation

@alexreinking

Copy link
Copy Markdown

FLATBUFFERS_BUILD_FLATLIB always built flatbuffers::flatbuffers as STATIC, with a separately-typed flatbuffers::flatbuffers_shared only available when FLATBUFFERS_BUILD_SHAREDLIB was explicitly requested. A distro that wants to avoid shipping static libraries (e.g. Fedora's flatbuffers-devel, which builds with -DFLATBUFFERS_BUILD_SHAREDLIB=ON -DFLATBUFFERS_BUILD_FLATLIB=OFF) ends up with a package that never installs FlatBuffersTargets.cmake at all. In this case, find_package(FlatBuffers) reports success, but the canonical flatbuffers::flatbuffers target consumers actually link against silently doesn't exist, so target_link_libraries fails downstream.

This applies the design from
https://alexreinking.com/blog/building-a-dual-shared-and-static-library-with-cmake.html: flatbuffers never materializes a _shared-suffixed physical library. There is exactly one library target (flatbuffers, aliased flatbuffers::flatbuffers), typed by BUILD_SHARED_LIBS/FlatBuffers_SHARED_LIBS like any target without an explicit STATIC/SHARED keyword. Its install(EXPORT) targets file is named for whichever type actually got built (FlatBuffersStaticTargets.cmake or FlatBuffersSharedTargets.cmake), so a packager who wants to offer both flavors runs two separate configure/build/install passes into the same prefix instead of building both from one configure.

flatbuffers-config.cmake resolves which one to load with this precedence chain: an explicit static/shared COMPONENTS request wins, then FlatBuffers_SHARED_LIBS, then BUILD_SHARED_LIBS (falling back to whichever variant is actually installed), then whatever is available, preferring static. flatbuffers::flatbuffers_shared is never a real target -- it's an ALIAS to flatbuffers::flatbuffers, created only when that resolves to a shared library, purely so consumers hardcoded to the legacy name keep working.

We also add a deprecation shim for FLATBUFFERS_BUILD_SHAREDLIB to keep downstream build scripts stable, while notifying them of eventual changes to the packaging here.

Finally, we add an integration test workflow to GitHub Actions to ensure both single- and multi-configuration install trees resolve as expected, according to the above precedence chain.

Fixes #9206

FLATBUFFERS_BUILD_FLATLIB always built flatbuffers::flatbuffers as STATIC,
with a separately-typed flatbuffers::flatbuffers_shared only available when
FLATBUFFERS_BUILD_SHAREDLIB was explicitly requested. A distro that wants to
avoid shipping static libraries (e.g. Fedora's flatbuffers-devel, which
builds with -DFLATBUFFERS_BUILD_SHAREDLIB=ON -DFLATBUFFERS_BUILD_FLATLIB=OFF)
ends up with a package that never installs FlatBuffersTargets.cmake at all.
In this case, find_package(FlatBuffers) reports success, but the canonical
flatbuffers::flatbuffers target consumers actually link against silently
doesn't exist, so target_link_libraries fails downstream.

This applies the design from
https://alexreinking.com/blog/building-a-dual-shared-and-static-library-with-cmake.html:
flatbuffers never materializes a "_shared"-suffixed physical library. There is
exactly one library target (flatbuffers, aliased flatbuffers::flatbuffers),
typed by BUILD_SHARED_LIBS/FlatBuffers_SHARED_LIBS like any target without
an explicit STATIC/SHARED keyword. Its install(EXPORT) targets file is named
for whichever type actually got built (FlatBuffersStaticTargets.cmake or
FlatBuffersSharedTargets.cmake), so a packager who wants to offer both
flavors runs two separate configure/build/install passes into the same
prefix instead of building both from one configure.

flatbuffers-config.cmake resolves which one to load with this precedence
chain: an explicit `static`/`shared` COMPONENTS request wins, then
FlatBuffers_SHARED_LIBS, then BUILD_SHARED_LIBS (falling back to whichever
variant is actually installed), then whatever is available, preferring static.
flatbuffers::flatbuffers_shared is never a real target -- it's an ALIAS to
flatbuffers::flatbuffers, created only when that resolves to a shared library,
purely so consumers hardcoded to the legacy name keep working.

We also add a deprecation shim for FLATBUFFERS_BUILD_SHAREDLIB to keep
downstream build scripts stable, while notifying them of eventual changes
to the packaging here.

Finally, we add an integration test workflow to GitHub Actions to ensure both
single- and multi-configuration install trees resolve as expected, according
to the above precedence chain.

Fixes google#9206
@github-actions github-actions Bot added c++ CI Continuous Integration labels Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ CI Continuous Integration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CMake package should expose a single canonical flatbuffers::flatbuffers target

1 participant