Does `find_dependency` also export target?

Hi all,

I am playing with these two blocks of CMake code (I replaced some target names with ...).

  1. find_dependency
include(CMakeFindDependencyMacro)
find_dependency(nlohmann_json)
export(TARGETS ${MLIR_EXPORTS} ... FILE ${catalyst_cmake_builddir}/CatalystTargets.cmake)
  1. find_package
find_package(nlohmann_json CONFIG REQUIRED PATHS ${nlohmann_json_BINARY_DIR})
export(TARGETS ${MLIR_EXPORTS} ... FILE ${catalyst_cmake_builddir}/CatalystTargets.cmake)

The first block compiles fine, but the second block complains of nlohmann_json not being exported. nlohmann_json is retrieved via FetchContent in an outer CMakeLists.txt.

Shouldn’t find_dependency be just a light wrapper around find_package?
Or is it doing something else?
I’ve read about EXPORT_PACKAGE_DEPENDENCIES but that option doesn’t seem to be used in my codebase.

Many thanks,
Roberto.

see FindDependency docs.

Both blocks do not find the package, because it is not yet installed I guess.

These are the outputs I get for 3 different cases.

I am looking for an explanation about cases 2 and 3. Why DON’T I need to export nlohmann_json after finding it via find_dependency but I DO need to export it after finding it via find_package? It looks like find_dependency is doing something else apart from merely light wrapping find_package.

Case 1
nlohmann_json package is found.
It is NOT included in the export TARGETS list.
It is NOT found by other targets.

Code

find_package(nlohmann_json CONFIG REQUIRED PATHS ${nlohmann_json_BINARY_DIR})
export(TARGETS ${MLIR_EXPORTS} QECUtils libstim tomlplusplus_tomlplusplus FILE ${catalyst_cmake_builddir}/CatalystTargets.cmake)

Output
Errors: targets cannot find nlohmann_json export.
It does not buiild.

CMake Error in cmake/modules/CMakeLists.txt:
  export called with target "qec-transforms" which requires target
  "nlohmann_json" that is not in any export set.


CMake Error in cmake/modules/CMakeLists.txt:
  export called with target "ion-transforms" which requires target
  "nlohmann_json" that is not in any export set.

Case 2
nlohmann_json package is found.
It is included in the export TARGETS list.
It is found by other targets.

Code

find_package(nlohmann_json CONFIG REQUIRED PATHS ${nlohmann_json_BINARY_DIR})
export(TARGETS ${MLIR_EXPORTS} nlohmann_json QECUtils libstim tomlplusplus_tomlplusplus FILE ${catalyst_cmake_builddir}/CatalystTargets.cmake)

Output
No warnings, no errors.
It builds.

Case 3
nlohmann_json package is found via find_dependency.
It is NOT included in the export TARGETS list.
It is found by other targets.

Code

include(CMakeFindDependencyMacro)
find_dependency(nlohmann_json)
export(TARGETS ${MLIR_EXPORTS} QECUtils libstim tomlplusplus_tomlplusplus FILE ${catalyst_cmake_builddir}/CatalystTargets.cmake)

Output
Warning: find_dependency cannot find the nlohmann_json config file.
It builds.

CMake Warning at /usr/share/cmake-3.28/Modules/CMakeFindDependencyMacro.cmake:76 (find_package):
  By not providing "Findnlohmann_json.cmake" in CMAKE_MODULE_PATH this
  project has asked CMake to find a package configuration file provided by
  "nlohmann_json", but CMake did not find one.

  Could not find a package configuration file provided by "nlohmann_json"
  with any of the following names:

    nlohmann_jsonConfig.cmake
    nlohmann_json-config.cmake

  Add the installation prefix of "nlohmann_json" to CMAKE_PREFIX_PATH or set
  "nlohmann_json_DIR" to a directory containing one of the above files.  If
  "nlohmann_json" provides a separate development package or SDK, be sure it
  has been installed.
Call Stack (most recent call first):
  cmake/modules/CMakeLists.txt:39 (find_dependency)

Case 3 doesn’t perform the export() at all, find_dependency() is a macro which calls return() if it fails to find the desired target. The processing of the CML ends at that point, the export() is never reached.

You should never use find_dependency() inside a CML like this, it is only intended to be called inside a CMake package configuration file

1 Like

Many thanks for the explanation @vito.gamberini.

Do you see any problems using the code from Case 2?

The use of export() at all is at little concerning. Assuming you have a valid use case for consuming non-utility targets from a build tree, it’s fine. LLVM-adjacent things like MLIR are always weird about their desire to be consumed from build trees. It’s not idiomatic CMake exactly, but it might be idiomatic for LLVM-based code.