CMake:如果你需要指定CMAKE_MODULE_PATH,那么find_package()有什么用?

我正在尝试使用CMake来获得一个跨平台的构build系统。 现在这个软件有一些依赖关系。 我自己编译它们,并将它们安装在我的系统上。

一些已安装的示例文件:

-- 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文件并在系统的库之后search并定义一些像SomeLib_FOUND等variables。

我的CMakeLists.txt包含这样的东西:

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

第一个命令定义了在Find*.cmake之后CMakesearch的Find*.cmake并且我添加了SomeLib所在的目录,所以find_package()按预期工作。

但是这find_package() ,因为find_package()存在的原因之一就是find_package()非交叉平台的硬编码path。

这通常如何完成? 我是否应该将SomeLibcmake/目录SomeLib到我的项目中并相对设置CMAKE_MODULE_PATH

命令find_package有两种模式: Module模式和Config模式。 当您实际需要Config模式时,您正尝试使用Module模式。

模块模式

Find<package>.cmake位于您的项目中的Find<package>.cmake文件。 像这样的东西:

 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_MODULE_PATH具有高优先级,当您需要重写标准的Find<package>.cmake文件时, CMAKE_MODULE_PATH可能是有用的。

configuration模式(安装)

<package>Config.cmake文件位于外部 ,由其他项目(例如Foo )的install命令生成。

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) 

configuration文件的简化版本:

 > 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 -- Install configuration: "" -- Installing: /usr/local/include/Foo.hpp -- Installing: /usr/local/lib/libfoo.a -- Installing: /usr/local/lib/cmake/Foo/FooConfig.cmake 

configuration模式(使用)

使用find_package(... CONFIG)FooConfig.cmake与导入的目标foo包含FooConfig.cmake

 > 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 

请注意,导入的目标是高度可configuration的。 看到我的答案 。

更新

这通常如何完成? 我是否应该将SomeLib的cmake/目录复制到我的项目中并相对设置CMAKE_MODULE_PATH?

如果你不相信CMake拥有这个模块,那么 – 是的,那样做 。 这就是我所做的一个后备。

请注意, FindFoo.cmake模块每个都是平台依赖和平台独立之间的桥梁 – 它们查看各种平台特定的位置以获取名称与平台无关的variables中的path。

不需要指定模块path本身。 CMake自带一套内置的find_package脚本,它们的位置在默认的CMAKE_MODULE_PATH中。

已被CMake化的依赖项目的更正常使用情况是使用CMake的external_project命令,然后在子项目中包含Use [Project] .cmake文件。 如果您只需要查找[Project] .cmake脚本,请将其从子项目中复制到您自己的项目源代码中,然后不需要增加CMAKE_MODULE_PATH以在系统级别查找子项目。