Skip to content

Installed phlexConfig.cmake is missing find_dependency() calls for public dependencies #656

Description

@brettviren

I tried building a minimal cmake package against phlex and found I had to include dependencies in my package that are not directly used in order to satisfy what phlex requires. I believe the fix is for Phlex's cmake should add some find_dependency() calls.

I hope it is okay to paste details generated from claude. If this kind of content is objectionable for the Phlex project, I'll hand-craft any future issue texts.

Or, if you prefer a PR, I can make one, though I am not a cmake expert.

Cheers,
-Brett.

Now, Claude writes:

Summary

The installed package config (phlexConfig.cmake) does not call find_dependency()
for phlex's public dependencies. As a result, the imported targets it defines
reference other packages' targets (Boost::boost, spdlog::spdlog, fmt::fmt,
TBB::tbb, Boost::json) that are not guaranteed to exist in the consumer's
project, so find_package(phlex) can succeed yet leave the targets unusable.

Details

phlexTargets.cmake defines imported targets whose INTERFACE_LINK_LIBRARIES
name targets from other packages, e.g.:

# phlex::model
INTERFACE_LINK_LIBRARIES "Boost::boost;spdlog::spdlog;fmt::fmt"
# phlex::core
INTERFACE_LINK_LIBRARIES "TBB::tbb;phlex::metaprogramming_int;phlex::model;phlex::utilities"

But phlexConfig.cmake includes CMakeFindDependencyMacro and then makes no
find_dependency() calls before including the targets file:

include(CMakeFindDependencyMacro)   # included, but never used
...
include("${CMAKE_CURRENT_LIST_DIR}/phlexTargets.cmake")

The contract of a config package is that after find_package(phlex) succeeds,
every imported target it defines is usable. Today that only holds if the
consumer happens to have already called find_package(Boost),
find_package(spdlog), find_package(TBB), etc. themselves.

Symptom

A minimal consumer that links, say, only phlex::model:

find_package(phlex REQUIRED)
target_link_libraries(mylib PUBLIC phlex::model)

fails at configure time with:

CMake Error at .../phlexTargets.cmake:85 (set_target_properties):
  The link interface of target "phlex::model" contains:
    Boost::boost
  but the target was not found.

The current workaround is for every consumer to replicate phlex's internal
dependency list (find_package(Boost), find_package(spdlog), ...) before
find_package(phlex). That is brittle: when phlex changes what its targets
link, every consumer silently breaks until updated.

Fix

Re-find phlex's public dependencies in phlexConfig.cmake.in, before including
the targets file, using find_dependency() (which forwards QUIET/REQUIRED
and fails with a clear message):

include(CMakeFindDependencyMacro)
find_dependency(Boost)
find_dependency(spdlog)   # transitively finds fmt
find_dependency(TBB)
# ... any other public deps (Boost components such as Boost::json) ...

include("${CMAKE_CURRENT_LIST_DIR}/phlexTargets.cmake")

Match the version constraints / components to what phlex actually requires
(e.g. specific Boost components). Once this is in place, consumers can drop
their workaround find_package() calls entirely.

Alternative

For any of these that are implementation details not exposed in phlex's public
headers, the cleaner fix is to make them PRIVATE link dependencies so they
never appear in INTERFACE_LINK_LIBRARIES and consumers need not find them at
all. Dependencies whose types appear in public phlex headers are genuinely
public and should be handled via find_dependency() as above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions