CMake package should expose a single canonical flatbuffers::flatbuffers target
- Dominant language
- C++
- Stars
- 26.5k
- Forks
- 3.7k
- PR merge metrics
- No merged PRs in 30d
Description
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
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](https://github.com/halide/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](https://alexreinking.com/blog/building-a-dual-shared-and-static-library-with-cmake.html) 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.
Contributor guide
Research direction
Start by reproducing the minimal CMake project shown in the issue with shared-only and dual static/shared FlatBuffers installations, comparing the available imported targets. Review the existing FlatBuffers CMake package and determine how the requested canonical target, flavor selection, and compatibility behavior should be represented; done means downstream configuration works consistently across the described environments.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cmake, cpp
- Domain
- build-system
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100