如果仍然需要指定CMAKE_模块路径,那么find_package()有什么用处?
我正在尝试使用CMake实现一个跨平台的构建系统。现在该软件有一些依赖项。我自己编译并安装在我的系统上 已安装的一些示例文件:如果仍然需要指定CMAKE_模块路径,那么find_package()有什么用处?,cmake,Cmake,我正在尝试使用CMake实现一个跨平台的构建系统。现在该软件有一些依赖项。我自己编译并安装在我的系统上 已安装的一些示例文件: -- Installing: /usr/local/share/SomeLib/SomeDir/somefile -- Installing: /usr/local/share/SomeLib/SomeDir/someotherfile -- Installing: /usr/local/lib/SomeLib/somesharedlibrary -- Installi
-- 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
现在,CMake有一个find_package()
,它打开一个find*.CMake
文件,搜索系统上的库,并定义一些变量,如SomeLib_FOUND
等
My CMakeLists.txt包含以下内容:
set(CMAKE_MODULE_PATH "/usr/local/lib/SomeLib/cmake/;${CMAKE_MODULE_PATH}")
find_package(SomeLib REQUIRED)
CMakeLists.txt
cmake/FindFoo.cmake
cmake/FindBoo.cmake
第一个命令定义了CMake在Find*.CMake
之后搜索的位置,我添加了SomeLib
目录,在那里可以找到FindSomeLib.CMake
,因此Find_package()
起作用
正如所料
但这有点奇怪,因为find_package()
存在的原因之一是为了避开非跨平台硬编码路径
这通常是怎么做的?我是否应该将SomeLib
的cmake/
目录复制到我的项目中,并相对地设置cmake\u模块路径?您不需要指定模块路径本身。CMake自带一组内置的find_包脚本,它们的位置在默认的CMake_模块路径中
对于已被CMakeified的依赖项目,更常见的用例是使用CMake的external_project命令,然后包含子项目中的use[project].CMake文件。如果您只需要Find[Project].cmake脚本,请将其从子项目复制到您自己项目的源代码中,这样您就不需要为了在系统级查找子项目而增加cmake_MODULE_路径。命令查找包
有两种模式:模块
模式和配置
模式。你是想
当您实际需要Config
模式时,请使用Module
模式
模块模式
Find.cmake
文件位于项目中的。大概是这样的:
set(CMAKE_MODULE_PATH "/usr/local/lib/SomeLib/cmake/;${CMAKE_MODULE_PATH}")
find_package(SomeLib REQUIRED)
CMakeLists.txt
cmake/FindFoo.cmake
cmake/FindBoo.cmake
CMakeLists.txt
内容:
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})
请注意,CMAKE\u模块\u路径
具有高优先级,当您需要重写标准Find.CMAKE
文件时,它可能会有用
配置模式(安装)
Config.cmake
文件位于外部并由install
其他项目的命令(例如Foo
)
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\u INSTALL\u PREFIX
目录中:
> 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
配置模式(使用)
使用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
Linking CXX executable Boo
/usr/bin/c++ ... -o Boo /usr/local/lib/libfoo.a
请注意,导入的目标是高度可配置的。看我的
更新
这通常是怎么做的?我是否应该将SomeLib的cmake/
目录复制到我的项目中,并相对地设置cmake\u模块路径
如果您不相信CMake拥有该模块,那么-是的,这样做-将find_SomeLib.CMake
及其依赖项复制到CMake/
目录中。这就是我作为后备力量所做的。但这是一个丑陋的解决方案
请注意,FindFoo.cmake
模块都是平台依赖性和平台独立性之间的桥梁-它们在不同的平台特定位置查找,以获取名称与平台无关的变量路径。如果您运行cmake
生成SomeLib
(作为超级构建的一部分),考虑使用。这不需要硬编码的路径,并且是跨平台的。在Windows(包括明文64)中,它通过注册表工作。如果您检查安装前缀列表是如何通过命令的<代码> CONFIG模式构建的,那么您将看到用户包注册表是元素之一。< /P>
简要操作指南
将外部项目外部所需的SomeLib
的目标添加到创建它们的CMakeLists.txt
文件中的导出集中,从而将它们关联起来:
add_library(thingInSomeLib ...)
install(TARGETS thingInSomeLib Export SomeLib-export DESTINATION lib)
在其${cmake\u CURRENT\u BUILD\u DIR}
中为SomeLib
创建一个XXXConfig.cmake
文件,并通过向与SomeLib
关联的CMakeLists.txt
添加两个调用,将此位置存储在用户包注册表中:
export(EXPORT SomeLib-export NAMESPACE SomeLib:: FILE SomeLibConfig.cmake) # Create SomeLibConfig.cmake
export(PACKAGE SomeLib) # Store location of SomeLibConfig.cmake
在依赖于SomeLib
的项目的CMakeLists.txt
文件中发出find_包(需要SomeLib)
命令,而不使用CMAKE_模块路径修补“非跨平台硬编码路径”
何时可能是正确的方法
这种方法可能最适合于您永远不会在构建目录的下游使用软件的情况(例如,您正在交叉编译并且从未在您的机器上安装任何东西,或者您正在构建软件只是为了在构建目录中运行测试),因为它会在“构建”中创建指向.cmake文件的链接输出,这可能是临时的
但如果您从未在工作流中实际安装SomeLib
,请调用EXPORT(PACKAGE)
允许您避免硬编码路径。当然,如果您正在安装SomeLib
,您可能知道您的平台,CMAKE_MODULE_path
,等等,因此@user2288008的优秀答案将让您了解。我觉得这种模式非常奇怪。使用CMAKE的库不应该公开其“查找”模块你是怎么找到“SomeLib”的?它是哪一个库?类似的东西是在中完成的。它是食人魔。你链接到的部分提到:“既然CMake(目前)没有发布它,你必须在你的项目中发布它。”这就是我在flvmeta中找到Libyml所做的(见)。模块路径指向此目录