What Is The Right Place for Findxxx.Cmake Files for Locally Compiled Libs

What is the right place for FindXXX.cmake files for locally compiled libs?

See the comments in the CMake documentation for the "find_package" command:

http://cmake.org/cmake/help/v2.8.8/cmake.html#command:find_package

It speaks of writing a "project-config" file, and where to install it, such that find_package(Eigen3) will work without having a FindEigen3.cmake find module... It is verbose, but the information is in there.

See also user contributed wiki pages such as this one:

https://gitlab.kitware.com/cmake/community/wikis/doc/tutorials/How-to-create-a-ProjectConfig.cmake-file

Custom path for my libraries for find_library

Use CMAKE_PREFIX_PATH to indicate paths where find_library, find_path et al. should have a look (documentation)

Stuff like PNGDIR should no longer be used and is considered legacy that is kept for backwards compatibility. Patches for FindXXX provided by CMake to add XXX_DIR or XXX_ROOT are rejected by the CMake developers.

What use is find_package() when you need to specify CMAKE_MODULE_PATH?

Command find_package has two modes: Module mode and Config mode. You are trying to
use Module mode when you actually need Config mode.

Module mode

Find<package>.cmake file located within your project. Something like this:

CMakeLists.txt
cmake/FindFoo.cmake
cmake/FindBoo.cmake

CMakeLists.txt content:

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
find_package(Foo REQUIRED) # FOO_INCLUDE_DIR, FOO_LIBRARIES
find_package(Boo REQUIRED) # BOO_INCLUDE_DIR, BOO_LIBRARIES

include_directories("${FOO_INCLUDE_DIR}")
include_directories("${BOO_INCLUDE_DIR}")
add_executable(Bar Bar.hpp Bar.cpp)
target_link_libraries(Bar ${FOO_LIBRARIES} ${BOO_LIBRARIES})

Note that CMAKE_MODULE_PATH has high priority and may be usefull when you need to rewrite standard Find<package>.cmake file.

Config mode (install)

<package>Config.cmake file located outside and produced by install
command of other project (Foo for example).

foo library:

> cat CMakeLists.txt 
cmake_minimum_required(VERSION 2.8)
project(Foo)

add_library(foo Foo.hpp Foo.cpp)
install(FILES Foo.hpp DESTINATION include)
install(TARGETS foo DESTINATION lib)
install(FILES FooConfig.cmake DESTINATION lib/cmake/Foo)

Simplified version of config file:

> cat FooConfig.cmake 
add_library(foo STATIC IMPORTED)
find_library(FOO_LIBRARY_PATH foo HINTS "${CMAKE_CURRENT_LIST_DIR}/../../")
set_target_properties(foo PROPERTIES IMPORTED_LOCATION "${FOO_LIBRARY_PATH}")

By default project installed in CMAKE_INSTALL_PREFIX directory:

> cmake -H. -B_builds
> cmake --build _builds --target install
-- Install configuration: ""
-- Installing: /usr/local/include/Foo.hpp
-- Installing: /usr/local/lib/libfoo.a
-- Installing: /usr/local/lib/cmake/Foo/FooConfig.cmake

Config mode (use)

Use find_package(... CONFIG) to include FooConfig.cmake with imported target foo:

> cat CMakeLists.txt 
cmake_minimum_required(VERSION 2.8)
project(Boo)

# import library target `foo`
find_package(Foo CONFIG REQUIRED)

add_executable(boo Boo.cpp Boo.hpp)
target_link_libraries(boo foo)
> cmake -H. -B_builds -DCMAKE_VERBOSE_MAKEFILE=ON
> cmake --build _builds
Linking CXX executable Boo
/usr/bin/c++ ... -o Boo /usr/local/lib/libfoo.a

Note that imported target is highly configurable. See my answer.

Update

  • Example

Use CMake binares to build cpp projects without installing CMake

Just copied builded Modules and Templates directories from cmake-3.19.0 build directory to /usr/local/share/cmake-3.19

Cmake: find_library doesn't work but find_path does (same path)

Well, I found my problem. I feel stupid for not thinking about this sooner...

The problem was in the pre/suffixes, with some debugging output I realised that they were set for Linux instead of Windows, hence not founding the library file.

The reason for that is that in the CMakeLists.txt, the call to find_package was done before the call to project(), thus the MSVC variables was not set during the call to find_package, which led the script to believe it was called under Linux.

variable to change for finding OpenCV

As identify by Tsyvarev when you compile opencv and want to install opencv it in an different path the default one (e.g. /usr/local/ on linux) it is better to modify the variable CMAKE_INSTALL_PREFIX in the CMakeFile.txt rather than move everything after installation.

cannot find library under /usr/local/lib

Fist, Thanks @Kamil Cuk. The argument -VERBOSE=1 was so useful that I can get more detail messages that show me what happens when I use make.

The point is that when I use cmake under OSX system. It will generate a txt be named 'link.txt' which includes commands and part of it is as the following:
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk

when I delete this part, the commands will execute right. but when I add this line, the commands execute wrong. so the point is that this line maybe limited the search path of c++. Thanks @tsyvarev . You are right, -isysroot limited the c++ linkers searches /usr/local/lib.

Second, I did't find out how to remove the line -isysroot ... generated by OSX cmake. So, I need to find another solution.

When I search more information about find_package/include_directories/target_link_libraries, I found out that find_package need a FindXXX.cmake file to help it to find out the header file and libraries of the target. So I googled a FindCyptoPP.cmake file. and in this file it find out tow vars, one hold the value of cryptopp's header directory path, and one hold the value of cryptopp's library path. Then I use include_directories/target_link_libraries as following, the problem
war solved.

find_package(CryptoPP)
include_directories(${CRYPTOPP_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${CRYPTOPP_LIBRARIES})

and then when I use make -VERBOSE = 1, I fond that the output was a little different when I use the CMakeLists.txt as following:

target_link_libraries(${PROJECT_NAME} cryptopp)

When I use three lines, the output contains a line /usr/local/lib/libcryptopp.dylib. When I use one line, the output contains a line -lcryptopp.

So, with the command line -isysroot, the command line -lcryptopp will search library under the directory defined by -isysroot, and under the directory, there is no library named cryptopp but under /usr/local/lib. But with command line /usr/local/lib/libcryptopp.dylib, it gaves the absolute path of the library, so the linkes just do the linking task and need not search. Thanks @Kamil Cuk again.

Thrid, I knew include_directories/target_link_libraries are two separate steps which one is used for include header file and one is used for link libraries.

Still, there were some problems not soled:
- how to remove -isysroot?
- how to create a FindXXX.cmake file?
- how to make /usr/local/lib as a default search directory and was it a practice way to do so?

I will continue working on them, and come back a few days or weeks later.



Related Topics



Leave a reply



Submit