How to install(EXPORT...) in subprojects with each having same dependencies

I am getting

CMake Error: install(EXPORT "mySubProjATargets" ...) includes target "mySubProjBshared" which requires target "logger" that is not in this export set, but in multiple other export sets: lib/cmake/mySubprojATargets.cmake, lib/cmake/mySubprojATargets.cmake.
An exported target cannot depend upon another target which is exported multiple times. 
Consider consolidating the exports of the "logger" target to a single export.

and indeed , logger has been installed and exported in another subproject mySubprojATargets.cmake already. This is because I am trying to avoid having to maintain some kind of global list of common dependencies and a single global /common project Targets.cmake. Subprojects are being added at different time and in their CMakeLists.txt I would not want to track other projects. cmake already knows that there is a duplicate to another …Targets.cmake so could not it proceed wioth Warning and still make duplicate into the …Targets.cmake. Then the upstream project importing /including the Config.cmake, …Targets.cmake would detect duplicate and ignore its installation?
How could I “consolidate the exports of the “logger” target to a single export” if both subprojects have it as target A and target B both dependent on it via corresponding target_link_libraries lists and I need to export both target A and B?

It appears as though the same EXPORT set is being installed twice, not that the target belongs to multiple export sets. Do you have a project to point to for the actual code?

Thanks for responding but I don’t have actual project at hands as this issue was logged couple months ago so I had to refactor to have single install(EXPORT calls in a root CMakeLists.txt as a workaround. So could you please advise based on the general requirements. In a project with multiple subprojects, with interdependence, how should installation be done ? I would like each project to create its own export-name Targets.cmake file, while each subproject has common dependent target. for instance
CMakeLists.tx for mySubProjA and mySubProjB 2 files mySubProjATargets.cmake and mySubProjBTargets.cmake are created. Both of them have dependency on another subproject target logger so logger has to be installed but cmake does not allow (would fail) logger to be installed twice with install(EXPORT calls in each subproject and it fails if logger is removed from one of the subproject’s install(EXPORT target list

Each project should install its own targets in its own export set. There shouldn’t be the need for any project other than logger itself to install the logger target and add it to an export set.

The issue is that within a single project there are multiple sub-projects which have dependency on common sub-project and when they installed, each of them attempts to that common dependency bc it is inherited transient dependency. For instance
target_link_libraries(mySubProjA logger) target_link_libraries(mySubProjB logger) install(TARGETS mySubProjA mySubProjB
So could you please address such case?

No. logger should control its installation and mySubProjA should trust that it will install properly. Same with mySubProjB. Your project can stitch things together in the right order so everybody is happy.

Again, cmake installation is using inheritance rule and automatically installs transient dependencies. So when install(TARGETS mySubProjA …EXPORTS targets_export_name.) ) and install(EXPORT targets_export_name) executed, cmake will install logger automatically as it is transient dependency of mySubProjA. Same goes for mySubProjB

I am seraching for a general and simple way to solve this.
Perhaps his may be interesting for you: How to install component libraries like boost?

@ClausKlein , great thanks, so you recognized this as an issue? Then could you please include Craig and brad.king into the loop ?

I agree with @ben.boeckel’s comments so far. I suspect the problem has to do with how you are combining the dependencies into your project, but without a complete example to look at, that’s just a guess. Please provide a complete, minimal example that demonstrates your problem.

@craig.scott I had to install the spdlog library hier, even it would be installed from fetch contents:

I found this very strange!

The resulting stage tree after install:

bash-3.2$ tree -d stage/
├── include
│   ├── fmt
│   ├── simplelog
│   │   ├── backend
│   │   │   ├── common
│   │   │   ├── null
│   │   │   ├── spdlog
│   │   │   ├── syslog
│   │   │   └── systemd_journal
│   │   └── detail
│   └── spdlog
│       ├── cfg
│       ├── details
│       ├── fmt
│       └── sinks
└── lib
    ├── cmake
    │   ├── fmt
    │   ├── simplelog
    │   └── spdlog
    └── pkgconfig

21 directories

Unfortunately I dont have full project ready to post but hope we will be able demo implementation base d on snippet that @ClausKlein kindly posted. With my questions I am trying to check the cmake expected behavior or requirements before implementation so could you please advise if cmake satisfies the following high level requirements.
R1. cmake shall be able to install a project’s target with all its transient dependencies if they are being built with the project. For example if target A depends on targets B, C and all of the targets are being built by the project, cmake shall be able to install B,C automatically when installation of A is requested. NOTE: this should not depend whether or not these target are built as static or shared library (?)
R2. cmake shall allow installation of targets which have common dependencies if they are also built with the project or are external libraries added as INTERFACE libraries. In this case cmake shall not fail build as it detects that common target has been already installed.
For example if A depends on targets B, C while E depends on D,C, cmake will allow installation of A and E with all their transient dependencies despite A and E have common dependency C and without the need for cmake user to exclude common dependency from the list of targets being installed.

CMake only installs targets it is explicitly told to install. Doing “magic” behind the scenes to also install transitive dependencies would need to be an opt-in thing because otherwise one would easily end up with dozens of duplicate targets installed. That said, the feature does not exist at all right now and would need design work on the CMake to get it to do anything like that.

I think this would also need to be opt-in (possibly listing other targets to exclude from the transitive tree or to stop recursing at).