Open CraigHutchinson opened 2 years ago
I would expand on option B.
Instead of having a special syntax for the new macro, allow listing of targets in CPMDeclarePackage
.
Here's some proposed code to illustrate my addition:
CPMDeclarePackage("gh:catchorg/Catch2@2.5.0") # implicitly adding known target Catch2::Catch2
CPMDeclarePackage(
NAME multilib
VERSION 1.2.3
GITHUB_REPOSITORY example/multilib
TARGETS
multilib::a
multilib::b
multilib-examplelib # allow unscoped
) # now we have three more known targets
cpm_target_link_libraries(myapp
Catch2::Catch2 # OK. Implicitly defined from first package
multilib::a # OK. Explicitly defined in second package
multilib-examplelib # OK. Explicitly defined in second package
foobar # OK. Unknown target. Pass down to target_link_libraries
foo::bar # OK. Unknown target. Pass down to target_link_libraries
cpm{multilib::b} # OK. Explicitly defined in second package
cpm{baz} # ERROR. baz is an unknown target and it was expected to come from a cpm package (not passed down)
)
Thus the added packages will depend on the known targets. Known targets come from CPMDeclarePackage
.
This, by the way, ties in well with a feature I'm working on (though not very actively) which, combined with my addition would allow code like:
CPMDeclarePackage("cpm:Catch2") # declare package from remote repo
# ...
cpm_target_link_libraries(myapp
Catch2::Catch2 # target from remote package
)
@iboB I love the addition of TARGETS
declared for the Package, really solves using unscoped
targets. This also acts as a validation point on package compatibility. For example target_link_libraries
links "Foo::Bar" which may not be defined which would be a generic-error, but by addition of TARGETS
the error can be more informative so the developer knows the source of the issue.
e.g.
"Package "Foo" does not define target "Foo::Bar"
is much more insightful than the current
Foo::Bar is not built by this project
Related to the 'CPM:<_package_>' source type its not very clear, do you have a PR or issue link to discuss on this aspect?
💡 To decide when considering the new parameter:
TARGETS
could overlap with options for in ExternalProject or FetchContent TARGETS
check could be added as a feature to ExternalProject
instead/later (outside of CPM but could be considered)TARGETS
the best option, some alternatives to consider (I like TARGETS
for now):
IMPORTS
IMPORT_TARGETS
USE_TARGETS
I agree that TARGETS
is not the best name. I'm thinking PROVIDES
or PRODUCES
.
To be honest I'm not in love with any of the proposed names for this argument
This feature depends on #414, or something similar if not exactly that, which will allow a clear distinction between a package's lifecycle phases: declared, defined, and added
This feature needs to take into account new feature for CMake v3.24 FetchContent override of find_package
https://cmake.org/cmake/help/latest/module/FetchContent.html#command:fetchcontent_declare
The premise is it would be really powerful to have a
target_link_libraries
alternative that instead of just linking existing packages could pull the respective packages using CPM when the library isn't yet available.This is based on the general usage pattern of find-package+link it as a dependency. By flipping the usage for end-user convenience it could later smooth core Cmake integration.
Example A
single-argument fetch+link syntax
Main issue = selecting target library from package
This initial example extends the single-argument syntax to include the
<target>
extension to make it possible to choose which target to link from the package:<single-arg-syntax>{<target>}
Pros:
CpmAddPackage
{<target>}
could be omitted as the package ALIAS name can be used-by-default i.e. {yaml-cpp::yaml-cpp} for most modern CMake compliant packages (ALL the examples on the main readme infact!)Cons
Example B
Declare separate then fetch+link using
<package>::<alias_target>
Main issue = Cmake packages that don't conform to common naming practices
This example is closer to the ideal. The issue is that if the package e.g.
Catch2
didn't use either:Catch2
Catch2::Catch2
Most example (All that I checked) repos appear to conform to these requirements.To solve this in Example B we would allow a more verbose alternative syntax also e.g.
<package>{<target>}
which could be used in the non-conforming cases. Note this example below uses the nice-and-consistent named packages where the redundancy is clear showing the reduced syntax above being valuable:Further, it may be possible to omit the
CPMDeclarePackage
by using the existing CPM cache package of the supplied name if we stored some information about the newest package in the cache etc.. Not sure this is a good idea.An even more powerful option would be to support a
.cpmpackages
file would be super powerful so we can just reference packages from that by name. I SeeCPMUsePackageLock()
sort of fulfills this but its not implicitly used and serves a subtly different use-case than defining a list of package modules in one place.UPDATE: A good alternative is provided in comment: https://github.com/cpm-cmake/CPM.cmake/issues/404#issuecomment-1256545915
Actions:
CPMDeclarePackage
such asPROVIDED_TARGETS