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。
这通常如何完成? 我是否应该将SomeLib
的cmake/
目录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以在系统级别查找子项目。