Skip to content

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

Description

@alexreinking

On Ubuntu, FlatBuffers is packaged to include both the static and shared libraries:

  • flatbuffers::flatbuffers points to the static libraries
  • flatbuffers::flatbuffers_shared points to the shared libraries.

But as packaged by Fedora, FlatBuffers does not include the static libraries at all. So only:

  • flatbuffers::flatbuffers_shared is available, pointing at the shared libraries.

Therefore, a simple CMake project like this can fail to configure in certain environments through no apparent fault of the project author:

cmake_minimum_required(VERSION 3.28)
project(myproj)

find_package(FlatBuffers REQUIRED)

# ...

add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE flatbuffers::flatbuffers)  # broken on shared-only installs

We discovered this issue in Halide when a colleague reported the find_package(FlatBuffers) call failing on Fedora 44. Halide links directly to flatbuffers::flatbuffers, which breaks on shared-only builds. I claim this is an issue with the contract on the FlatBuffers CMake package.

I wrote a blog post about distributing dual static/shared libraries in CMake a few years back. In it, I argue that libraries should expose a single target to CMake downstreams (here, flatbuffers::flatbuffers) because (a) they almost never need to link to both static and shared at the same time, (b) they rarely want both and, if they do, it's likely because they're packaging it and are willing to eat the cost of building it twice, (c) when a packager of the downstream wants to switch how FlatBuffers is built or linked, they must patch the downstream to use (or omit) the _shared suffix.

I would like to adjust FlatBuffers' CMake package to expose only flatbuffers::flatbuffers. We have several mitigations to make this change less disruptive to downstreams:

  1. We can provide an ALIAS target flatbuffers::flatbuffers_shared that points to flatbuffers::flatbuffers when it is shared.
  2. The CMake package can provide static and shared components that enforce one or the other when a downstream has a genuine need for one flavor.
  3. The CMake package can honor FlatBuffers_SHARED_LIBS as a cache/environment toggle.
  4. The CMake package can honor BUILD_SHARED_LIBS when both are available.
  5. Load whichever is available, preferring static.

Items (2)-(5) form a precedence chain resolved at configure-time: an explicit component request wins, then the package-specific variable, then the standard hint, and finally whatever is available. Switching between the two at configure-time then becomes a matter of setting BUILD_SHARED_LIBS, which is perfectly standard.

Would this be a welcome change for this project? I have a branch ready to PR.

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