-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add package dependency checking to install_basic_package_files()
#317
Comments
Fyi @GiulioRomualdi |
I did not review this in detail, but thanks a lot for this! This functionality is quite useful and would avoided us several problems for exaple the one listed in robotology/unicycle-footstep-planner#33 .
Just to understand, why you don't use the |
I am a bit afraid (even if I am not sure what failure could cause) in silently adding tests in a CMake function call. Do you think it could make sense to make this opt-in instead of opt-out? |
I believe this would significantly diminish the usefulness of the extra check: we would have to teach people to enable it explicitly (which costs time and effort and makes their build scripts noisier), and it wouldn't be enabled on old projects. Personally I'm strongly in favor of everything that reduces the noise level in CMake files. If you are worried about inadvertent breakage, I guess we could first make it opt-in, then gain some experience in the field, and later make it opt-out if no problems occur. Note that my extension defines a custom target (through |
I haven't seen the code yet (sorry, I'm reading this from the phone), but having an easy way to test a package and it's targets seems like a very good idea (also it would help a lot in creating unit tests for this module) , but in my opinion it goes beyond the scope of I'll just dump a few random ideas and comments in random order here
I will have a look at the code next week, sorry, but I don't think I'll be able to do it earlier. |
Thank you both for the feedback, much appreciated.
This would boil down to do_thing(args...)
validate_thing_args(args...) i.e. we would have an optional extra step just for checking that the arguments to
You mean like this? project(Foo ...)
add_library(Foo INTERFACE)
# no calls to `find_package(Bar)` or `target_link_libraries(Foo PRIVATE Bar::Bar)` here!
install_basic_package_files(Foo
COMPATIBILITY SameMajorVersion
DEPENDENCIES
"Bar") # not actually available on this system That would indeed break my check. But is this really a sensible scenario? It would also lead to inconsistency; consuming the targets of Foo through
I agree with @traversaro that Why do you dislike generating a custom target for the check? CMake already generates some custom targets by itself (e.g.
Note that the subproject is only ever configured, not built, and hence neither compiled nor linked. I only want the transitive dependency search which CMake runs during configuration.
But what would be the benefit of duplicating CMake's target resolution logic?
But |
That should no longer be a concern:
(https://gitlab.kitware.com/cmake/cmake/issues/20301#note_691768) |
But that would allow to do just the
Unfortunately it is, see YARP_eigen and YARP_cv for example.
👍 to this, I'm in favour of having it in a separate module, using
Because almost nobody knows about them, and they are not used by anyone, and if you have lots of targets it's hard to notice them. Also if you have tests in your program it doesn't make sense to have some checks run by
But I was actually thinking to split it in one command to check a single target, and eventually some other command that checks the export calling the first command for each target in the export. This could give you some more flexibility and allow to skip tests that require extra dependencies not available on the system at build time. Adding also the header to include, it could become a good test to ensure that each target will work. |
So a separate module it is. I'll submit a new PR.
Perhaps like this? add_package_test(<Name>
[EXPORT <export> | TARGETS <target>...] # defaults to EXPORT <name>
[INCLUDE <header>...]) Then I could say add_package_test(Foo) to generate a config-only test that just checks whether all CMake targets are available (i.e. what my current PR does, but under a dedicated test named, say, add_package_test(Foo
TARGETS Foo::Foo
INCLUDE <foo/foo.hpp>) to additionally generate code that Would you prefer |
Looks good, but I just had an idea, what do you think about using the |
What would that test entail? Would it just test that a header includes all its dependencies, i.e. that compiling a source file consisting of I've thought about
Which other errors would be prevented by having |
install_basic_package_files()
makes package installation a breeze by saving us from writing pages of boilerplate code. Yet I think we all agree that it is a crutch: partly because it ought to be provided by CMake itself (cf. cmake/#18634, "Simplify exporting of CMake Packages"), but also because it necessitates duplicating the package dependencies of the exported targets, something CMake should be able to track but currently doesn't (cf. cmake/#17006, "Add new properties to better track whatfind_package
command was used to import the target").For example, the exported targets of my library depend on gsl-lite, which I express in the target definition using
find_package()
andtarget_link_libraries()
:But to install the library package I additionally need to write:
This is clearly suboptimal, but as far as the
install_basic_package_files()
abstraction goes, I believe this is the best we can do. We cannot really track the packages of target dependencies unless cmake/#17006 is resolved. Unfortunately, for me this duplication has proven error-prone with more complicated packages: I often forget adding packages to theDEPENDENCIES
section and only notice after I broke someone who depended on my package.Now, we may not be able to automate away this duplication, but I think
install_basic_package_files()
can do some extra work to validate the package dependencies. The idea is as follows:When installing a package with exports,
install_basic_package_files()
generates a subproject which consumes the config file in the build directory as a package and defines an executable target which links to all targets our package exports. It then usesExternalProject_Add()
to generate an extra targetcheck-package-dependencies
which configures the subproject.Thus, if one of the exported targets has a dependency that was forgotten in the
DEPENDENCIES
argument, building the package (with testing enabled) causes thecheck-package-dependencies
target to fail:I attempted an implementation of this idea in PR #316. I'm not quite happy with some of the details though:
CMAKE_TESTING_ENABLED
is set, which is the case ifenable_testing()
has previously been called. UnfortunatelyCMAKE_TESTING_ENABLED
is currently undocumented; in cmake/#20301 "DocumentCMAKE_TESTING_ENABLED
" I request that it be documented.<package>Targets.cmake
file foradd_library(<target> ... IMPORTED)
statements instead.ExternalProject_Add()
has an argumentBUILD_ALWAYS
, but there is noCONFIG_ALWAYS
; I work around by passing a timestamp as a config argument.Perhaps some ugliness in the implementation is acceptable because this is just a sanity check and doesn't alter the semantics of
install_basic_package_files()
. And if something goes wrong, dependency checking can be suppressed by setting the optionNO_PACKAGE_DEPENDENCIES_CHECK
in my draft.What do you think?
The text was updated successfully, but these errors were encountered: