且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

CMake:什么用途是find_package()如果你需要指定CMAKE_MODULE_PATH无论如何?

更新时间:2023-12-04 08:10:46

命令 find_package 模块模式和配置模式。您实际需要配置模式时,尝试
使用模块模式。



模块模式



查找位于的< package> .cmake 在之内。像这样:

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

CMakeLists.txt 内容:

 列表(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})

CMAKE_MODULE_PATH 具有高优先级,并且当您需要重写标准查找< package> .cmake 文件时, p>

配置模式(安装)



< package> Config.cmake $ c $ $ $ c>)。



foo

 > 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)

配置文件的简化版本:

 > 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 })

默认情况下,项目安装在 CMAKE_INSTALL_PREFIX 目录:

 > cmake -H。 -B_builds 
> cmake --build _builds --target install
- 安装配置:
- 安装:/usr/local/include/Foo.hpp
- 安装:/ usr / local /lib/libfoo.a
- 安装:/usr/local/lib/cmake/Foo/FooConfig.cmake



配置模式(使用)



使用 find_package(... CONFIG) FooConfig.cmake 与导入目标 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
链接CXX可执行文件Boo
/ usr / bin / c ++ ... -o Boo /usr/local/lib/libfoo.a

请注意,导入的目标是高度可配置的。请参阅我的回答



更新




I'm trying to get a cross-plattform build system working using CMake. Now the software has a few dependencies. I compiled them myself and installed them on my system.

Some example files which got installed:

-- Installing: /usr/local/share/SomeLib/SomeDir/somefile
-- Installing: /usr/local/share/SomeLib/SomeDir/someotherfile
-- Installing: /usr/local/lib/SomeLib/somesharedlibrary
-- Installing: /usr/local/lib/SomeLib/cmake/FindSomeLib.cmake
-- Installing: /usr/local/lib/SomeLib/cmake/HelperFile.cmake

Now CMake has a find_package() which opens a Find*.cmake file and searches after the library on the system and defines some variables like SomeLib_FOUND etc.

My CMakeLists.txt contains something like this:

set(CMAKE_MODULE_PATH "/usr/local/lib/SomeLib/cmake/;${CMAKE_MODULE_PATH}")
find_package(SomeLib REQUIRED)

The first command defines where CMake searches after the Find*.cmake and I added the directory of SomeLib where the FindSomeLib.cmake can be found, so find_package() works as expected.

But this is kind of weird because one of the reasons why find_package() exists is to get away from non-cross-plattform hard coded paths.

How is this usually done? Should I copy the cmake/ directory of SomeLib into my project and set the CMAKE_MODULE_PATH relatively?

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