Questions about `--find-package` CLI & MSVC

The output of cmake --help says

  --find-package               = Legacy pkg-config like mode.  Do not use.

However, incorrect CMake metadata it is one of the possible failure modes in integration work like conda-forge does (not least since some packages contain some unholy mess of build hacks, mostly upstream directly, or occasionally also in conda-forge itself for various reasons).

To catch such failures early, I want to test that the packaged lib/cmake/<pkg>/<pkg>Config.cmake etc. work correctly. A bit of googling later, I found I could successfully do

cmake --find-package -DNAME=zstd -DLANGUAGE=C -DMODE=EXIST -DCOMPILER_ID=GNU    # [linux]
cmake --find-package -DNAME=zstd -DLANGUAGE=C -DMODE=EXIST -DCOMPILER_ID=Clang  # [osx]

First question is: what is a non-legacy way to do the same thing?

The second question is why the windows version

cmake --find-package -DNAME=zstd -DLANGUAGE=C -DMODE=EXIST -DCOMPILER_ID=MSVC  # [win]

fails with:

CMake Error at D:/bld/zstd-split_1659310630313/_test_env/Library/share/cmake-3.23/Modules/Platform/Windows-MSVC.cmake:67 (message):
  MSVC compiler version not detected properly:
Call Stack (most recent call first):
  D:/bld/zstd-split_1659310630313/_test_env/Library/share/cmake-3.23/Modules/Platform/Windows-MSVC-C.cmake:1 (include)
  D:/bld/zstd-split_1659310630313/_test_env/Library/share/cmake-3.23/Modules/CMakeCInformation.cmake:48 (include)
  D:/bld/zstd-split_1659310630313/_test_env/Library/share/cmake-3.23/Modules/CMakeFindPackageMode.cmake:116 (include)

CMake Error: Run 'cmake --help' for all supported options.

Unfortunately, the recommended-by-the-error cmake --help does not show any useful way of what to change (except a list of generators, but adding -GNinja also doesn’t change anything either).

Thanks in advance for any help on this. :slight_smile:

There’s no replacement for --find-package because it doesn’t work with targets all that well.

As for MSVC, you need to call it from a developer prompt or load vcvarsall.bat manually. It works with the other compilers because they “just work” with the path. MSVC doesn’t work that way, but CMake always assumes that the compiler is usable in the given environment (except for IDE generators where it is assumed the IDE knows how to use the toolchain itself…which is usually true).

Thanks for the response!

OK. But cmake will presumably still produce metadata files that will be used internally whenever find_package is called. As an integrator (especially a cross-platform one), it’s essential that there’s some way to test that this metadata is correct – unfortunately we don’t have the luxury of letting everything be handled by CMake; some projects don’t have native CMake integration, or it doesn’t match how our distribution works (no static libs except in rare cases), or is flat-out wrong, or, or, or…, so this is not a hypothetical scenario.

For example, I recently encountered

CMake Error at $PREFIX/lib/cmake/zstd/zstdTargets.cmake:87 (message):
  The imported target "zstd::libzstd_static" references the file

     "$PREFIX/lib/libzstd.a"

  but this file does not exist.  Possible reasons include:
  * The file was deleted, renamed, or moved to another location.
  * An install or uninstall procedure did not complete successfully.
  * The installation package was faulty and contained
     "$PREFIX/lib/cmake/zstd/zstdTargets.cmake"
  but not all the files it references.

Call Stack (most recent call first):
  $PREFIX/lib/cmake/zstd/zstdConfig.cmake:1 (include)
  cmake/config-ix.cmake:149 (find_package)
  CMakeLists.txt:768 (include)

-- Configuring incomplete, errors occurred!

I’d like to catch this at the source (in this case the testing phase of zstd), and currently cmake --find-package fits the bill. What will I be able to use to test something like that, once --find-package is removed?

I also don’t fully understand why a compiler is necessary – couldn’t the existence of files referenced in <pkg>Targets.cmake be tested more trivially?

Add tests which perform find_package() from CMake and make small programs or whatever just by linking to the target(s) as needed. This will at least test that the CMake integration is correct. Bonus points for running the tests against an install tree and not just the build tree. As for providing the relevant information for non-CMake projects:

find_package modules can do a lot of things. For example, FindMPI ends up needing to know the compiler for $reasons. I think FindHDF5 is similar. The most robust that I’ve been able to come up with is this script which basically generates a small project and then logs the build to extract out the flags that actually matter. You might be able to do it more statically if you know there aren’t more fancy usage requirements (compile flags, link flags, etc.) or the dependency graph is “simple”.

You might be able to generate this for a given install prefix and install it as a .pc file or something for more direct usage (though your project is then non-relocatable as far as this information is related).

OK fair, but that’s a bunch more test setup than a CLI invocation. For now, I guess I’ll stay with --find-packages until it breaks…

Always :grin:

Thanks for the help!

So I tried this with our compiler setup, and despite

CALL "VC\Auxiliary\Build\vcvars64.bat" -vcvars_ver=14.16 10.0.22000.0

passing successfully

** Visual Studio 2019 Developer Command Prompt v16.11.17
** Copyright (c) 2021 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

this still runs into “MSVC compiler version not detected properly”…

This is exactly the same setup under which cmake would run in non-CLI mode as well, so it’s a bit frustrating that there’s zero info about which part of the version detection is failing, much less how to fix it.