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.
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 callfind_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'sproject, so
find_package(phlex)can succeed yet leave the targets unusable.Details
phlexTargets.cmakedefines imported targets whoseINTERFACE_LINK_LIBRARIESname targets from other packages, e.g.:
But
phlexConfig.cmakeincludesCMakeFindDependencyMacroand then makes nofind_dependency()calls before including the targets file: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:fails at configure time with:
The current workaround is for every consumer to replicate phlex's internal
dependency list (
find_package(Boost),find_package(spdlog), ...) beforefind_package(phlex). That is brittle: when phlex changes what its targetslink, every consumer silently breaks until updated.
Fix
Re-find phlex's public dependencies in
phlexConfig.cmake.in, before includingthe targets file, using
find_dependency()(which forwardsQUIET/REQUIREDand fails with a clear message):
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
PRIVATElink dependencies so theynever appear in
INTERFACE_LINK_LIBRARIESand consumers need not find them atall. Dependencies whose types appear in public phlex headers are genuinely
public and should be handled via
find_dependency()as above.