8

When a library defines a build with CMake and goes through the trouble of building an install package for itself, there will be a XXXConfig.cmake.

If a library doesn't have a way to export it's targets to CMake, CMake tries to bridge the gap by providing FindXXX.cmake scripts that attempt to locate such libraries.

In the docs, FindXXX.cmake (module mode), is attempted first, and only if that fails does it attempt to use XXXConfig.cmake (config mode). But this seems like a really backwards to me.

The problem is, for example, I have built CURL from source, and the ConfigXXX produces a different target name than FindXXX, so, when trying to use it, it fails because FindXXX took responsibility for the find_package request and loaded a different target name than what I was expecting.

Can I at least tell CMake somehow to do things the other way around? Config mode first.

I know I can disable module mode entirely, but I'd rather have it as a fallback option.

johnb003
  • 1,821
  • 16
  • 30

3 Answers3

7

Just use find_package with CONFIG mode, check its result, and, if result is false, repeat the call with MODULE mode:

# First time do not use common *REQUIRED* but use QUIET for do not output error messages on fail.
find_package(XXX CONFIG QUIET)
if(NOT XXX_FOUND)
    # Previous call has been failed. Fallback with MODULE mode.
    find_package(XXX MODULE REQUIRED) # Now it is OK to use REQUIRED if needed.
    # ... There could be additional actions for wrap result "as if" CONFIG mode.
endif()
# ... use XXX
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • I guess this would be a good macro to write, overriding find_package, to keep it looking idiomatic? – johnb003 Jun 22 '18 at 16:15
  • If both `CONFIG` and `MODULE` mode results has the same format, then the macro could be easy to write. But if actions described by `There could be additional actions for wrap result "as if" CONFIG mode.` are really needed.. it could be non-trivial to implement a generic macro. In any case, if you find this feature for your project(s) useful, just write the macro and use it. – Tsyvarev Jun 22 '18 at 16:20
  • It sounds good. At the moment, I've got like 15 find_package(lib CONFIG REQUIRED) calls, and it feels like this just cuts off the potential to find things on the system if they're missing from the install. (Without the workaround you described) – johnb003 Jun 22 '18 at 16:26
7

New in version 3.15:

Set CMAKE_FIND_PACKAGE_PREFER_CONFIG to TRUE to tell find_package() to first search using Config mode before falling back to Module mode.

References: 1, 2.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
user12129795
  • 86
  • 1
  • 1
1

You can try this find_package(XXX CONFIG REQUIRED).

see the link: CMake: Of what use is find_package() if you need to specify CMAKE_MODULE_PATH anyway?

Wei Guo
  • 544
  • 3
  • 15
  • Yes, "CONFIG" allows me to override the search behavior, but I was hoping to still have a fallback on MODULE mode. I liked the link though. – johnb003 Jun 22 '18 at 16:46
  • For one thing, most libraries just "find_package(lib REQUIRED)", which don't specify module or config, but if I'm providing "CMAKE_MODULE_PATH" and there's one on the system, I have no way of overriding that without editing that 3rd party cmake. – johnb003 Jun 25 '18 at 18:02
  • For CMake 3.10.2, this works! First this looks for a XXXConfig.cmake in XXX_DIR; If no such config is found, it reverts back to the Modul mode (i.e. look for&execute FindXXX.cmake within the CMAKE_MODULE_PATH) – Oliver Zendel Apr 29 '19 at 13:24