# Package-config generated by \`install(EXPORT)\` is inconsistent with enforcing dependency checking

**URL:** https://discourse.cmake.org/t/package-config-generated-by-install-export-is-inconsistent-with-enforcing-dependency-checking/5661
**Category:** Development
**Created:** [May 12, 2022, 1:10pm UTC](https://discourse.cmake.org/t/package-config-generated-by-install-export-is-inconsistent-with-enforcing-dependency-checking/5661 "2022-05-12T13:10:46Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![dbahadir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dbahadir/32/197_2.png) [@dbahadir](https://discourse.cmake.org/u/dbahadir)
#### Post date: [May 12, 2022, 1:10pm UTC](https://discourse.cmake.org/t/package-config-generated-by-install-export-is-inconsistent-with-enforcing-dependency-checking/5661/1 "2022-05-12T13:10:46Z")

</div>

## Introduction:

When installing an export-set using `install(EXPORT)` a package-config script is generated which, when loaded via a `find_package` call, creates imported targets and also sets their `INTERFACE_LINK_LIBRARIES` property.

#### case 1:

If the `INTERFACE_LINK_LIBRARIES` property contains dependencies to targets that have been imported (e.g. by a call to `find_package`) during build-time, then that generated package-config script does not check if these dependency targets exist when it is loaded by `find_package`.

At the end of the generated package-config you can find the following comment:

```cmake
# This file does not depend on other imported targets which have
# been exported from the same project but in a separate export set.

```

#### case 2:

However, if the `INTERFACE_LINK_LIBRARIES` contains dependencies to targets that themselves are also built and exported in another export-set, then the generated package-config script checks that these dependency targets already exist and fails the current `find_package` call if they are not.

At the end of the generated package-config you can find the following code instead of the comment from case 1:

```cmake
# Make sure the targets which have been exported in some other
# export set exist.
unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)
foreach(_target "dependency1" "dependency2" )
  if(NOT TARGET "${_target}" )
    set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets} ${_target}")
  endif()
endforeach()

if(DEFINED ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)
  if(CMAKE_FIND_PACKAGE_NAME)
    set( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)
    set( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "The following imported targets are referenced, but are missing: ${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}")
  else()
    message(FATAL_ERROR "The following imported targets are referenced, but are missing: ${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}")
  endif()
endif()
unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)

```

## Observation:

Note, the exact wording of the comment in case 1: it talks about targets which have been exported **from the same project** (but in some other export set).

I can understand this reasoning. Targets from the same project probably have something in common and therefore might be expected to be installed together, especially if they depend on each other.

However, the check in case 2 is **always** generated for all dependencies that were built together, regardless of the project they belong to.

## Hypothesis:

Either the generated comment in case 1 is misleading or the check in case 2 should not be generated in all cases.

## Suggestion:

Whether the check from case 2 should be generated for all dependencies (as currently) or only for the ones from the same project, **I would prefer to have some mechanism to disable this check.**  
Maybe some variable that is checked and only if it evaluates to `TRUE` should the specific check be done.

That would allow to introduce the required dependencies after `find_package` (successfully) returns which is a valid use-case, especially if `find_package` is called recursively to find indirect dependencies / components.  
Otherwise, the (indirect) dependencies and their order has to be known at the time `find_package` is called for one (direct) dependency.

Of course, that problem currently only manifests if the check is in the generated package-config, which is the case if all dependencies are built monolithically.

## Example for reproduction:

Possibly, I want to use `find_package` to find some dependency and use the pre-built and already installed one and only fall back to building it myself via `add_subdirectory` if I am unable to find it.  
That would generate different package-config scripts, whether I found a pre-built dependency or had to build it myself:

#### source1/source1.cpp:

```cpp
int source1() { return 1; }

```

#### source1/source2/source2.cpp:

```cpp
int source2() { return 2; }

```

#### source1/CMakeLists.txt:

```cmake
cmake_minimum_required( VERSION 3.23 )
project( lib1 VERSION 1.0.0 )

# Prefer pre-built dependency and fall back to building it ourselves.
if (NOT TARGET common::lib2)
    find_package( lib2 )
    if (NOT lib2_FOUND)
        add_subdirectory( source2 )
    endif()
endif()

# Build lib1.
add_library( ${PROJECT_NAME} SHARED )
add_library( common::${PROJECT_NAME} ALIAS ${PROJECT_NAME} )
target_sources( ${PROJECT_NAME} PRIVATE source1.cpp )
target_link_libraries( ${PROJECT_NAME} PUBLIC common::lib2 )

# Install lib1 and its package-config script.
install( TARGETS ${PROJECT_NAME}
    EXPORT ${PROJECT_NAME}_exportset
    COMPONENT ${PROJECT_NAME}
)
install( EXPORT ${PROJECT_NAME}_exportset
    DESTINATION lib/cmake/${PROJECT_NAME}-${PROJECT_VERSION}
    NAMESPACE common::
    COMPONENT ${PROJECT_NAME}
    FILE ${PROJECT_NAME}-config.cmake
)

```

#### source1/source2/CMakeLists.txt:

```cmake
cmake_minimum_required( VERSION 3.23 )
project( lib2 VERSION 2.0.0 )

# Build lib2.
add_library( ${PROJECT_NAME} SHARED )
add_library( common::${PROJECT_NAME} ALIAS ${PROJECT_NAME} )
target_sources( ${PROJECT_NAME} PRIVATE source2.cpp )

# Install lib2 and its package-config script.
install( TARGETS ${PROJECT_NAME}
    EXPORT ${PROJECT_NAME}_exportset
    COMPONENT ${PROJECT_NAME}
)
install( EXPORT ${PROJECT_NAME}_exportset
    DESTINATION lib/cmake/${PROJECT_NAME}-${PROJECT_VERSION}
    NAMESPACE common::
    COMPONENT ${PROJECT_NAME}
    FILE ${PROJECT_NAME}-config.cmake
)

```

#### Build like so:

```auto
# Build and install only lib2:
cmake -S source1/source2 -B build2-only && cmake --build build2-only && cmake --install build2-only --component lib2 --prefix installed2-only

# Build and install only lib1, using pre-built lib2:
lib2_DIR=installed2-only cmake -S source1 -B build1-only && cmake --build build1-only && cmake --install build1-only --component lib1 --prefix installed1-only

# Build and install lib1 and lib2:
cmake -S source1 -B build-both && cmake --build build-both && cmake --install build-both --component lib1 --prefix installed-both && cmake --install build-both --component lib1 --prefix installed-both

```

You will notice that the two package-config scripts for `lib1`,

- `installed1-only/lib/cmake/lib1-1.0.0/lib1-config.cmake` and
- `installed-both/lib/cmake/lib1-1.0.0/lib1-config.cmake`

are not identically but only differ in the (absence of) the dependency check.

---

<div class="post-metadata">

### Author: ![dbahadir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dbahadir/32/197_2.png) [@dbahadir](https://discourse.cmake.org/u/dbahadir)
#### Post date: [May 12, 2022, 1:56pm UTC](https://discourse.cmake.org/t/package-config-generated-by-install-export-is-inconsistent-with-enforcing-dependency-checking/5661/2 "2022-05-12T13:56:10Z")

</div>

Mmhhh…, seeing this post now, this probably better belongs into a Gitlab issue!?

---

<div class="post-metadata">

### Author: ![dbahadir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dbahadir/32/197_2.png) [@dbahadir](https://discourse.cmake.org/u/dbahadir)
#### Post date: [May 12, 2022, 2:59pm UTC](https://discourse.cmake.org/t/package-config-generated-by-install-export-is-inconsistent-with-enforcing-dependency-checking/5661/3 "2022-05-12T14:59:51Z")

</div>

The corresponding Gitlab issue is here: [https://gitlab.kitware.com/cmake/cmake/-/issues/23507](https://gitlab.kitware.com/cmake/cmake/-/issues/23507)
