Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Debug CMake find_library

Tags:

cmake

Is it possible to debug find_library from CMake?

What I want is a list of considered paths. My use case is a call like

find_library (FOO_LIBRARY
              NAMES foo foo.so.0)

and there is /lib64/libfoo.so.0 on my system. However CMake does not find it. I checked that FIND_LIBRARY_USE_LIB64_PATHS is set to TRUE.

like image 918
Flamefire Avatar asked Mar 22 '18 14:03

Flamefire


People also ask

What does Find_library do in CMake?

This command is used to find a library. A cache entry, or a normal variable if NO_CACHE is specified, named by <VAR> is created to store the result of this command. If the library is found the result is stored in the variable and the search will not be repeated unless the variable is cleared.

How do I debug CMake?

You can also start a debug session from Solution Explorer. First, switch to CMake Targets View in the Solution Explorer window. Then, right-click on an executable and select Debug. This command automatically starts debugging the selected target based on your active configuration.


2 Answers

With CMake 3.17 this got added:

The “CMAKE_FIND_DEBUG_MODE” variable was introduced to print extra find call information during the cmake run to standard error. Output is designed for human consumption and not for parsing.

So you pass either -DCMAKE_FIND_DEBUG_MODE=true or --debug-find to your CMake command.

Here is an example output when searching for libFOO:

find_library considered the following locations:

/usr/local/lib64/(lib)FOO(\.so|\.a)
/usr/local/lib/(lib)FOO(\.so|\.a)
/usr/local/lib64/(lib)FOO(\.so|\.a)
/usr/local/lib/(lib)FOO(\.so|\.a)
/usr/local/lib64/(lib)FOO(\.so|\.a)
/usr/local/(lib)FOO(\.so|\.a)
/usr/lib64/(lib)FOO(\.so|\.a)
/usr/lib/(lib)FOO(\.so|\.a)
/usr/lib64/(lib)FOO(\.so|\.a)
/usr/lib/(lib)FOO(\.so|\.a)
/usr/lib64/(lib)FOO(\.so|\.a)
/usr/(lib)FOO(\.so|\.a)
/lib64/(lib)FOO(\.so|\.a)
/lib/(lib)FOO(\.so|\.a)
/opt/(lib)FOO(\.so|\.a)

The item was not found.
like image 54
usr1234567 Avatar answered Oct 19 '22 06:10

usr1234567


I know this isn't a complete answer, but I had the same problem and found that it was necessary to add debug logging to find_library in the CMake source code. I submitted a pull request (work in progress) to add this to mainstream CMake.

I eliminated some possible sources of errors by logging an error message with some relevant details if find_library fails, like this:

    set(libssl_names
            ssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
            ssl${_OPENSSL_MSVC_RT_MODE}
            ssl
            ssleay32${_OPENSSL_MSVC_RT_MODE}
            ssleay32
    )

    find_library(SSL_EAY_DEBUG
            NAMES ${libssl_names}
            NAMES_PER_DIR
            PATHS ${OPENSSL_ROOT_DIR}
            PATH_SUFFIXES ${_OPENSSL_PATH_SUFFIXES}
            NO_DEFAULT_PATH
    )

    if(NOT SSL_EAY_DEBUG)
            message(FATAL_ERROR "OPENSSL_ROOT_DIR is set to '${OPENSSL_ROOT_DIR}', but did not find any file matching ${OPENSSL_ROOT_DIR}/{${_OPENSSL_PATH_SUFFIXES}}/${CMAKE_FIND_LIBRARY_PREFIXES}{${libssl_names}}${CMAKE_FIND_LIBRARY_SUFFIXES}")
    endif()

Which outputs something like:

CMake Error at CMakeLists.txt:526 (message):
  OPENSSL_ROOT_DIR is set to '../../Install/openssl/', but did not find any
  file matching
  ../../Install/openssl//{lib/VC/static;VC/static;lib}/lib{ssl64MT;sslMT;ssl;ssleay32MT;ssleay32}.a

Apart from semicolons (instead of commas) in the {braced} portions of the above pattern, and regexes if multiple CMAKE_FIND_LIBRARY_SUFFIXES are configured (e.g. .lib .a on Windows), this is the correct form for shell expansion to a list of paths, which you can pass to ls to check for their existence:

$ ls ../../Install/openssl//{lib/VC/static,VC/static,lib}/lib{ssl64MT,sslMT,ssl,ssleay32MT,ssleay32}.a
ls: ../../Install/openssl//VC/static/libssl.a: No such file or directory
ls: ../../Install/openssl//VC/static/libssl64MT.a: No such file or directory
ls: ../../Install/openssl//VC/static/libsslMT.a: No such file or directory
ls: ../../Install/openssl//VC/static/libssleay32.a: No such file or directory
ls: ../../Install/openssl//VC/static/libssleay32MT.a: No such file or directory
ls: ../../Install/openssl//lib/VC/static/libssl.a: No such file or directory
ls: ../../Install/openssl//lib/VC/static/libssl64MT.a: No such file or directory
ls: ../../Install/openssl//lib/VC/static/libsslMT.a: No such file or directory
ls: ../../Install/openssl//lib/VC/static/libssleay32.a: No such file or directory
ls: ../../Install/openssl//lib/VC/static/libssleay32MT.a: No such file or directory
ls: ../../Install/openssl//lib/libssl64MT.a: No such file or directory
ls: ../../Install/openssl//lib/libsslMT.a: No such file or directory
ls: ../../Install/openssl//lib/libssleay32.a: No such file or directory
ls: ../../Install/openssl//lib/libssleay32MT.a: No such file or directory
../../Install/openssl//lib/libssl.a

It's not obvious (at least to me) that:

  • relative paths (like ../../Install above) are actually relative to the original source directory (not the current project build directory, which CMake calls CMAKE_BINARY_DIR. (So you should run ls from there, not your build directory).

  • FIND_LIBRARY_USE_LIB64_PATHS, which is often ON by default, results in your original paths being replaced by mangled ones (lib -> lib64) (not just supplemented by additional search paths, but completely replaced).

  • Other, even less well-known properties such as FIND_LIBRARY_USE_LIB32_PATHS result in similar mangling (lib -> lib32).

  • This mangling can be disabled with set(CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX "").

like image 42
qris Avatar answered Oct 19 '22 05:10

qris