I have a project which consists of many smaller subprojects. For ease of use we are building everything as one big project - each subproject is add_subdirectory. This way all targets are visible, we can use EXCLUDE_FROM_ALL and build only necessary dependencies, it greatly improves build times. On the other hand, it is possible to unclude some of those subprojects as a platform for another project. In this case we would want to install necessary targets. Here comes the tricky part. Target names have to be unique within the whole cmake invocation, thus out target names tend to be component_subcomponent_module. On the other hand, while we are exporting them, it makes sense to use namespace component::subcomponent. Here is a problem, it still requires using target name, so the user would have to use component::subcomponent::component_subcomponent_module. Is there a way to support both including and importing the project and using namespaced names? I want to export component_subcomponent_module as a module in component::subcomponent namespace. I understand that I can create such alias within the project but I can't find any way to change (alias) the exported name.
add_library(component_subcomponent_mocks ...)
install(
TARGETS component_subcomponent_mocks
EXPORT FindComponentSubcomponentMocks
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include
)
install(
EXPORT FindComponentSubcomponentMocks
NAMESPACE component::subcomponent
DESTINATION cmake
)
You see where it is going, imported name will become component::subcomponent::component_subcomponent_mocks. On the other hand I can't create just:
add_library(mocks ...)
install(
TARGETS mocks
...
}
If I do it this way, then adding subprojects with add_subdirectory will end up with clashing project names. One option is not to use namespaces at all. If it already has to be unique within the whole project, then what is the point of adding namespaces? I don't like this idea but this is where it is all going to.
I've seen solutions like this: Cmake: Exporting targets with the same name in the build tree This does not solve my issues at all. I could configure it this way but the whole point of using subprojects is to avoid implementing additional layer of dependency tracking. Either we'd have to call make && make install on each (of a few hundred) dependency before proceeding to our build, or we'd have to believe that none of them has changed which leads to many mistakes. For imported projects we use this approach and it works fine but is unnecessarily slow. Just running cmake on each of them to update them in case of changes is taking a few minutes. All of this for 10 seconds of running tests you are currently developing. That's why the support for adding subprojects as subdirectories is must have for us.
In my understanding, the easiest solution would be installing target it an alias but there is no such option by default. For example:
install(
TARGETS component_subcomponent_mocks
EXPORT FindComponentSubcomponentMocks
...
)
install(
EXPORT FindComponentSubcomponentMocks
NAMESPACE component::subcomponent
ALIAS mocks
...
This way installed target would be component::subcomponent::mocks and target used by add_subdirectory would be component_subcomponent_mocks which I can easily aliast to the same namespaced version. Everything would be neat and consistent except it is not supported by default. Is there any alternative to it?
There were similar but not detailed questions to this, all without a particular answer. Change name of exported target cmake install xxxTargets.cmake with a different name from the original target
The whole problem is that I have to keep my target names unique, so they already include their "namespace" in the name and including it once again seems to be pointless.
You can set the EXPORT_NAME property on your targets. The following setup ensures consistent names (e.g. component::subcomponent::target) both in cmake superprojects as well as in exported configurations.
add_library(component_subcomponent_mylib ...)
set_property(TARGET component_subcomponent_mylib PROPERTY EXPORT_NAME mylib)
add_library(component::subcomponent::mylib ALIAS component_subcomponent_mylib)
install(TARGETS component_subcomponent_mylib
EXPORT FindComponentSubcomponentTargets
DESTINATION lib
)
install(EXPORT FindComponentSubcomponentTargets
DESTINATION cmake
NAMESPACE component::subcomponent::
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With