Coming from https://github.com/conan-io/conan/issues/7217#issuecomment-648998898
closes #6069
There is one limitation regarding the name of the find_package files and targets in CMake. Currently, the name specified in self.cpp_info.names["cmake_find_package"] is the one used to generate the Find<name>::component.
There are use cases where those names are different, for example protobuf has FindProtobuf.cmake while the targets are protobuf::libprotobuf.
The proposal for this would be to add something like self.cpp_info.filename["cmake_find_package"] = "Protobuf" so both names can be defined in the recipe:
def pacakge_info(self):
self.cpp_info.filename["cmake_find_package"] = "Protobuf"
self.cpp_info.names["cmake_find_package"] = "protobuf"
self.cpp_info.components["libprotobuf"] = "libprotobuf"
cc/ @TimSimpson @uilianries
This one is related to https://github.com/conan-io/conan/issues/6069, probably this one should close that one once fixed/added/closed
There's another case where multiple CMake packages might use a common namespace, such as a theoretical modularized Boost. To restate that example, there may exist a Conan package for Boost-coroutine and another one for Boost-asio. From CMake these would be used by calling find_package(Boost-coroutine), which would bring in target Boost::coroutine, and find_package(Boost-asio) which would bring in target Boost::asio.
If filename is added, it would be possible to make this work, however self.cpp_info.names["cmake_find_package"] would be Boost for both packages.
I would guess this might lead to adverse affects on other generators as they could create files or other build components all named "Boost" which would conflict with each other.
Would it be better to instead create a property like cmake_namspace? This way it only affects the generated CMake. So it would be:
def pacakge_info(self):
self.cpp_info.names["cmake_find_package"] = "Protobuf"
self.cpp_info.cmake_target = "protobuf"
self.cpp_info.components["libprotobuf"] = "libprotobuf"
Then for the boost example you'd have
def pacakge_info(self):
self.cpp_info.names["cmake_find_package"] = "Boost-coroutine"
self.cpp_info.cmake_target = "boost"
self.cpp_info.components["libprotobuf"] = "coroutine"
and
def pacakge_info(self):
self.cpp_info.names["cmake_find_package"] = "Boost-asio"
self.cpp_info.cmake_target = "boost"
self.cpp_info.components["libprotobuf"] = "asio"
Your modularized boost example would work as follows with the initial proposal:
def pacakge_info(self):
self.cpp_info.filename["cmake_find_package"] = "Boost-asio"
self.cpp_info.names["cmake_find_package"] = "boost"
self.cpp_info.components["asio"].libs = ["asio"]
def pacakge_info(self):
self.cpp_info.filename["cmake_find_package"] = "Boost-coroutine"
self.cpp_info.names["cmake_find_package"] = "boost"
self.cpp_info.components["coroutine"].libs = ["coroutine"]
@jgsogo I'm wondering if there would be unforeseen issues with other generators since self.cpp_info.names is so well-established and it may be hard to predict all the effects of having multiple packages set it to the same value. If people start trying to share the same setting for names across multiple packages just to change the CMake target namespace, that seems more intrusive than if they could change a property that would just change the CMake target namespace.
Another idea: what if the include statements for the build modules which appear in the generate find modules were moved to after the current targets were created? which would make it possible to clone them? Build modules can be used to create "clones" of the find module targets today, but doing so involves relying on the same variables Conan happens to use to create the targets which may be brittle.
In my mind this seems safer as it lets all the other code in Conan use the targets Conan already generates today, while allowing CMake superfans to use alternate targets which look exactly how they wish.
The names approach is already working, names are assigned per generator, so adding to CMake doesn't mean it will affect other generators. The feature (together with the filename) does exactly what you are suggesting: _"just change the CMake target namespace"_. Name collision could eventually be an issue, but there is nothing we can do from the Conan side (maybe an error instead of overriding), it is up to the recipe maintainers to manage that situation, we'll try to do our best with the recipes in conan-center-index.
The idea for the build_modules is to provide functions/macros to the CMake consumers that were already provided by the CMake's module files, not to impostate the targets defined in the recipe. Now that we will be able to replicate the name of the FindXXXX.cmake file, the namespace of the provided targets and the name of the targets themselves, there is no need to "clone" those targets. If a consumer needs different names that snippet should go on the consumer's side.
@jgsogo you're right: names are assigned per generator, so adding to CMake doesn't mean it will affect other generators. Sorry, I was in some sort of fugue state when I wrote the above and was got self.cpp_info.names (plural) mixed up with self.cpp_info.name which, of course, can can keep doing whatever it already does today.
@danimtb @jgsogo I can contribute this code if that's helpful. I've started a work on a branch here though it needs another few rounds of polish. Full disclosure: I don't have much time to work on this stuff outside of nights and weekends though I'd certainly like to see this in Conan soon. It's also no big deal if someone else picks it up before me.
I've also created this project as a recreate to test the situation of having multiple Conan packages which use the same target namespace in their find module exported targets. Right now my branch linked above can successfully build both projects in the recreate, but when I scan the files I can spot a couple of places where it's creating the wrong targets in the dependent project's find modules still.
One observation I'd like to share is that there are a lot of global variables in the generated find modules which I had to change to use the new filenames attribute instead to make sure the two modules didn't create the same variables as each other. I'm probably beating a dead horse but it made me wonder again if having an attribute specifically for the CMake namespace target would be more optimal in the long run.
Second, the requires attribute of the components look like they refer to CMake targets- and in most cases they do - but actually the string before the :: is the package name defined from within Conan and not the CMake target namespace name.
This is probably intuitive from a heavy Conan user's perspective but could confuse new users coming from a strictly CMake packaging world and should probably get a call-out in the docs. For example, the recreate's project B's package_info method refers to acme-a::a, while in CMake no such target exists (there it's called ACME::a).
Hi! Contributions are more than welcome. If you are working on this, feel free to open the PR as soon as possible so we can see how it is going and provide feedback to you as early as possible. I'm assigning it to the next release, we have four weeks ahead, if you think you won't have time to finish it, just tell us and we will resume your work.
About the values in the requires field, more/better docs are always needed (PRS more than welcome 馃檮 ), but yes, as you have realized they use the name of the package and components, not any other name assigned via names["<generator>"].
There's one other scenario, where the upstream does not provide a namespace. The issue is highlighted here https://github.com/conan-io/conan-center-index/issues/2151
This has been implemented in #7320. Thanks a lot to everyone for the collaboration!!
Most helpful comment
This has been implemented in #7320. Thanks a lot to everyone for the collaboration!!