Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cmake find_library and CMAKE_FIND_ROOT_PATH

Tags:

c++

c

cmake

In the documentation for cmake's find_library function, we have

The CMake variable CMAKE_FIND_ROOT_PATH specifies one or more directories to be prepended to all other search directories. This effectively “re-roots” the entire search under given locations. Paths which are descendants of the CMAKE_STAGING_PREFIX are excluded from this re-rooting, because that variable is always a path on the host system. By default the CMAKE_FIND_ROOT_PATH is empty.

The CMAKE_SYSROOT variable can also be used to specify exactly one directory to use as a prefix. Setting CMAKE_SYSROOT also has other effects. See the documentation for that variable for more.

These variables are especially useful when cross-compiling to point to the root directory of the target environment and CMake will search there too. By default at first the directories listed in CMAKE_FIND_ROOT_PATH are searched, then the CMAKE_SYSROOT directory is searched, and then the non-rooted directories will be searched. The default behavior can be adjusted by setting CMAKE_FIND_ROOT_PATH_MODE_LIBRARY. This behavior can be manually overridden on a per-call basis. By using CMAKE_FIND_ROOT_PATH_BOTH the search order will be as described above. If NO_CMAKE_FIND_ROOT_PATH is used then CMAKE_FIND_ROOT_PATH will not be used. If ONLY_CMAKE_FIND_ROOT_PATH is used then only the re-rooted directories and directories below CMAKE_STAGING_PREFIX will be searched.

(see http://www.cmake.org/cmake/help/v3.0/command/find_library.html)

I'm not sure how you read that, but to me, it seems implied that find_library will use CMAKE_FIND_ROOT_PATH to look for libraries. I've written the following cmakelists.txt:

cmake_minimum_required( VERSION 3.0 )

project( "cmakefindlibtest" )

message( "CMAKE_FIND_ROOT_PATH is ${CMAKE_FIND_ROOT_PATH}" )
list( APPEND CMAKE_FIND_ROOT_PATH "C:/DEV/lib/" )
message( "CMAKE_FIND_ROOT_PATH is now ${CMAKE_FIND_ROOT_PATH}" )
#find_library( punycode_library_test punycode PATHS "C:/DEV/lib" )
find_library( punycode_library_test punycode  )
message( "punycode_library_test is now ${punycode_library_test}" )

add_executable( cmakefindlibtest main.cpp )
target_link_libraries( cmakefindlibtest ${punycode_library_test} )

main.cpp is just hello world. In C:\DEV\lib, I've put a library named punycode.lib (this is on Windows). I've pointed CMAKE_FIND_ROOT_PATH to the directory. And then when I call find_library, I get:

c:\DEV\cmakefindtest\_build>cmake ..
-- Building for: Visual Studio 11 2012
CMAKE_FIND_ROOT_PATH is
CMAKE_FIND_ROOT_PATH is now C:/DEV/lib/
punycode_library_test is now punycode_library_test-NOTFOUND
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
punycode_library_test
    linked by target "cmakefindlibtest" in directory C:/DEV/cmakefindtest

-- Configuring incomplete, errors occurred!
See also "C:/DEV/cmakefindtest/_build/CMakeFiles/CMakeOutput.log".

Note that when I add the directory to the PATHS part of find_library's invocation

find_library( punycode_library_test punycode PATHS "C:/DEV/lib" )

everything works:

c:\DEV\cmakefindtest\_build>cmake ..
-- Building for: Visual Studio 11 2012
CMAKE_FIND_ROOT_PATH is
CMAKE_FIND_ROOT_PATH is now C:/DEV/lib/
punycode_library_test is now C:/DEV/lib/punycode.lib
-- Configuring done
-- Generating done
-- Build files have been written to: C:/DEV/cmakefindtest/_build

So does find_library just not use CMAKE_FIND_ROOT_PATH?

Update:

It looks like CMAKE_LIBRARY_PATH mostly does what I want it to do here, and according to http://public.kitware.com/pipermail/cmake-developers/2012-January/002850.html, it looks like that's what I should be using it for in this case anyways.

But, I'm still trying to figure out why CMAKE_FIND_ROOT_PATH doesn't work with find_library. The documentation at http://www.cmake.org/Wiki/CMake_Cross_Compiling says of CMAKE_FIND_ROOT_PATH,

this is a list of directories, each of the directories listed there will be prepended to each of the search directories of every FIND_XXX() command.

which doesn't seem to be true in this case, unless there's some sort of set-up or another variable that I've missed.

like image 637
Ted Middleton Avatar asked Oct 01 '22 09:10

Ted Middleton


2 Answers

First, CMAKE_FIND_ROOT_PATH will be prepended to a certain set of directories described in the docs of find_library. It won't be prepended to the file names you specify for find_library.

You only need to use CMAKE_FIND_ROOT_PATH for cross-compiling. For example, while find_library(.. jpeg ...) will find /usr/lib/libjpeg.so you can hijack this search with set(CMAKE_FIND_ROOT_PATH ~/my_toolchain) to find ~/my_toolchain/usr/lib/libjpeg.so instead.

Since you didn't mention you were cross-compiling what you probably need is CMAKE_PREFIX_PATH. Try set(CMAKE_PREFIX_PATH "c:/DEV") or set(CMAKE_LIBRARY_PATH "c:/DEV/lib") to make find_library search in c:/DEV/lib.

like image 133
tamas.kenez Avatar answered Oct 02 '22 23:10

tamas.kenez


I have met the same problem when doing cross-compiling of openwrt, with an external toolchain specified.

Like the problem described, I have set the CMAKE_FIND_ROOT_PATH to the toolchain's directory, but still, rpcd complains about missing crypt library.

Then I noticed this thread and figured may be it is because of implied lib search path of ./usr/lib and ./lib. As such, I changed the CMAKE_FIND_ROOT_PATH to be the sysroot of the toolchain, which includes ./usr/lib and ./lib for the target platform, then the problem is gone.

Getting back to the original problem, I think maybe if you can try to set CMAKE_FIND_ROOT_PATH to be C:/DEV, and place the library to be linked to under C:/DEV/lib.

That being said, if you are not doing a cross-compiling, this may not be the most sensible solution.

like image 20
Jing Qiu Avatar answered Oct 02 '22 22:10

Jing Qiu